看我如何進行Python對象注入利用
譯者:天鴿
預估稿費:130RMB
投稿方式:發送郵件至linwei#http://360.cn,或登陸網頁版在線投稿
簡介
在今天的 Defencely Lab 中,我們將詳細介紹和演示 Python 對象注入攻擊(Python Object Injection)的細節。整個演示將使用我們專門編寫的易受攻擊的應用程序和漏洞,源碼可以在這裡找到 - Github – Python Object Injection。
需要的基礎知識
了解基本的 OOP 概念
Python 類和對象簡介
什麼是類?
類是一個模板,你可以在其中存儲變數和方法。
什麼是對象?
對象可以是任何東西,一個類的實例,一個變數或者一個類中的函數。
讓我們來看一個實際的例子:
在這裡,你可以看到我們創建了一個名為 Test 的類實例,並將它分配給了一個名為 simpleapp 的變數,將變數 rony 的值傳遞給了該實例。
輸出如下:
simpleapp = Test(rony)n
當執行此代碼時,python 會創建一個對象,然後將我們的值傳遞給第一個參數。每當 python 創建一個對象時,__init__ 函數就會被調用。__init__ 像 python 中的構造函數一樣工作。
伴隨著我們的輸出,列印出了一個隨機的數字,這是因為我們直接列印出了實例分配的變數,以顯示 python 是如何對待一個對象的。
什麼是對象注入?
對象注入是一種應用程序級的安全漏洞,它允許攻擊者根據上下文執行嚴重的攻擊。
Python 專門將某原生模塊命名為「Pickle」,它在特定情況下容易受到對象注入攻擊。
危險發生在當用戶控制的數據被傳遞時,Python 已經在其官方文檔中指出 pickle 是一個存在風險的模塊。
我們可以將「Pickle」模塊與 PHP 中的 serialize/unserialize() 原生函數進行比較,當存在用戶輸入時該 PHP 函數也容易受到對象注入攻擊。
在 Python 中,與 PHP 不同的是,我們不需要一個魔術方法作為注入到對象的條件。
在 python 中進行序列化和反序列化僅僅是對數據的 Pickling 和 Unpickling。
除非用戶輸入的數據被傳遞到 Unpickling 的過程中,否則,Python 中數據的 Unpickling 並不一定是危險的。
下面是 Python 中 Pickled 和 Unpickled 的數據的樣子:
檢測對象注入攻擊
要實現對象注入,你必須在應用程序上執行一個白盒 Pentest。因為每當你在複雜對象上 pickling 時,Python 中的序列化數據都會帶有類名、變數和值。
Pickle 模塊提供了四種簡單和快速 pickling 和 unpickling 的方法。
dump()
dumps()
load()
loads()
您可以在 Python 官方文檔中找到它們各自的功能。
正如我已經提到的,Unpickling 數據並不一定是危險的,但如果你是在後端處理,那麼 pickling 和 unpickling 用戶輸入的數據就是危險的。永遠不要相信用戶的輸入。
如果所提供的數據是由用戶控制的,那麼很明顯會被篡改。
因此,如果你看到 pickled 的數據正在通過 HTTP 方法傳輸,則可能存在對象注入。
了解易受攻擊應用程序的工作流
文件名:pickle.py
我們將研究上述代碼,並據此實現一個對象注入。
忽略上面代碼上寫的所有內容,讓我們集中精力在三件事情上。
在這裡,arg 變數是用戶的輸入。
類 simpleApp 中的 final_workout() 方法將運行一個 python 文件。
app.secureaApp() 方法用於 unpickling 輸入的數據。
現在,讓我們更深入地了解這些方法正在扮演的角色。
simpleApp() 類中的 secureApp() 方法:
我假設你已經閱讀了 Python 的官方文檔,並且知道了這篇文章使用的所有方法的輸入輸出。
方法:
dump()
dumps()
load()
loads()
secureApp() 方法所做的是將文件名作為參數。使用 pickle 模塊的 load() 方法 Unpickling 文件中的數據,並將 unpickled 的數據賦予變數 workDone。之後該變數會作為 final_workout() 方法的參數。
我們看看 final_workout() 方法的內容。
simpleApp() 類中的 final_workout() 方法:
該方法創建一個名為 code.py 的 python 文件,將 unpickled 的數據寫入文件並運行它。
我們來看看,當使用已經生成的序列化數據來運行易受攻擊的應用程序 pickle.py 時,會發生什麼。
正如我們看到的,它列印出了序列化數據的內容,並成功運行,列印出字元串。
下面我們將學習怎樣構造自己的序列化數據,以在相同的應用程序上成功地進行對象注入。
編寫漏洞利用
現在我們知道 pickle.py 正在使用序列化的數據,因此,我們將使用 dumps() 方法 pickle 我們構造的 payload。
文件名:exploit_pickle.py
我們將序列化一條包含了編碼後系統命令的代碼, 並在它工作時對其進行測試。
現在我們就成功地注入了自己精心構造的代碼。
推薦閱讀:
※Python從零開始系列連載(10)——Python的基本運算和表達式(中)
※Python課件的中文版
※Python操作SQLite/MySQL/LMDB/LevelDB
※讓彈幕飄一會兒的Python小實驗
※Python學習如何下手?看完本文後你能明白60%