webshell静态检测
一个PHP文件躺在服务器上,静态检测代码只有三行:$_GET['cmd']拼进system()。静态检测没有混淆,静态检测没有加密,静态检测连注释都懒得写。静态检测这种webshell,静态检测静态检测工具扫一眼就能揪出来——但现实中,静态检测没人会留这么蠢的静态检测后门。
真正的静态检测静态检测,是静态检测在和“变形”搏斗。攻击者把assert拆成字符串拼接,静态检测用base64_decode包一层,静态检测再塞进数组里绕两圈。静态检测你写正则匹配eval(,静态检测他就用create_function;你盯上create_function,静态检测他改用preg_replace的/e修饰符——直到PHP 7删掉这个特性,大家才松了口气。
我见过最刁钻的一个样本,把恶意代码藏进图片的EXIF信息里,用exif_read_data()读出来再执行。静态扫描器若只查文件内容,根本不知道那串像素点里藏着system('id')。这就像查毒品只看外观,人家把粉末混进面粉袋,你总不能把整袋面粉都倒了吧。
静态检测的核心逻辑其实不复杂:要么特征匹配,要么语法树分析。特征匹配快但脆,攻击者换个编码方式就绕过;语法树分析更稳,把代码解析成抽象结构,看有没有“用户输入→危险函数”的数据流。但后者费资源,一个大型CMS的PHP文件成千上万,全量解析能把服务器CPU拖到报警。
还有个被忽视的维度——文件时间戳和权限。正常运维不会在凌晨三点往/tmp/目录传PHP文件,更不会给它755权限。静态检测若只盯内容不盯上下文,等于警察只看人脸不看行为。
说句实话,纯静态检测永远赢不了。攻击者只要花十分钟研究你的规则库,就能写出绕过的样本。但别急着否定它——静态检测的价值在于“门槛”和“广度”。它把那些只会复制粘贴脚本的脚本小子挡在门外,也能在webshell刚落地、还没开始通信时就报警。真正的安全防线,靠的是静态检测筛一遍,动态沙箱跑一遍,流量监控盯长期行为。
我见过不少团队,把静态检测结果当圣旨,扫出高危就赶紧删文件。结果有一次,扫描器报警指向某个第三方插件的正常文件——那插件用了call_user_func动态调用,误报。运维手一抖删了,整站白屏。所以啊,工具是辅助,判断还得靠人。静态检测告诉你“这有可疑”,你得追问“为什么可疑”,而不是直接判死刑。
最后说个实操细节:别只检测.php后缀。攻击者把shell改成.php.jpg,或者用.pht、.php5之类的冷门后缀,Apache配置稍有不慎就能解析执行。静态检测的第一步,先确认你扫描的文件范围够不够宽——连后缀都覆盖不全,后面全是白搭。
