## 工具
Fotify|代碼審計靜態掃描工具,商業化靜態代碼掃描工具,誤報率相對較低。
seay|源代碼審計工具
PHPStorm|是PHP編程語言開發的集成環境。
chrome & burp & HackerBar 插件 & xdebug插件
Xcheck |Xcheck是一個由騰訊公司CSIG質量部代碼安全檢查團隊自研的靜態應用安全測試工具。Xcheck在基於成熟的污點分析技術與對抽象語法樹的精准剖解上,通過巧妙優雅的實現來達到對污點的傳遞和跟蹤的目的,更精准地發現隱藏在代碼中的安全風險。同時賦予了Xcheck兩大優勢:快!低誤報!
框架
確定目標是否使用的框架、MCV設計模式。
熟悉常見的框架:ThinkPHP、Laravel、Codeigniter、Yii等
MVC
既然是MVC框架的,那么我們真正關心的是其中的控制器(C),因為功能點大部分都在C上,我們能找到的大部分漏洞也都在C上
ThinkPHP
一般如果是審計基於框架的cms,我不會去看框架系統目錄(對於TP框架就是ThinkPHP文件夾下的東西),第三方類庫vendor也不會去先看,除非是在審計過程中流向了這些文件中,才會大概看一看,而重點在Application文件夾下做文章。
Laravel
目錄怎么變,MVC架構的重點還是在Controllers里
無框架
先弄清目標的目錄結構。
審計過程中需要關注幾個點:(在我們后面開始審計的過程中,自己要注意這些地方,經常想一想)
1)函數集文件,通常命名包含function或者common等關鍵字,這些文件里面是一些公共的函數,提供其他文件統一調用,所以大多數文件都會在文件頭部包含到其他文件。尋找這些文件一個非常好用的技巧就是去打開index.php或者一些功能性文件,在頭部一般都能找到。
2)配置文件,通常命名中包括config關鍵字,配置文件包括web程序運行必須的功能性配置選項以及數據庫等配置信息。從這個文件中可以了解程序的小部分功能,另外看這個文件的時候注意觀察配置文件中參數值是單引號還是用雙引號括起來,如果是雙引號可能就存在代碼執行的問題了。
3)安全過濾文件,安全過濾文件對代碼審計至關重要,這關系到我們挖掘到的可以點能否直接利用,通常命名中帶有filter、safe、check等關鍵字,這類文件主要是對參數進行過濾,大多數的應用其實會在參數的輸入做一下addslashes()函數的過濾。
4)index文件,index是一個程序的入口,所以通常我們只要讀一讀index文件就可以大致了解整個程序的架構、運行的流程、包含到的文件,其中核心的文件有哪些。而不同目錄的index文件也有不同的實現方式,建議最好將幾個核心目錄的index文件都通讀一遍。
路由
以ThinkPHP為例,一般有幾種形式:普通模式、PATHINFO模式、REWRITE模式、兼容模式
普通模式:
http://localhost/?m=home&c=user&a=login&var1=value1&var2=value2
pathinfo模式:
http://serverName/index.php(或者其他應用入口文件)/模塊/控制器/操作/[參數名/參數值...]
REWRITE模式:
在PATHINFO的基礎上去掉入口文件
http://serverName/模塊/控制器/操作/[參數名/參數值...]
兼容模式:
http://servername/index.php?s=/index/Index/index
其中變量`s`的名稱的可以配置的。
審計
流程
1、先全局總覽:配置文件、路由等
2、定向功能審計:黑盒(找到敏感功能)+白盒(定位到代碼進行審計)
3、敏感函數回溯
比較完整的審計流程:
先黑盒+白盒看敏感功能,再用自動化審計工具跑一遍並驗證,最后再根據漏洞危險函數去回溯
常見漏洞類型審計(危險函數)
這里先僅列出函數,后面會詳細展開
⭐SQL注入
- 如果使用了框架,可以分辨一下框架名稱以及版本,去搜索一下該版本的框架是否存在漏洞,如果存在再去cms中驗證。
- 如果沒有使用框架,則需要仔細的觀察數據庫函數,一般來說,cms是將select、insert等函數進行了封裝的,比如$db->table(‘test’)->where(“name=admin”)便是 select * from test where name=admin這種格式,而此時若是發現cms使用的是過濾+拼接,那么很有可能會出現問題,而如果使用了PDO,則繼續跟進涉及到table,order by等字段的拼接去,因為這些字段是無法使用PDO的。
審計要素:
- 參數是否用戶可控
- 是否使用了預編譯
那么首先,如果沒有使用框架封裝的sql語句,那么全局搜索insert、select等sql語句關鍵詞,然后定位到具體的語句,然后查看里面有沒有拼接的變量,回溯可不可控。如果可控並且存在字符串拼接,很有可能就存在漏洞。
使用了框架的就是搜索的關鍵詞不一樣,還是得看是否存在字符串拼接,可不可控。
即使使用了預編譯,但是如果在預編譯之前字符串拼接了,那照樣沒有鳥用,該注入還是能注入。
關鍵詞:
insert
create
delete
update
order by
group by
where
from
limit
desc
asc
union
select
寬字節注入
SET NAMES 'gbk' => set character_set_connection='gbk',character_set_results='gbk',character_set_client='gbk'
檢索關鍵字:
1、SET NAMES
2、character_set_client = gbk
3、mysql_set_charset('gbk') //后面沒有 mysql_real_escape_string函數
GPC
magic_quotes_gpc=on,會自動在GET、POST、COOKIE變量中的' 、"、 \、 NULL的前面加上反斜杠(\),但是在PHP5中magic_quotes_gpc並不會過濾$_SERVER變量,導致很多類似client-ip,referer一類的漏洞能夠利用。PHP5.4取消這個參數。
二次urldecode注入
我們提交參數到web服務器,web服務器會自動解碼一次。
1%2527 解碼兩次=》1'
檢索關鍵字:
urldecode
rawurldecode
XSS
審計要素
- 是否存在全局參數過濾器,過濾規則是否符合安全要求,是否存在需過濾和不需過濾兩種輸出,頁面是否控制恰當。
- 輸出時是否進行編碼(HTML、JS等)。
- 前端是否采用了Angularjs、React、vue.js等具有XSS防護功能的前端框架進行數據輸出
尋找帶有參數的輸出函數,然后根據輸出函數對輸出內容回溯輸入參數,觀察有沒有經過過濾
常用的輸出函數:
print、print_r、echo、printf、sprintf、die、var_dump、var_export
CSRF
先黑盒:打開幾個有非靜態操作的頁面,抓包看看有沒有token,如果沒有token的話,再直接請求這個頁面,不帶referer
再白盒:讀代碼的時候看看幾個核心文件里面有沒有驗證token和referer相關的代碼
可以嘗試全局搜索
csrf-tokencsrf_tokencsrftokencsrf
SSRF
審計要素:
- 是否存在可以產生SSRF漏洞的函數。
- 是否存在內網ip地址正則過濾,且正則是否嚴謹。
- 是否存在限制請求的方式只能為HTTP或者HTTPS。
通過全文關鍵函數搜索,再看是否限制了訪問端口,訪問協議,內網ip地址等。
關鍵詞:
file_get_contentsfsockopencurl_execget_headersfopenreadfile
⭐文件包含漏洞
文件包含算是拿shell最快的方法了,所以一般要重點關注。
大多數出現在模塊加載、模板加載以及cache調用的地方
先跟蹤一下程序運行流程,看看里面模塊加載時包含的文件是否可控,另外就是直接搜索
關鍵詞:
include、include_once、require、require_once
回溯看看有沒有可控的變量
文件讀取(下載)漏洞
先黑盒看看功能點對應的文件,再去讀文件
搜索文件讀取函數,回溯看看有沒有直接或者間接控制的變量:
關鍵詞:
file_get_contents() highlight_file() fopen() readfile() fread() fgetss() fgets() parse_ini_file() show_source() file() 文件包含函數include等
⭐文件上傳
審計要素
- 是否檢查了上傳文件的文件類型
- 是否限制了文件上傳路徑
- 是否對文件進行了重命名
- 文件大小是否限制
- 是否返回了文件路徑或文件路徑很好猜測
有的項目,會對文件上傳下載進行分裝,所以可以全局搜索有關upload、file的函數,看看是不是封裝了
function upload
function file
如果封裝了,那么就看這些封裝好的函數,有沒有上面提到的審計要素的漏洞。
如果沒封裝,一般是move_uploaded_file這個函數,全局搜索這個函數,回溯查看這些漏洞存不存在。(白盒黑盒一起搞比較好。)
文件刪除
可以先去找相應的功能點,直接黑盒測試一下看能不能刪除某個文件,如果刪除不了,再去執行流程去追提交的文件名參數的傳遞過程。
unlinkrmdir
⭐代碼執行
審計要素
- php.ini文件中的disable_function是否有禁用函數。
- 是否存在代碼執行的敏感函數。
- 是否輸入變量可控。
關鍵詞:
eval()、assert()、preg_replace()、create_function()、array_map()、call_user_func()、call_user_func_array()、array_filter、 usort()、動態函數
⭐命令執行
審計要素
- 參數是否用戶可控
- 是否配置了全局過濾器,過濾規則是否符合安全規范
- 是否所有的命令執行參數都經過了過濾器,或受白名單限制
關鍵詞:
exec()、passthru()、system()、 shell_exec()、popen()、反引號`、proc_open()、pcntl_exec()
變量覆蓋
變量覆蓋漏洞通常要結合應用其他功能代碼來實現完整攻擊,所以挖掘一個可用的變量覆蓋漏洞不僅僅要考慮的是能夠實現變量覆蓋,還要考慮后面的代碼能不能讓這個漏洞利用起來。要挖可用的變量覆蓋漏洞,一定要看漏洞代碼行之前存在哪些變量可用覆蓋並且有被使用到。
extract()
、parse_str()
這兩個函數比較好挖掘,直接檢索關鍵字,然后回溯
import_request_variables()
函數則相當於開了全局變量注冊,這時候只要找哪些變量沒有初始化並且操作之前沒有賦值的,然后就去提交這個變量作為參數。 PHP4-5.4.0 才有該函數。
$$ 變量覆蓋,經典代碼:
以上代碼,可以用從G P C獲得的 '參數=值',來覆蓋之前的所有變量
XXE
就關鍵函數:
SimpleXMLElement simplexml_load_stringloadxml
直接搜索 回溯
邏輯漏洞
通讀功能點源碼。值得關注的點是程序是否可以重復安裝、修改密碼處是否可越權修改其他用戶密碼、找回密碼驗證碼是否可暴力破解以及修改其他用戶密碼、cookie是否可預測或者說cookie驗證是否可繞過等。
危險函數: php黑魔法
in_array : 在比較之前會自動做類型轉換
is_numeric: 任何參數做16進制編碼傳入,會直接通過(true)
雙等於(==):弱等於,判斷之前會先做變量類型轉換
$_REQUEST獲取變量,進行過濾,可能存在繞過:GET方式傳危險數據,POST方式傳正常數據,$_REQUEST默認獲取的是POST方式傳入的數據。所有如果存在類似,$_GET傳入的參數,通過$_REQUEST進行過濾,就可能存在問題