文章目录
代码执行漏洞
PHP代码执行漏洞可以将代码注入到应用中,最终到webserver去执行。该漏洞主要存在于eval()、assert()、preg_replace()、call_user_func()、array_map()以及动态函数中。
挖掘思路
- 用户能够控制函数的输入
- 存在可执行代码的危险函数
常见危险函数
eval()和assert()
eval()、assert()将输入的字符串参数当作PHP代码来执行.
举个例子:
<?php
if(isset($_GET['cmd']))
{
$cmd = $_GET['cmd'];
eval("$cmd");
#assert("$cmd");
}else
{
echo '当前没有可执行的代码!';
}
php也是可以执行系统命令的,通过**system()**函数实现:
回调函数
call_user_func
具体可以这么实现:
<?php
function callBack(){
$b = $_GET['cmd'];
eval($b);
}
# 回调函数
call_user_func('callBack');
payload:
?cmd=phpinfo();
动态执行函数
- 定义一个函数
- 将函数名(字符串)赋值给一个变量
- 使用变量名代替函数名动态调用函数
测试代码:
<?php
# a作为函数,b作为函数的参数
$_GET['a']($_GET['b']);
payload:
?a=assert&b=phpinfo()
preg_replace()代码执行
preg_replace()函数就是通过正则替换,但是当正则中包含变量的情况下,会造成一个代码执行。
第一个参数
先来举一个例子,preg_replace中/e模式会将过滤后的字符串当作php代码执行,假如它将我们输入的内容拼接到了正则表达式中,那么我们可以构造一个含有代码执行漏洞的正则表达式:
<?php
echo $cmd = $_GET['cmd'];
echo '<br>';
echo $Str = $_GET['str'];
preg_replace("/<php>(.*?).$cmd","\\1","$Str");
根据正则构造payload:
?cmd=1/e&str=<php>system(whoami);-1--
第二个参数
第二个参数是,替换的字符串,当正则匹配上之后,程序将匹配的内容替换为第二个参数中的内容,如果第二个参数用户可控,那么也有可能造成代码执行:
<?php
preg_replace("/.ak.*php/e",$_GET['cmd'],$_GET['str']);
构造payload:
?str=1akphp&cmd=system(whoami)
第三个参数
假如我们对输入可控,程序又没有做严格的替换,也会代码执行:
<?php
preg_replace("/\[php\](.*?)ak/e","\\1",$_GET['str']);
修复方案
- 尽量不要执行外部应用程序或命令
- 使用自定义函数或函数库来代替外部应用程序或命令的功能
- 使用escappeshellarg()函数过滤
- 使用safe_mode_exec_dir来指定可执行文件路径
- 将执行函数的参数做白名单限制,在代码或配置中限制某些参数