原文 https://www.yuque.com/ni4n/blogs/zpw349
漏洞原理
代码执行漏洞是指应用程序在调用“把字符串作为PHP代码执行”的函数时未对用户的传参严格过滤,致使用户可以将代码注入应用程序执行。
代码执行漏洞形成原因大概有以下几种:
- eval()和assert()函数
- preg_replace()函数
- 调用函数过滤不严
- 动态函数执行
eval()和assert()函数
函数解释
eval ( string $code )
把字符串 code 作为PHP代码执行。
assert( mixed $assertion )
参数需是函数或者表达式,才会执行
示例:
eval()
<?php
if (isset($_GET['cmd'])){
eval($_GET['cmd']); //未对参数进行过滤
}
?>
//payload:?cmd=phpinfo();
assert()
<?php
assert('phpinfo()');
?>
preg_replace()函数
函数解释
preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
//搜索$subject的$pattern部分,以$replacement替换掉$pattern;但当$pattern处,即第一个参数存在e修饰符时,$replacement的值会被当成php代码执行;但前提是匹配到$pattern
//但是在高版本中已经不行了
示例1:
<?php
$subject="hello hack";
$pattern='/hack/e';
$replacement=$_GET["name"];
echo preg_replace($pattern,$replacement,$subject)
?>
//payload:?name=phpinfo()
这是个简单的构造,然后在看个稍微复杂的
示例2:
<?php
preg_replace("/\[(.*)\]/e", '\\1', $_GET['str']);
?>
"\1"表示重复正则第一个圆括号内匹配到的内容
当我们传入[phpinfo()]时,$replacement="phpinfo()" 然后执行phpinfo()
//payload:?str=[phpinfo()]
然后说一下修饰符
调用函数过滤不严
在php中,有很多可以调用其他函数的函数;如call_user_func()和array_map()等,以一个参数为要调用的函数,其他的为要调用函数的参数;当其传入的函数名可控,就可以调用任意函数,执行任意代码。
call_user_func()
<?php
$cmd=$_GET['cmd'];
$var=$_GET['var'];
call_user_func($cmd,$var);
?>
//payload:?cmd=assert&var=phpinfo()
函数解释
call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。
动态函数执行
直接看示例吧
<?php
$_GET['a']($_GET['b']);
?>
//payload:?a=assert&b=phpinfo()
其意思就是接受GET请求的a参数,作为函数,b参数作为函数的参数。和call_user_func()有点相似。
漏洞修复
使用白名单过滤机制,严格控制用户传入的参数。