php代碼審計入門讀書小結

由於看到不少講web安全的地方都會推薦一本書叫 《代碼審計:企業級web代碼安全架構》,於是從圖書館找來這本書讀了一下,雖然有些內容可能有點老了,但整體上還是挺不錯的,下面做一點總結。

一、通用代碼審計思路

常見的代碼審計思路有以下四種:

1、根據敏感關鍵詞(敏感函數)回溯參數傳遞過程。

2、查找可控變量,正向追蹤變量傳遞過程。

3、尋找敏感功能點,通讀功能點代碼。
(1)文件上傳功能:文件上傳漏洞、文件名SQL注入漏洞
(2)文件管理功能:任意文件操作漏洞、XSS漏洞
(3)登陸認證功能:任意用戶登陸漏洞、越權漏洞
(4)找回密碼功能

4、直接通讀全文代碼

通讀全文代碼時,首先應看程序的代碼結構,如主目錄有哪些文件,模塊目錄有哪些文件,插件目錄有哪些文件,除了關注有哪些文件,還要注意文件的大小、創建時間。在看程序目錄結構時候,注意以下幾個文件:
(1)函數集文件:通常命名中包含functions或者common等關鍵字,一般可以在index.php或者一些功能性文件的頭部可以找到。
(2)配置文件:通常命名中包含config關鍵字,配置文件包括web程序運行必須的功能性配置選項以及數據庫等配置信息。
(3)安全過濾文件:通常文件名中包含filtersafecheck等關鍵字,這類文件主要是對參數進行過濾,關係到我們找到的可疑點能否利用。
(4)index文件:index是一個程序的入口文件,通常讀一遍index文件就可以大致瞭解整個程序的架構、運行的流程、包含到的文件,其中核心文件有哪些。


二、SQL注入漏洞

1.普通注入:int型和string型

2.編碼注入:寬字節注入和二次urldecode注入

(1)寬字節注入:
當php連接mysql時如果 set character_set_client =gbk時會導致該注入的發生。提交

`/1.php?id= -1' and 1=1%23`

時,單引號會被\轉義.
這時如果提交?id=-1%df' and 1=1#的話,過濾用的\ (%5c)會與%df%5c組合,mysql語句就成了

select * from user where id='-1運' and 1=1#`

(2)urldecode二次解碼
在web中通常使用addslashes()mysql_real_escape_string()mysql_escape_string函數或者開啓GPC的方式來防止注入,原理就是給預定義字符也就是單引號、雙引號、反斜槓和NULL進行轉義,但是如果某處使用了urldecode或者rawurldecode函數,如果開啓了GPC來過濾,那麼提交?id=1%25%27,%25經過url解碼爲%%27解碼爲單引號,那麼成功引發注入,在代碼審計的過程中要注意這兩個函數。

3.防護
(1)魔術引號 gpc/rutime
在數據處理中主要有兩條路線,一種是用戶主動提交的,另外一種是用戶被動接受的,
GPC主要對用戶的POST、GET、cookie的值進行過濾,runtimer對從數據庫或者文件中獲取的數據進行過濾,但是對Int類型注入作用不大。

(2)過濾函數
addslashes與GPC的作用差不多。

mysql_real_esca## 二、SQL注入漏洞pe_string()、mysql_escape_string():主要對字符串進行過濾。

intval()、floatval()等:這類是將string類型轉化爲int類型的函數,將 1' union select強制轉化爲1,


三、XSS漏洞

推薦書籍:《XSS跨站腳本攻擊剖析與防禦》、《Web前端黑客技術揭祕》

1.分類
(1)反射型XSS
(2)存儲型XSS

2.防禦
過濾掉特殊字符即可:

  • 單引號(’)
  • 雙引號(")
  • 尖括號(<>)
  • 反斜槓(\)
  • 冒號(:)
  • and符(&)
  • #號(#)

四、CSRF漏洞

1.判斷方法

(1)黑盒
在挖掘CSRF的時候可以先搭建好環境,打開幾個有非靜態操作的頁面,抓包看看有沒有token,如果沒有token的話,在直接請求這個頁面,不帶referer。如果返回的數據還是一樣的,那說明有可能有CSRF漏洞。
(2)白盒
看看幾個核心文件裏面有沒有驗證token和referer相關的代碼。

2.防禦
(1)Token驗證
(2)驗證碼驗證


五、文件操作漏洞

1.文件包含漏洞
文件包含函數:

  • include()
  • include_once()
  • require()
  • require_once()

2.文件讀取(下載漏洞)
文件讀取函數:

  • file_get_contents()
  • highlight_file()
  • fopen()
  • readfile()
  • fread()
  • fgetss()
  • fgets()
  • parse_ini_file()
  • show_source()
  • file()
  • 文件包含函數include以及php輸入輸出流php://filter

3.文件上傳漏洞

  • 對文件名或擴展名未過濾或過濾不全
  • 黑名單存在繞過
  • 文件頭、content-type驗證繞過
  • 解析漏洞

4.文件刪除漏洞
文件刪除函數:

  • unlink()
  • 老版本下session_destroy()

5.防禦
(1)對文件操作的權限管理要合理
(2)有些文件不需要直接傳入文件名
(3)過濾掉文件跳轉的一些符號
(4)文件上傳儘量使用白名單過濾擴展名,保存上傳的文件時利用時間戳+隨機數MD5重命名


六、代碼執行漏洞

1.常見函數

  • eval()
  • assert()
  • preg_replace()
  • call_user_func()
  • call_user_func_array()
  • array_map()

(1)eval 和 assert 函數

動態執行代碼,參數直接就是php代碼。

<?php
$a='aaa';
$b='bbb';
eval('$a=$b;');
echo $a;
?>

結果輸出: bbb

(2)preg_replace函數
該函數作用是對字符串進行正則處理,它的參數和返回如下:
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit=-1 [, int &$count ] ] )
這段代碼的含義是搜索$subject中匹配$pattern的部分,以$replacement進行代替,而當$pattern處即第一個參數存在e修飾符時,$replacement的值會被當作PHP代碼來執行。

