一、php中常見的危險函數和審計要點 危險函數(功能過於強大) 參數是否外部可控,有沒有正確的過濾。 PHP獲取外界傳入參數是通過下麵幾個全局函數的形式,所以審計參數傳入經常要和下麵幾個變數打交道 PHP中危險函數有五大特性: 參數是否可控 執行任意代碼函數 1)把傳入的字元串直接當成php代碼直接 ...
一、php中常見的危險函數和審計要點
危險函數(功能過於強大)
參數是否外部可控,有沒有正確的過濾。
PHP獲取外界傳入參數是通過下麵幾個全局函數的形式,所以審計參數傳入經常要和下麵幾個變數打交道
PHP中危險函數有五大特性:
變數 | 說明 |
$_GET | 數組,存放著所有通過URL參數傳遞的數據 |
$_POST | 數組,當HTTP POST請求的Content-Type是application/x-www-form-urlencoded或multipart/form-data的部分解析成關聯數組 |
$_FILES | 數據,存放著HTTP POST上傳的文件信息 |
$_COOKIE | 數組,存放著HTTP頭裡面cookie段內容 |
$_REQUEST | 數組,預設情況下包含了$_GET, $_POST, $_COOKIE的數據 |
$_SERVER | 數組,包含了HTTP頭,伺服器環境等信息 |
$_SESSION | 數組,存放當前會話可用的session變數 |
參數是否可控
執行任意代碼函數
1)把傳入的字元串直接當成php代碼直接執行,如:
A | B | C | D | |
1 | 函數 | 函數說明 | 例子 | 運行結果 |
2 | assert | 判斷一個斷言是否為false | assert('print(123)') | 輸出123 |
3 | eval | 把一個字元串當做php代碼執行 | eval('echo 123') | 輸出123 |
4 | create_function | 用給的一個字元串創建匿名函數 | create_function('$a','print($a);')(123) | 輸出123 |
2)通過引入文件的形式執行php代碼,如:(利用:查看這些引入文件參數是否外部可控)
A | B | C | D | |
1 | 函數 | 函數說明 | 例子 | 結果 |
2 | include | 包含並運行指定文件 | include '1.php' | 包含文件1.php,並執行裡面的代碼 |
3 | include_once | 包含並運行指定文件 | include_once '1.php' | 包含文件1.php,並執行裡面的打碼 |
4 | require | 包含並運行指定文件 | require '1.php' | 包含文件1.php,並執行裡面的代碼 |
5 | require_once | 包含並運行指定文件 | require_once '1.php' | 包含文件1.php,並執行裡面的代碼 |
3)數據處理函數
函數 | 函數說明 | 例子 | 結果 | |
1 | preg_replace | 使用正則替換內容,php7之前的正則表達式參數可以開啟\e的模式,執行任意代碼 | preg_replce("/(.)/e",'print(\1),'123'); |
php5下輸出123 |
2 | array_map | 為數組的每個元素應用回調函數 | $b=array_map('assert',['print(123)']); | php5下輸出123 |
3 | array_filter | 用回調函數過濾數組中的單元 | array_filter(['print(123)'],'assert'); | php5下輸出123 |
4 | array_walk | 使用用戶自定義函數對數組中的每個元素做回調處理 |
$a=['print(123)'];array_walk($a,'assert') |
php5下輸出123 |
5 | call_user_func | 把第一個參數作為回調函數調用 | call_user_func('assert','print(123)'); | 輸出123 |
4)能夠讀取網路資源的函數(配置 allow_url_include=1 才可以使用)
函數 | 函數說明 | 例子 | 結果 | |
1 | curl系列 | 發起網路請求 | ||
2 | file_get_contents | 原本功能是讀取文件,但是支持封裝協議,所以可以讀取網路上的資源 | file_get_contents('https://url.com') | 請求url.com |
3 | file | 原本功能是讀取文件,但是支持封裝協議,所以可以讀取網路上的資源 | file('https://url.com') | 請求url.com |
4 | fopen | 原本功能是讀取文件,但是支持封裝協議,所以可以讀取網路上的資源 | fopen('https://url.com') | 請求url.com |
5 |
copy |
原本功能是複製文件,但是支持封裝協議,所以可以讀取網路上的資源 | copy('https://url.com') | 請求url.com,並保存txt文檔 |
5)能夠執行系統命令或者調用外部程式的函數
函數 | 函數說明 | 例子 | 結果 |
exec | 執行一個外部程式 | exec('touch 1.txt') | 在當前目錄下生成1.txt |
shell_exec |
通過shell執行命令,並且將完整的輸出以字元串的方式返回 | shell_exec('touch 1.txt') | 在當前目錄下生成1.txt |
system | 執行外部程式,並顯示輸出 | system('touch 1.txt') | 在當前目錄下生成1.txt |
passthru | 執行外部程式,並顯示輸出 | passthru('touch 1.txt') | 在當前目錄下生成1.txt |
popen | 打開進程文件指針 | popen('touch 1.txt','r') | 在當前目錄下生成1.txt |
proc_open | 執行一個命令,並打開用來輸入/輸出的文件指針 | proc_open('touch 1.txt',[],$a) | 在當前目錄下生成1.txt |
`` | 反引號包含的內容會當成系統命令執行 | `touch 1.txt` | 在當前目錄下生成1.txt |
6)能夠修改運行時候的上下文環境
函數 | 函數說明 | 例子 | 結果 |
extract | 從數組中將變數導入到當前的符號表,審計時候需要判別傳輸數組是否外部可控 | $a='1';extract(['a'=>'2']);echo $a | 輸出2 |
parse_str |
將字元串解析成多個變數 | $a='1';parse_str('a=2');echo $a | 輸出2 |
ini_set | 修改運行時php配置 | ini_set('memory_limit','2048M') | 設置運行時最大占用額記憶體為2048M |