0x00 簡介
之前看了seay寫的PHP代碼審計的書,全部瀏覽了一遍,作為一個代碼審計小白,希望向一些和我一樣的小白的人提供一下我的收穫,以及一個整體的架構和常見漏洞函數。這也算是這本書的一個學習筆記吧,可以結合我捋順的思路來看這本書。: )
0x01 整體
學習代碼審計的目標是能夠獨立完成對一個CMS的代碼安全監測。其通用的思路有:
- 通讀全文代碼,從功能函數代碼開始閱讀,例如 include 檔案夾下的 common_fun.php ,或者有類似關鍵字的檔案。
- 看設定檔,帶有 config 關鍵字的檔案,找到mysql.class.php檔案的connect()函數,查看在資料庫連接時是否出現漏洞。
- 繼續跟讀首頁檔案, index.php ,瞭解程式運作時調用了哪些函數和檔案 以index.php檔案作為標線,一層一層去擴充閱讀所包含的檔案,瞭解其功能,之後進入其功能檔案夾的首頁檔案,進行擴充閱讀。
0x02 各種洞洞
a.檔案操作漏洞
- 能不用檔案名稱參數就不用 盡量不要讓使用者可控
- 平行使用者的許可權 管理員的許可權 操作許可權
- 禁止傳入參數類似於這種 .. , / , \ 檢查傳入的參數,做出限制,停止程式往下執行
1.檔案包含漏洞:
(1) 本地檔案包含:
- 一般存在於模組載入,模板載入,cache調用
- 包括函數: include()/include_once() , require()/require_once() 尋找可控變數
(2) 遠程檔案包含:
- 前提條件: allow_url_include = on
- 出現頻率不如當地套件含
(3) 檔案包含截斷:
- %00截斷(php版本小於5.3)
- 問號截斷(問號後面相當於請求的參數,偽截斷)
- 英文(.) 反斜線(/) 截斷
2.檔案讀取(下載)漏洞:
搜尋關鍵函數:
file_get_contents() , highlight_file() , fopen() , read file() , fread() , fgetss() , fgets() , parse_ini_file() , show_source() , file() 等
3.檔案上傳漏洞:
搜尋關鍵函數:
move_uploaded_file() 接著看調用這個函數的代碼是否存在為限制上傳格式或者可以繞過。
(1) 未過濾或本地過濾:伺服器端未過濾,直接上傳PHP格式的檔案即可利用。
(2) 黑名單副檔名過濾:
- 限制不夠全面:IIS預設支援解析 .asp , .cdx , .asa , .cer 等。
- 副檔名可繞過:
不被允許的檔案格式 .php ,但是我們可以上傳檔案名稱為 1.php (注意後面有一個空格)
(3) 檔案頭 content-type 驗證繞過:
- getimagesize() 函數:驗證檔案頭只要為GIF89a,就會返回真。
- 限制 $_FILES["file"]["type"] 的值 就是人為限制content-type為可控變數。
(4) 防範:
- 使用 in_array() 或 利用三等於 === 對比副檔名。
- 儲存上傳檔案是重新命名,規則採用時間戳記拼接隨機數: md5(time() + rand(1,1000)) 。
4.檔案刪除漏洞:
搜尋關鍵函數:
- unlink() 利用回溯變數的方式
- 老版本下的 session_destroy() ,可以刪除檔案,現已基本被修複。
Metinfo的任意檔案刪除漏洞:
$action = delete 即可刪除 .sql 的檔案,如果檔案不是 sql 直接刪除提交的檔案名稱
target.com/recovery.php?&action=delete&filename=../../index.php
b.代碼執行漏洞
1.代碼執行函數:
搜尋關鍵函數: eval() , assert() , preg_replace() , call_user_func() , call_user_func_array() , array_map()
(1) preg_replace() 函數:
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
當$pattern處存在e修飾符時,$replacement 會被當做php代碼執行。
(2) mixed call_user_func( callable $callbank [ , mixed $parameter [ , mixed $…) :
第一個參數為回呼函數,第二個參數是回呼函數的參數
(3) eval() 和 assert() :
當assert()的參數為字串時 可執行PHP代碼
【區分】:
eval(" phpinfo(); ");【√】 eval(" phpinfo() ");【X】assert(" phpinfo(); ");【√】 assert(" phpinfo() ");【√】
2.動態函數執行:
動態函數後門:
#!php
3.命令執行函數:
搜尋關鍵函數: system() , exec() , shell_exec() , passthru() , pcntl_exec() , popen() , proc_open()
(1) popen 和 proc_open() :
#!php> /Users/bingdaojueai/Desktop/1.txt', 'r' ); ?>
所在路徑就會出現一個1.txt 裡面的內容為命令執行後的結果
(2) 反引號命令執行:
雙引號時,可以直接解析變數,造成代碼執行漏洞,過狗繞過。
c.變數覆蓋漏洞
1.函數使用不當:
- int extract( array &$var_array , int $extract_type = EXTR_OVERWRITE , string $prefix = null )
- void parse_str( string $str , array &$arr )
- bool import_request_variables( string $type , string $prefix )
2.$$變數覆蓋:
d.邏輯漏洞
需要思考的問題:
- 程式是否可以重複安裝
- 修改密碼是否存在越權修改其他使用者密碼
- 找回密碼驗證碼是否可以暴力破解
- cookie是否可以預測 驗證存在繞過
1.等於與存在判斷繞過:
(1) in_array() : 比較之前會自動轉換類型
(2) is_numeric() : 當傳入參數為hex時 直接通過並返回true 並且MYSQL可以直接使用hex編碼代替字串明文 可以二次注入 並且可能造成XSS漏洞
(3)雙等於 == 和三等於 === :
- 雙等於會在變數比較時,進行類轉換,與 in_array() 是一樣的問題。
- 三等於是 type 和 value 的雙重比較,相比之下更加安全。
2.賬戶體系中的越權問題:
- 水平越權: A使用者能夠以B使用者的身份,進行B使用者的全部許可權操作。前提A使用者和B使用者擁有相同的許可權。
- 垂直越權: A使用者能夠以C使用者的身份,進行C使用者的全部許可權操作,前提C使用者比A使用者擁有更高的許可權。
(1) 未 exit / return / die :
#!php
test 依舊會被輸出,替換成安裝流程,PHP依舊會進行。
(2) 支付漏洞:
- 用戶端修改單價
- 用戶端修改總價和購買數量
- 服務端未校正嚴格
-
重複發包利用時間差:
#!php
可能導致漏洞函數: str_replace()
#!php$b
";$c = str_replace($a,'',$b);echo trim($c);?>
e.會話認證漏洞
f.二次漏洞
1.類型:
- 不是邏輯問題,是可信問題。
- 商務邏輯複雜度,與二次漏洞觸發率 成正比。
- 購物車 / 訂單 / 引用資料 / 文章編輯 / 草稿 ==> SQL注入 / XSS
2.技巧:
(1) 鑽GPC等轉義的空子:
- 不受GPC保護的 $_SERVER 變數: PHP5以後,$_SERVER取到的header不再受GPC影響,就算開啟特殊字元也不會被轉義,存在注入
-
編碼問題轉換:
- GBK的寬位元組注入: %df ' 單引號自動被轉義成(%5c),同時 %df 與 %5c 連在一起組合成 運 字單引號依然在,成功閉合。【php與mysql互動過程中發生的編碼轉換問題】
-
mb_convert_encoding() :
#!php
(2)字串問題:
0x03 End
自己走上安全這條路既是興趣也是偶然,選擇白盒完全是因為喜歡php,畢竟是初識代碼審計,seay的書確實幫了我不少,抱作者大腿 (我是萌妹紙) ,希望這篇文章能夠協助像我一樣小白的人,花了兩天總結的,如果有什麼缺陷也等著大家指出。
不會開發的談審計都是耍流氓! :)