<?php
preg_replace("/\[(.*)\]/e", '\\1', $_GET['str']);
?>

當傳入?str=[phpinfo()]
代碼執行成功,回顯phpinfo頁面

(3)調用函數過濾不嚴
call_user_fun()和araay_map()等函數有調用其他函數的功能,其中一個參數作爲要調用的函數名,如果這個傳入的函數名可控, 就可以調用意外的函數來執行代碼。

<?php
$b='phpinfo()';
call_user_func($_GET['a'], $b);
?>

當請求?a=assert時候,調用了assert函數,並將phpinfo()作爲參數傳入,執行了該代碼。

(4)動態函數執行
php動態函數的寫法爲“變量(參數)”,如下例:

<?php
$_GET['a']($GET_['b']);
?>

上述代碼意思時a的參數作爲函數,b的參數作爲函數的參數
即當傳入?a=assert&b=phpinfo()時,相當於執行assert('phpinfo()')

2.防禦
採用白名單過濾,或者結合正則表達式來進行白名單限制。


七、命令執行漏洞

1.命令執行函數:

  • system()
  • exec()
  • shell_exec()
  • passthru()
  • pcntl_exec()
  • popen()
  • proc_open()
  • 反引號(`),相當於調用shell_exec()

(1)system()、exec()、shell_exec()、passthru()以及反引號(`)可以直接傳入命令並且函數會返回執行結果,其中system()函數會直接回顯打印輸出,不需要ehco也可以。

<?php
system('whoami');
?>

結果輸出當前的WebServer用戶

(2)popen()、proc_open()不會直接返回執行結果,而是返回一個文件指針,但是命令已經執行了。

<?php
popen('whoami >>D://2.txt', 'r');
?>

執行完可以在D盤根目錄看到2.txt這個文件,內容爲WebServer用戶名

2.防禦
(1)命令防注入函數

  • escapeshellcmd() 過濾整體命令,參數是一整條命令
  • escapeshellarg() 過濾參數,將參數限制在一對雙引號裏,確保參數爲一個字符串,因此它會把雙引號替換爲空格

八、變量覆蓋漏洞

1.引發函數:

  • extract()
  • parse_str()
  • import_request_variables()

(1)extract 函數
簡單來說就是將數組中的鍵值對註冊成變量。

<?php
$b=3;
$a=array('b'=>'1');
extract($a);
print_r($b);
?>

結果輸出:1

原本變量$b的值爲3,經過extract()函數對變量$a處理後,變量$b的值被覆蓋爲1。

(2)parse_str 函數
parse_str()函數作用是解析字符串並註冊成變量,它在註冊變量之前不會驗證當前變量是否已經存在,所以會覆蓋掉已有變量。

<?php
$b=1;
parse_str('b=2');
print_r($b);
?>

結果輸出:2

(3)import_request_variables 函數
import_request_variables()函數是把GET、POST、COOKIE的參數註冊成變量,用在register_globals被禁止的時候,需要PHP4.1至5.4之間的版本。

(4)$$ 變量覆蓋

2.防禦
(1)使用原始變量
(2)驗證變量存在


九、邏輯處理漏洞

1.等於與存在判斷繞過
(1)in_array()函數
(2)is_numeric函數
(3)雙等於(==)和三等於( ===)

2.賬戶體系中的越權漏洞

3.未 exit 或 return 引發的安全問題

4.常見支付漏洞

5.防禦
(1)深入熟悉業務邏輯
(2)熟悉函數的功能和差異


十、會話認證漏洞

1.cookie認證安全
(1)cookie的SQL注入
(2)僞造cookie

2.防禦
(1)嚴格限制輸入的異常字符已經避免用客戶端提交的內容直接操作
(2)將cookie與session結合起來使用,並保證客戶端不能操作敏感session參數
(3)敏感數據不要放在cookie中


十一、二次漏洞

1.什麼是二次漏洞
需要先構造好利用代碼寫入網站保存,在第二次或多次請求後調用攻擊代碼觸發或者修改配置觸發的漏洞叫做而此漏洞。

(此漏洞較複雜,需之後進一步學習研究)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章