找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3295

积分

0

好友

427

主题
发表于 11 小时前 | 查看: 1| 回复: 0

在网络安全攻防演练或代码审计中,理解攻击者如何构造和隐藏 Webshell 是进行有效防御的关键。尤其是在对抗静态查杀和动态监控时,绕过对敏感函数名的直接引用,是 Webshell 免杀技术中的重要一环。本文将深入探讨在 PHP 环境中,几种无需直接书写 systemexec 等危险字符串即可获取并调用恶意函数的方法。

利用 get_defined_functions 获取函数

get_defined_functions 是 PHP 的一个内置函数,它能返回所有已定义函数的数组,其中就包含内部函数和用户自定义函数。这恰好为我们“寻找”可用的危险函数提供了一个绝佳的目录。

通过遍历这个数组,我们可以轻易地定位到如 systemexecpassthru 等可执行系统命令的函数。下图展示了从该函数列表中筛选出的部分高危函数,其中 create_function 被高亮显示:

PHP get_defined_functions 函数列表截图,显示包含 create_function 等函数名

更进一步,我们可以获取到如 system 这样的命令执行函数。下图展示了数组中的一部分,请注意第517个元素(键为[517])就是 system 函数:

PHP get_defined_functions 返回的数组片段,高亮显示 system 函数

一旦知道了目标函数在数组中的索引位置,调用它就变得非常简单。下面的代码演示了如何直接通过索引调用 exec 函数(索引516)来执行 whoami 命令:

<?php
$a=(get_defined_functions());
$a["internal"][516]("whoami");
?>

代码执行效果如下图所示,成功获取了当前系统用户:

使用 get_defined_functions 获取 exec 函数并执行 whoami 命令的输出结果

get_defined_constants 常量中提取

除了函数,PHP 的常量也可能暗藏玄机。get_defined_constants 函数会返回所有已定义常量的关联数组。攻击者可以从中寻找包含特定子串(如 “system”)的常量名,并通过字符串截取来“拼凑”出想要的函数名。

下图展示了部分常量列表,其中包含了大量以 INI_SYSTEM 等格式定义的常量:

PHP get_defined_constants 返回的大量常量定义截图

观察发现,常量名 INI_SYSTEM 恰好包含 SYSTEM 这个关键词。我们可以通过字符串操作,将其转换为小写的 system 并作为函数调用。以下是实现这一思路的完整代码:

<?php
$a=get_defined_constants();
foreach ($a as $key => $value){
    if (substr($key, 0, 7)=="INI_SYS"){
        $x= strtolower(substr($key, 4, 6));
        $x("whoami");
    }
}
?>

这段代码遍历所有常量,寻找以 “INI_SYS” 开头的常量名,然后截取其第4个字符开始的6个字符(即 “SYSTEM”),转换为小写后动态调用。执行结果成功输出了当前用户名:

利用 get_defined_constants 获取常量名并截取为 system 函数执行的截图

巧用自定义函数进行编码转换

这是一种更为隐蔽的手法,通过一个自定义的编码/解码函数,将一串看似无意义的数字还原成敏感的函数名。一个经典的例子如下:

<?php
function fun($a){
    $s = ['a','t','s','y','m','e','/'];
    $tmp = "";
    while ($a>10) {
        $tmp .= $s[$a%10];
        $a = $a/10;
    }
    return $tmp.$s[$a];
}

单看这个函数,很难猜出它的意图。但是,当我们用一个特定数字 451232 去调用它时:

echo fun(451232);

执行后,它会输出字符串 system。这个过程巧妙地利用了数学运算和数组索引,将数字“翻译”成了目标函数名。下图为执行该代码的输出结果:

自定义函数 fun 输入 451232 后输出 system 的截图

通过抛出异常间接获取字符串

PHP 的异常类在实例化时,会将传入的参数作为异常信息存储。结合上文的数字转换函数,我们可以通过抛出异常,再获取异常信息的方式来间接得到 system 字符串。这里以 ParseError 异常类为例。

