基於python的自動化代碼審計
本文通過介紹在python開發中經常出現的常規web漏洞,然后通過靜態和動態兩種方式對python代碼進行自動化審計挖掘漏洞,並且展示自動化系統在自動化審計python應用代碼的成果,本文比較長,請耐心閱讀,驚喜在后面。
從python常規漏洞來看都有一個共同點,那就是危險函數中使用了可控參數,
-
如system函數中使用到的(‘mv %s’% filename),
-
如execute函數中使用到的username參數,
-
如HttpResponse中使用到的nickname參數,
這些參數直接從第一層入口函數中傳進來,或者經過簡單的編碼,截斷等處理直接進入危險函數,導致了以上危險行為。
靜態分析的核心是什么?
注入判斷的核心就在於找到危險函數,並且判斷其參數是可控的,找到危險函數這個只需要維護一個危險函數列表即可。
當在語法樹中發現了函數調用並且其名稱在危險列表中就可以標記出該行代碼,接下來的難點就在於跟蹤該函數的參數,默認認為該危險函數的外層函數的參數是可控的,那就只需要分析這個外層函數參數的傳遞過程即可
在python中,參數的處理過程大概總結如下這些情況:
直接賦值:GET參數直接賦值
屬性賦值:request.POST.get(‘name’)賦值,排除META中的內容
字符串拼接:字符串拼接
列表解析式:
元組、列表、字典數據處理:元素相加,賦值value等
Subscript分片取值:通過下標索引取值
函數調用后賦值:字符串操作的系統函數str,strip,split,encode等,未過濾的自定義函數,危險函數
With操作:
For循環:
If判斷:
排除特殊情況:
判斷是否合法:os.path.exitst,isdir等
鎖定范圍:Type in [xxx,xxx]
如果存在此文件中導入了其他非系統模塊,繼續遞歸解析此模塊文件
如果存在此文件中導入了其他非系統模塊,繼續遞歸解析此模塊文件
如果存在類的話,繼續遞歸類里面方法的內容
Body的內容是嵌套的,一個body里面可能還有很多個body
循環body體中的元素,然后取出body中的body,orelse,test,handlers元素,繼續遞歸查找可控參數
以行為單位解析出來的結構和內容
Name為被賦值的變量名
然后value里面就是具體的內容
從右往左一次嵌套,所以request在最里層的value
以Python文件為入口,解析成語法樹,格式化為json格式
取出語法樹中的函數體內容
然后遍歷函數體中的代碼行:
如果有危險函數調用,並且有可控參數進入此危險函數,則報出漏洞
所以這里的核心就是:
1、遞歸全部代碼查找可控參數,生成可控參數列表
2、維護危險函數列表
最早的版本已經開源,大家可以借鑒,可以閱讀代碼了解python的語法樹
靜態分析的缺陷:
漏報誤報高
可控參數分析覆蓋不夠全
外部導入函數對可控參數判斷的影響
python 是一種動態類型語言,python 中一切皆對象
所以換句話說每個對象可以在程序里任何地方改變它
這就意味着我們可以劫持我們認為危險的函數
攔截進入函數的參數,判斷是否有惡意參數進入,從而判斷是否存在漏洞
Python的廣泛使用,很大部分是因為開發效率高,模塊使用方便
所以就劫持就針對:
1、模塊的直接方法
2、模塊的類,已經類方法進行了
舉例:
模塊的方法可以直接被劫持
首先通過imp導入os模塊,然后在覆蓋到其中的system方法
在調用system方法時,就是這里的__call__方法了
判斷進入system方法的參數是否有惡意內容,從而可以判斷是否真正觸發了漏洞
元類:
元類就是用來創建類的類,函數type實際上是一個元類
元類的主要目的就是為了當創建類時能夠自動地改變類。
__metaclass__:
你可以在寫一個類的時候為其添加__metaclass__屬性, Python就會用它來創建類
__metaclass__可以接受任何可調用的對象,你可以在__metaclass__中放置可以創建一個類的東西
__new__:是用來創建類並返回這個類的實例
__call__:任何類,只需要定義一個__call__()方法,就可以直接對實例進行調用,用callable來判斷是否可被調用
__getattribute__:定義了你的屬性被訪問時的行為
你首先寫下class Foo(object),但是類對象Foo還沒有在內存中創建。
Python會在類的定義中尋找__metaclass__屬性,如果找到了,Python就會用它來創建類Foo,如果沒有找到,就會用內建的type來創建這個類
定義test類,使用metaclass來創建tesk類
這時在metaclass中就可以動態修改這個類
這里使用upperattr,在創建test類時,將屬性名稱全部大寫
在test類實例化的時候就會執行上述操作,達到動態修改類的效果
舉例:
模塊的類的劫持
在當前pythonpath路徑下創建socket.py文件
然后劫持_fileobject類,使用_installclshook動態修改此類
變量_fileobject的屬性方法時,返回_hook_writelin 和 _hook_readline
寫好的劫持腳本,放到當前的工作根目錄下即可
然后正常啟動項目,劫持腳本就會自動生效,劫持特定的方法
但是內建函數方法,built-in method無法直接覆蓋劫持
這時也可以通過monkey path來實現:
Monkey patch就是在運行時修改代碼,實現hot patch的一種手段
將patch腳本import到應用里面,在功能函數入口通過裝飾器的方式應用patch即可
動態審計的優點:
-
准確性高
-
可以平台化
-
但是使用和擴展需要了解具體模塊的結構,pyhton的魔術方法等基礎知識
-
因為需要部署到目標系統代碼中,所以動態修改后的類和方法會對系統造成未知的影響,(不過目前測試來看還沒出現)
這里這個開源的項目是使用動態hook來制作python后門的例子,可以參考
動態檢測和靜態檢測相結合,相輔相成,相互補助,才能達到更好的效果,最后才能自動化檢測
對於,git和svn這種版本控制的,可以不用每次都掃描全部代碼,可以根據版本號掃描范圍之間的代碼,節省資源,速度快
下載agent安裝包后,根據右邊的部署說明,部署agent到需要檢測的服務器上即可
成功部署agent后,會在平台上顯示主機是否在線
並且agent會自動hook功能代碼入口:
比如django開發的系統,根據url整理views中的方法,然后自動劫持這些方法即可,不用全部劫持,盡量減少對系統代碼的改動
用戶設置代理,正常訪問系統
代理替換參數內容為payload,到系統后,漏洞檢測系統自動檢測漏洞然后顯示信息到控制台
歡迎閱讀,關於此自動化審計系統開源情況請關注FormSec官方公眾號,謝謝!
本文作者:逢魔安全實驗室
本文為安全脈搏專欄作者發布,轉載請注明:https://www.secpulse.com/archives/68344.html