文章目录
代码注入
PHP 可能出现代码注入的函数:eval()、preg_replace+/e()、assert()、call_user_func()、call_user_func_array()、create_function()等
查找程序中程序中使用这些函数的地方,检查提交变量是否用户可控,有无做输入验证。
1、eval()函数
eval 函数将输入的字符串参数当作 PHP 程序代码来执行
函数原型:
mixed eval(string code_str) //eval 注入一般发生在攻击者能控制输入的字符串的时候
//test.php
<?php
$var = "var";
if (isset($_GET["arg"]))
{
$arg = $_GET["arg"];
eval("\$var = $arg;");
echo "\$var =".$var;
}
?>
当我们提交 http://www.sectop.com/test3.php?arg=phpinfo();
漏洞就产生了.
2、preg_replace+/e()函数
preg_replace — 执行正则表达式的搜索和替换
mixed preg_replace( mixed $pattern , mixed $replacement , mixed $subject [, int $limit ] )
在subject中搜索pattern模式的匹配项并替换为replacement。如果指定了limit,则仅替换limit个匹配,如果省略limit或者其值为-1,则所有的匹配项都会被替换。
/e 修正符使preg_replace()将replacement参数当作PHP代码(在适当的逆向引用替换完之后)。提示:要确保replacement构成一个合法的PHP代码字符串,否则PHP会在报告在包含preg_replace()的行中出现语法解析错误。
<?php
function test($str){
//......
//......
return $str;
}
echo preg_replace("/\s*\[php\](.+?)\[\/php\]\s*/ies", 'test("\1")', $_GET["h"]);
?>
提交?h=[php]{${phpinfo()}}[/php]
,phpinfo()就会被执行。
在php中,双引号里面如果包含有变量,php解释器会将其替换为变量解释后的结果;单引号中的变量不会被处理。注意:双引号中的函数不会被执行和替换。
在这里我们需要通过{KaTeX parse error: Expected 'EOF', got '}' at position 3: {}}̲构造出了一个特殊的变量,`'t…{phpinfo()}}")'`,达到让函数被执行的效果 ${phpinfo()} 会被解释执行。
3、assert()
编写程序时,常会做出一定的假设,那断言就是用来捕获假设的异常,我们也可以认为断言是异常的一种特殊形式。
断言一般用于程序执行结构的判断,不可让断言处理业务流程。用的最多的场景就是单元测试,一般的单元测试框架都采用了断言。
在 PHP 中,采用 assert()函数对表达式进行断言。
1、先看一个正常使用断言assert()
try {
assert('a +== 1');
} catch (Throwable $e) {
echo $e->getMessage(), "\n";
}
运行结果为:
Failure evaluating code:
a +== 1
2、但是assert()与eval()函数一样,都会执行任何的PHP代码,我们按照如下方式,便可造成代码注入。
function demo(){
file_put_contents('data.log', 'shockerli.net');
return true;
}
$func = $_GET["func"];
assert("$func()");
4、call_user_func()
all_user_func — 把第一个参数作为回调函数调用
call_user_func(callable $callback, mixed $parameter = ?, mixed $... = ?): mixed
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。
callback:将被调用的回调函数(callable)。
parameter:0个或以上的参数,被传入回调函数。
如下示例:把完整的函数作为回调传入call_user_func()
test1.php
<?php
call_user_func(function($arg) { print "[$arg]\n"; }, 'test');
?>
5、call_user_func_array()
用一个数组作为参数调用一个回调函数·返回值为回调函数执行的结果或者为false,要传递参数给函数,作为一个索引数组。
call_user_func_array的作用和call_user_func的作用一样,不同的是call_user_func用回调函数处理字符,而call_user_func_array用回调处理数组,也就是说call_user_func_array的参数二只能为数组。
6、create_function()
适用范围:PHP 4> = 4.0.1,PHP 5,PHP 7
功能:根据传递的参数创建匿名函数,并为其返回唯一名称。
语法:
create_function(string $args,string $code)
string $args 声明的函数变量部分
string $code 执行的方法代码部分
示例:WordPress <= 4.6.1的任意代码执行漏洞
function make_plural_form_function($nplurals, $expression) {
$expression = str_replace('n', '$n', $expression);
$func_body = "
\$index = (int)($expression);
return (\$index < $nplurals)? \$index : $nplurals - 1;";
return create_function('$n', $func_body);
}
不过从PHP 7.2.0开始,create_function()
被废弃了。