概述
- 类似于SQL注入,可以吧SQL语句注入到SQL服务执行
- PHP代码执行则是吧代码 注入应用中最终到WebServer去执行,这样的函数如果没有过滤,相对于存在一个后门代码执行
函数
- eval()
- assert()
- preg_replace()
- call_user_func()
- call_user_func_arry()
- array_map()等
挖洞经验
- eval()和assert()函数导致的代码执行漏洞大多是因为载入缓存或者模板以及对变量的处理不严格导致,比如直接吧一个外部可控的参数直接拼接到模板里面然后调用这两个函数去当成PHP代码执行
- preg_replace()函数的代码执行需要/e参数,这个函数本身是用来处理字符串的,因出现的漏洞比较多的是对字符串的处理,比如URL,HTML标签以及文章内容等过滤功能
- call_user_func_arry()和array_map()函数的功能是调用函数,多用在框架里面动态调用函数,一般比较小的程序容易出现这种方式的代码执行比较少,array_map()函数的作用是调用函数并去除第一个参数外其他参数为数组,通常会写死一个参数,即调用的函数,类似三个函数功能的函数还有很多
eval和assert函数
- 这两个函数原本的作用就是动态执行代码,所以它们的参数就是PHP代码,我们来看看怎么使用的,测试代码如下:
<?php
$q = $_GET['q']; //获取用户输入的参数q
$id = $_GET['id']; //获取用户输入的参数id
eval("\$get = $id;"); //eval函数对$shiyanlou赋值
echo $q; //打印q
echo $get; //打印赋值过后的get
?>
我们来请求一次
- 请求变量q时候
- 并没有执行php代码
- 请求变量id时候
- 发现执行了php代码
结论
- 如果变量被传入eval和asser函数,该变量值打印出来的代码可以直接执行PHP代码
preg_replace函数
- preg_replace函数的作用是对字符串进行正则处理,下面我们来看看它什么情况下才会出现代码执行漏洞
它的参数返回如下
- mixed preg_replace (mixed $pattern ,mixed $replacement , mixed
$subject [, int $limit = -1 [, int &$count]] ) - 这段代码的含义是搜索$subject 中匹配$pattern的部分,以$replacement进行替换,而当$pattern处即第一个参数存在e修饰符时,$replacement的值会被当成PHP代码执行,我们来看一个简单的例子(1.php)
<?php
preg_replace("/\[(.*)\]/e",'\\1',$_GET['str']);
?>
- 正则的意思是从$_GET[‘str’]变量里面搜索中括号[]中间的内容作为第一组结果,preg_replace()函数第二个参数’\1’代表这里用第一组结果填充,这里是可以直接执行代码的
- 所以当我们请求/1.php?str=[phpinfo()]时候,则执行phpinfo(),结果如下
call_user_func()和array()_map()函数
-
call_user_func()和array_map()等数十个函数有调用其他函数的功能,其中一个参数作为要调用的函数名,那如果这个传入的参数名可控,那就可以调用意外的函数来执行我们的代码,也就是存在代码执行漏洞
-
我们用call_user_func()函数来举列。函数的作用是调用函数并且第二个参数作为要调用的函数的参数,官方文档如下:
mixed call_user_func ( callable $callback [,mixed $parameter [ , mixed $…]]) -
该函数第一个参数为回调函数,后面的参数为回调函数的参数,测试代码如下:
<?php
$b=$_GET['b'];
call_user_func($_GET['a'],$b);
?>
- 当请求php?a=assert&b=phpinfo()时候,执行了php代码
- assert为要调用的函数,phpinfo为该函数调用的参数
动态函数执行
- 由于PHP特性原因,PHP的函数可以直接由字符串拼接,这导致了PHP在安全的控制又加大了难度,比如增加了漏洞数量和提高了PHP后门的查杀难度
- 要找漏洞就要先理解为什么程序要这么写,不小知名的程序中也用到动态函数的写法,这种写法跟call_user_func的初衷是一样的,大多用在框架里面,用来更简单更方便的调用函数,但是一旦过滤不严格就会造成代码执行漏洞
- PHP动态函数写法为 “变量(参数)”,我们来看一个动态函数后门的写法:
<?php
$_GET['a']($_GET['b']);
?>
- 代码的意思就是接受GET请求的a参数,作为函数,b参数作为函数的参数,当请求a参数值为assert,b参数为phpinfo()的时候打印出phpinfo信息,请求如下:
- php?a=assert&b=phpinfo()
要挖掘这种形式的代码执行,需要找可控的动态函数名