作者:niexinming
作者博客:https://www.n0tr00t.com/2018/08/30/Python-dynamic-codereview.html
議題 PPT 下載地址:/static/ppt/KCon-2018-Python-dynamic-codereview.pptx
0x00 動態代碼審計用處
- 大型項目代碼結構復雜
- 有些危險的功能隱藏較深(危險的定時計劃任務、sqlite數據庫任意創建導致任意文件覆蓋……)
- 提高效率,希望通過一些黑盒的方法比較快速的找到漏洞。
0x01 常見漏洞分類
- 數據庫操作
- 敏感函數的調用和傳參
- 文件讀寫操作
- 網絡訪問操作
0x02 正文目錄
- 數據庫general log 日志
- hook關鍵函數
- 結合auditd
- http盲攻擊
- fuzzing
0x03 數據庫日志
general-log是記錄所有的操作日志,不過他會耗費數據庫5%-10%的性能,所以一般沒什么特別需要,大多數情況是不開的,例如一些sql審計和代碼審計等,那就是打開來使用了
Mysql通過命令行的方式打開general log:
set global general_log_file='';
set global general_log=on;
Postgresql 通過編輯配置文件打開general log:
編輯:postgresql.conf
log_directory = 'pg_log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_statement = 'all'
打開之后用burp向web api發送一些包含sql注入的畸形數據

利用Linux的grep指令過濾出sql執行中的ERROR關鍵字,就可以很快的找到sql注入漏洞

0x04 Hook關鍵函數
根據基于python的自動化代碼審計和pyekaboo這兩個文章的啟發而來
Python對象可以被輕易的改變,通過設置PYTHONPATH這個環境變量,使python在加載string這個模塊的時候優先加載我自定義的string模塊,下圖演示的是劫持string模塊的upper函數

之后我的思路是,通過劫持python的函數,把輸入到危險函數的參數輸出到日志中,最后調用正常的python函數

這樣就可以劫持我們認為敏感的函數
劫持模塊的demo:
import imp
import sys
class _InstallFcnHook(object):
def __init__(self,fcn):
self._fcn=fcn
def _pre_hook(self,*args,**kwargs):
print "hook:"+str(args)
return (args,kwargs)
def __call__(self,*args,**kwargs):
(_hook_args,_hook_kwargs)=self._pre_hook(*args,**kwargs)
retval=self._fcn(*_hook_args,**_hook_kwargs)
return retval
fd,pathname,desc=imp.find_module(__name__,sys.path[::-1])
mod =imp.load_module(__name__,fd,pathname,desc)
system=_InstallFcnHook(system)
劫持效果:

這就意味著我們可以劫持危險的函數,把參數輸出到日志里面,通過日志信息,可以判斷這些參數是否可以被輸入控制。通過這種方式可以方便找到ssti、pickle反序列化漏洞和命令執行漏洞等其他的漏洞

而且這些可以很方面的拓展到其他的模塊中
- cd hook/ #進入到hook模塊所在目錄
- cp os.py xxx.py #把os模塊復制一份,xxx模塊是你想hook的模塊
- 編輯xxx.py :注釋掉原來被hook的函數,添加想要hook的函數,下面的示例是hook了subprocess模塊中check_call函數

Ps 需要填一些坑:
- 修改啟動代碼從shell中啟動python web
因為有一些python web是從wsgi中啟動的,這些只要簡單修改啟動代碼就可以從WSGI方式啟動切換到shell啟動 - 從內存中刪掉已加載的模塊
一些模塊通過import動態導入,需要在動態導入后通過del modules刪掉被裝載的模塊 - 關閉調試選項
例如在flask啟動時將debug選項設置為false,否則會產生兩個python進程 - 其他問題 Python web性能下降、代碼不兼容、有些模塊無法被hook,其中python的內置函數open就無法通過這樣的方式被hook。
0x05 結合Auditd
網上有很多方法去獲取python web的文件讀寫操作,其中有一種是在文件讀寫函數前面添加裝飾器,但是我覺得那種方法太過于煩瑣,且不能覆蓋到所有的文件讀寫操作,那怎么不通過修改原始代碼去獲取文件讀寫操作?
可以利用Auditd:
auditd(或 auditd 守護進程)是Linux審計系統中用戶空間的一個組件,其可以記錄Linux中文件,進程等操作,且安裝方便
CentOS 默認安裝
Ubuntu 安裝:apt-get install auditd
只要簡單的配置就可以監視一些文件操作
sudo auditctl -a exclude,always -F msgtype!=PATH -F msgtype!=SYSCALL #記錄文件操作
sudo auditctl -a always,exit -F arch=b64 -S execve -k rule01_exec_command #記錄所有的shell指令的執行
sudo auditctl -a always,exit -F pid=$mypid #記錄指定進程文件操作
執行 sudo auditctl -l 查看所有的規則

只要發送一些包含目錄跳轉的畸形數據給webapi,如有任意文件讀取的漏洞就可以很快的發現。
因為Auditd日志中包含大量其他的日志,通過grep和關鍵字高亮工具(https://github.com/paoloantinori/hhighlighter)進行查看日志(grep過濾PATH,高亮name)

除了記錄文件讀取,還能記錄文件的其他操作

這樣就可以找到:
- 任意文件上傳
- 任意文件創建
- 任意文件讀取
- 任意文件刪除
0x06 http盲攻擊
怎么解決諸如ssrf等網絡操作的問題?
ssrf攻擊可以讓黑客越過防火墻來探測或者攻擊一個大型企業的內網

那么在動態代碼審計過程中就可以通過構造特定的poc,來探測代碼中是否有對應的漏洞
可以構造請求dns解析的數據
- 命令執行的常見形式
Ping –c 1 xxx.pw - ssrf的常見形式
url=http://xxx.pw - xxe的常見形式

通過dns日志的記錄可以很快找到諸如ssrf、xxe、命令執行等,包括可以找到一些隱藏的比較深的定時計劃任務的中漏洞

0x07 fuzzing
做完上面的一些工作之后,我在想如何提高我的工作效率,畢竟我們部門產品眾多,但是代碼審計這個工作只有我一個在做。我把正常數據,畸形數據,poc數據,等其他數據全發給web api,然后在審計數據庫日志,危險函數日志,auditd日志,dns日志,web報錯日志,希望能從日志中發現潛藏的漏洞

利用burp的intruder這個功能就可以實現,測試用例可以使用wooyun提供的fuzzing數據

Ps 還是有幾個自己需要處理的問題:
- 需要根據自己的業務類型制定自己的測試用例
- 自己要想辦法處理產生的大量的日志
- 其他問題
0x08 TODO
- 自動化部署客戶端
- 開發一個日志處理平臺
- 盡可能的覆蓋更多的漏洞類型
- 豐富測試用例
- 開源( https://github.com/niexinming/python_hook)
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/689/
暫無評論