Command Injection,即命令注入,是指通過(guò)提交惡意構(gòu)造的參數(shù)破壞命令語(yǔ)句結(jié)構(gòu),從而達(dá)到執(zhí)行惡意命令的目的。PHP命令注入攻擊漏洞是PHP應(yīng)用程序中常見(jiàn)的腳本漏洞之一
LOW
1 查看服務(wù)器端源代碼

2 相關(guān)函數(shù)
stristr(string,search,before_search)
stristr函數(shù)搜索字符串在另一字符串中的第一次出現(xiàn),返回字符串的剩余部分(從匹配點(diǎn)),如果未找到所搜索的字符串,則返回 FALSE
| 參數(shù) | 描述 |
|---|---|
| string | 必需。規(guī)定被搜索的字符串。 |
| search | 必需。規(guī)定要搜索的字符串。 |
| 如果該參數(shù)是數(shù)字,則搜索匹配該數(shù)字對(duì)應(yīng)的 ASCII 值的字符。 | |
| before_search | 可選。默認(rèn)值為 "false" 的布爾值。 |
| 如果設(shè)置為 "true",它將返回 search 參數(shù)第一次出現(xiàn)之前的字符串部分。 |
php_uname() 返回了運(yùn)行 PHP 的操作系統(tǒng)的描述
| 參數(shù) | 描述 |
|---|---|
| ”a” | (此為默認(rèn),包含序列”s n r v m”里的所有模式) |
| ”s ” | (返回操作系統(tǒng)名稱(chēng)) |
| ”n” | (返回主機(jī)名) |
| ” r” | (返回版本名稱(chēng)) |
| ”v” | (返回版本信息) |
| ”m” | (返回機(jī)器類(lèi)型)。 |
可以看到,服務(wù)器通過(guò)判斷操作系統(tǒng)執(zhí)行不同ping命令,但是對(duì)ip參數(shù)并未做任何的過(guò)濾,導(dǎo)致了嚴(yán)重的命令注入漏洞
命令執(zhí)行漏洞概念:當(dāng)web應(yīng)用程序需要調(diào)用一些外部程序去處理內(nèi)容的情況下,就會(huì)用到一些執(zhí)行系統(tǒng)命令的函數(shù) 在遠(yuǎn)程服務(wù)器上執(zhí)行任意系統(tǒng)命令
常用命令執(zhí)行函數(shù)
exec()、system()、popen()、passthru()、proc_open()、pcntl_exec()、shell_exec() 、反引號(hào)` 實(shí)際上是使用shell_exec()函數(shù)
system() 輸出并返回最后一行shell結(jié)果。
exec() 不輸出結(jié)果,返回最后一行shell結(jié)果,所有結(jié)果可以保存到一個(gè)返回的數(shù)組里面。
passthru() 只調(diào)用命令,把命令的運(yùn)行結(jié)果原樣地直接輸出到標(biāo)準(zhǔn)輸出設(shè)備上。
漏洞利用及繞過(guò)姿勢(shì)
| 命令管道符
<>>> 文件重定向符
測(cè)試: 0 | dir c:
代碼只過(guò)濾了部分特殊字符,可以考慮用其他字符進(jìn)行測(cè)試,這邊列舉一下Window/Linux可利用的特殊字符:
windows支持:
| 直接執(zhí)行后面的語(yǔ)句 ping 127.0.0.1|whoami
|| 前面出錯(cuò)執(zhí)行后面的 ,前面為假 ping 2 || whoami
& 前面的語(yǔ)句為假則直接執(zhí)行后面的,前面可真可假 ping 127.0.0.1&whoami
&&前面的語(yǔ)句為假則直接出錯(cuò),后面的也不執(zhí)行,前面只能為真 ping 127.0.0.1&&whoami
Linux支持:
; 前面的執(zhí)行完執(zhí)行后面的 ping 127.0.0.1;whoami
| 管道符,顯示后面的執(zhí)行結(jié)果 ping 127.0.0.1|whoami
ll 當(dāng)前面的執(zhí)行出錯(cuò)時(shí)執(zhí)行后面的 ping 1||whoami
& 前面的語(yǔ)句為假則直接執(zhí)行后面的,前面可真可假 ping 127.0.0.1&whoami
&&前面的語(yǔ)句為假則直接出錯(cuò),后面的也不執(zhí)行,前面只能為真 ping 127.0.0.1&&whoami
解題:
由服務(wù)端代碼知 沒(méi)有對(duì)特殊字符進(jìn)行過(guò)濾
輸入
127.0.0.1

輸入
127.0.0.1&&net user

Linux下輸入127.0.0.1&&cat /etc/shadow甚至可以讀取shadow文件,可見(jiàn)危害之大
DVWA亂碼問(wèn)題的解決辦法:
到DVWA安裝目錄下(.../WWW/DVWA-master/dvwa/includes)尋找文件dvwaPage.inc.php
-
打開(kāi)這個(gè)文件,然后在全文查找charset=utf-8,將所有utf-8修改為gb2312。
注意:有好幾處charset=utf-8,要全部修改成charset=gb2312。記得保存。
接下來(lái)再使用DVWA就不會(huì)亂碼啦。
Medium
1 查看服務(wù)器端代碼

str_replace() 函數(shù)替換字符串中的一些字符(區(qū)分大小寫(xiě))
str_replace(find,replace,string,count)
| 參數(shù) | 描述 |
|---|---|
| find | 必需。規(guī)定要查找的值。 |
| replace | 必需。規(guī)定替換 find 中的值的值。 |
| string | 必需。規(guī)定被搜索的字符串。 |
| count | 可選。一個(gè)變量,對(duì)替換數(shù)進(jìn)行計(jì)數(shù)。 |
array_keys() 函數(shù)返回包含數(shù)組中所有鍵名的一個(gè)新數(shù)組
array_keys(array,value,strict)
| 參數(shù) | 描述 |
|---|---|
| array | 必需。規(guī)定數(shù)組。 |
| value | 可選。您可以指定鍵值,然后只有該鍵值對(duì)應(yīng)的鍵名會(huì)被返回。 |
| strict | 可選。與 value 參數(shù)一起使用??赡艿闹担?/td> |
| true - 返回帶有指定鍵值的鍵名。依賴(lài)類(lèi)型,數(shù)字 5 與字符串 "5" 是不同的。 | |
| false - 默認(rèn)值。不依賴(lài)類(lèi)型,數(shù)字 5 與字符串 "5" 是相同的。 |
運(yùn)行實(shí)例
<!DOCTYPE html>
<html>
<body>
<?php
$a=array("Volvo"=>"XC90","BMW"=>"X5","Toyota"=>"Highlander");
print_r(array_keys($a));
?>
</body>
</html>
輸出結(jié)果: Array ( [0] => Volvo [1] => BMW [2] => Toyota )
相比Low級(jí)別的代碼,服務(wù)器端對(duì)ip參數(shù)做了一定過(guò)濾,即把”&&” 、”;”刪除,本質(zhì)上采用的是黑名單機(jī)制
但是對(duì) "&" 沒(méi)有進(jìn)行過(guò)濾
”&&”與” &”的區(qū)別:
Command 1&&Command 2
先執(zhí)行Command 1,執(zhí)行成功后執(zhí)行Command 2,否則不執(zhí)行Command 2
Command 1&Command 2
先執(zhí)行Command 1,不管是否成功,都會(huì)執(zhí)行Command 2
所以可以輸入
127.0.0.1&net user

由于使用的是str_replace把”&&” 、”;”替換為空字符,因此可以采用以下方式繞過(guò):
127.0.0.1&;&ipconfig
這是因?yàn)椤?27.0.0.1&;&ipconfig”中的” ;”會(huì)被替換為空字符,這樣一來(lái)就變成了”127.0.0.1&& ipconfig” ,會(huì)成功執(zhí)行

High
服務(wù)器端核心代碼

從源碼可以知道
黑名單看似過(guò)濾了所有的非法字符,但仔細(xì)觀(guān)察到是把”| ”(注意這里|后有一個(gè)空格)替換為空字符,于是 ”|”成了“漏網(wǎng)之魚(yú)”。
127.0.0.1|net user

Command 1 | Command 2
“|”是管道符,表示將Command 1的輸出作為Command 2的輸入,并且只打印Command 2執(zhí)行的結(jié)果
Impossible
服務(wù)端代碼

相關(guān)函數(shù)
stripslashes() 函數(shù)刪除由 addslashes() 函數(shù)添加的反斜杠
stripslashes函數(shù)會(huì)刪除字符串中的反斜杠,返回已剝離反斜杠的字符串
explode() 函數(shù)把字符串打散為數(shù)組
| 參數(shù) | 描述 |
|---|---|
| separator | 必需。規(guī)定在哪里分割字符串。 |
| string | 必需。要分割的字符串。 |
| limit | 可選。規(guī)定所返回的數(shù)組元素的數(shù)目 |
is_numeric(string)
檢測(cè)string是否為數(shù)字或數(shù)字字符串,如果是返回TRUE,否則返回FALSE。
Generate Anti-CSRF token
生成反CSRF令牌