我们先实例化一个 ParseError 异常,并将 fun(451232) 的结果(即 “system”)作为异常消息传入。然后,通过调用该异常对象的 getMessage() 方法,即可提取出这个字符串:

<?php
function fun($a){
    $s = ['a','t','s','y','m','e','/'];
    $tmp = "";
    while ($a>10) {
        $tmp .= $s[$a%10];
        $a = $a/10;
    }
    return $tmp.$s[$a];
}
$a = new ParseError(fun(451232));
echo $a->getMessage();

执行后,成功输出了 “system”。这种方法将敏感字符串的生成过程隐藏在了标准的错误处理流程中,增加了检测的难度。

通过 ParseError 异常 getMessage 方法获取 system 字符串的截图

利用 DirectoryIterator 读取文件系统

DirectoryIterator 类用于遍历目录。如果攻击者能够控制服务器上的文件名或目录名,那么他就可以创建一个名为 “system” 的文件或文件夹,然后通过脚本遍历目录来获取这个字符串。

例如,当前目录下存在一个名为 system 的文件夹。我们可以使用以下代码遍历并获取其名称:

<?php
// 创建FilesystemIterator实例
$iterator = new FilesystemIterator(dirname(__FILE__));
foreach ($iterator as $item) {
    // 输出文件和目录的属性
    echo $item->getFilename() . "\n";
}
?>

代码运行后,会列出当前目录下的所有条目,其中就包含了 system 目录,从而间接获取到了这个关键字。

使用 FilesystemIterator 遍历目录的代码截图

FilesystemIterator 遍历输出结果,包含 system 目录名

使用 pack 函数二进制打包构造

pack 函数用于将数据按指定格式打包成二进制字符串。这个函数功能强大,可以根据 ASCII 码值或十六进制数据构造出任意字符串,自然也能构造出 system

pack 函数支持多种格式码,例如 C 表示无符号字符,H 表示十六进制字符串高位在前。了解这些格式对于安全/渗透/逆向领域中的二进制数据处理非常有帮助。

下图展示了 pack 函数支持的部分格式字符:

pack 函数支持的格式字符类型说明表

方法一:使用 ASCII 码值 (C 格式)
s, y, s, t, e, m 的 ASCII 码值(115, 121, 115, 116, 101, 109)打包。

方法二:使用十六进制字符串 (H 格式)
直接传入 system 的十六进制表示 73797374656d

以下是两种方法的实现代码:

<?php
echo pack("C6", 115, 121, 115, 116, 101, 109);
echo pack("H*", "73797374656d");
?>

执行后,两行代码都会输出 system,这为在严格字符过滤环境下构造字符串提供了更多可能。

使用 pack 函数通过两种格式构造 system 字符串的代码及输出结果

总结与思考

本文介绍了在 PHP 中绕过直接书写敏感函数名来获取恶意函数的五种方法:从内置函数列表和常量中提取、利用自定义算法转换、通过异常机制泄露、读取文件系统信息以及使用二进制打包函数构造。这些手法本质上都是利用了 PHP 语言的动态特性(如可变函数 $func())和丰富的内置功能来隐藏真实意图。

对于防御方而言,理解这些构造技巧至关重要。仅依赖简单的字符串黑名单检测是远远不够的,需要结合静态代码分析、动态行为监控和上下文语义理解,才能更有效地识别和阻断这类隐蔽的 Webshell。安全是一个持续对抗的过程,在 云栈社区 等技术论坛中与同行交流最新的攻防案例,能帮助我们不断提升安全防御水位。




上一篇:观鸟平台数据接口逆向分析:RSA请求体与AES响应解密实战
下一篇:从工程师到架构师:一张成长蓝图,帮你拆掉思维里的墙
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-10 18:27 , Processed in 0.386147 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表