背景
最近在做一批历史站点的安全巡检时,遇到过几次比较典型的 Webshell 告警。实际排查下来,问题并不复杂:入口多是老旧组件、弱口令后台、历史遗留上传接口,落点则集中在可写目录、缓存目录和模板目录。
这类事件的价值不在于“发现一个木马文件”本身,而在于通过复盘把排查链路、代码审计点和后续加固动作沉淀下来。很多站点反复中招,往往不是因为攻击手法多高级,而是缺少一套稳定的处置流程。
本文只讨论防御视角下的排查、分析和修复方法,不涉及利用、控制、横向移动等攻击操作。
场景与初始现象
典型告警一般来自几类信号:
- EDR 或主机安全产品提示 Web 目录出现可疑脚本文件。
- Web 访问日志中出现异常 POST 请求,目标文件位于 upload、cache、tmp、template 等目录。
- 站点响应偶发异常,PHP-FPM、Java 进程或 Web Server 进程 CPU 波动。
- 某些业务目录出现修改时间异常的新文件,文件名伪装成图片、缓存或配置文件。
实际处置时,不建议一上来就删除文件。更稳妥的方式是先隔离、留证、确认入口,再做清理和加固。否则很容易出现“今天删、明天又出现”的情况。
排查思路
我一般按“文件、日志、进程、代码、配置”五条线并行看。这样做的好处是可以相互印证,避免只凭单个样本下结论。
一、可疑文件定位
首先看 Web 根目录下最近变更的脚本文件。以 Linux 环境为例,可以先按修改时间粗筛:
find /var/www/html -type f -mtime -7 \
\( -name "*.php" -o -name "*.jsp" -o -name "*.jspx" -o -name "*.asp" -o -name "*.aspx" \) \
-printf "%TY-%Tm-%Td %TH:%TM %p\n" | sort如果站点较大,可以重点关注不应存在脚本执行能力的目录,比如:
- upload、uploads、attachment、file
- cache、runtime、tmp、temp
- static、assets、public
- template、themes、views
还可以结合常见高危函数做静态搜索。注意这里不是靠关键字“一锤定音”,而是用来辅助发现异常文件:
grep -RInE "(eval|assert|system|shell_exec|passthru|proc_open|popen|base64_decode|gzinflate|str_rot13)" /var/www/html --include="*.php"对于 Java Web 应用,可以关注上传目录、临时解压目录和应用部署目录中的 JSP/JSPX 文件:
find /opt/tomcat/webapps -type f \( -name "*.jsp" -o -name "*.jspx" \) -printf "%TY-%Tm-%Td %TH:%TM %p\n" | sort排查时常见的异常特征包括:
- 文件名伪装成图片或缓存,例如 1.php、cache.php、logo.php、index1.php。
- 脚本内容高度压缩、混淆,正常业务代码风格明显不一致。
- 文件修改时间集中出现在非发布时间段。
- 上传目录出现可执行脚本文件。
- 文件权限异常,例如 Web 用户可写的范围过大。
二、日志关联分析
找到可疑文件后,要回到访问日志确认它是如何被访问或写入的。以 Nginx 为例:
grep "suspicious.php" /var/log/nginx/access.log*如果文件名不确定,可以按时间窗口检索 POST 请求、异常状态码和上传接口:
awk '$4 >= "[10/Oct/2026:01:00:00" && $4 <= "[10/Oct/2026:03:00:00" {print}' /var/log/nginx/access.log | grep "POST"常见需要重点看的字段:
- 请求时间:是否与文件创建或修改时间吻合。
- 请求方法:可疑文件首次访问前是否有 POST 上传行为。
- URI:是否命中上传接口、编辑模板接口、插件安装接口。
- User-Agent:是否异常、是否为空、是否与正常用户差异明显。
- 来源 IP:是否短时间内访问大量敏感路径。
- 状态码和响应大小:是否存在异常 200、500 或固定响应长度。
如果有 WAF、反向代理、负载均衡日志,也需要一起关联。很多时候源 IP 在 Nginx access.log 中已经是代理地址,需要结合 X-Forwarded-For 或上游日志还原。
三、进程与计划任务检查
Webshell 事件中,部分入侵者会尝试写入持久化任务或启动异常进程。排查时可以看当前进程、网络连接和计划任务。
ps aux --sort=-%cpu | head
ps aux | grep -E "(www-data|nginx|apache|tomcat|php-fpm)"
ss -antp计划任务重点看系统级和 Web 用户级:
crontab -l
ls -la /var/spool/cron/
ls -la /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/这里的目标不是做“猎奇式取证”,而是确认有没有超出 Web 层面的影响。如果发现异常下载器、反弹连接、未知二进制文件,应立即扩大处置范围,包括主机隔离、镜像留存和账号凭据轮换。
四、入口代码审计
只清理 Webshell 没有意义,入口不修复一定会复发。入口审计通常从日志中的可疑接口开始,重点检查以下几类问题。
1. 文件上传校验不完整
上传功能是最常见入口。安全的上传逻辑至少应同时考虑扩展名、MIME、文件内容、保存路径、文件名生成和执行权限控制。
典型风险点包括:
- 只检查前端或只检查 Content-Type。
- 黑名单方式过滤扩展名,遗漏大小写、双后缀、特殊解析场景。
- 用户可控保存路径或文件名。
- 上传目录允许脚本执行。
- 图片处理库未重新编码,导致伪装文件保留原内容。
较稳妥的思路是白名单扩展名、随机文件名、单独存储目录、禁止执行脚本,并在业务允许时进行图片重编码。
# Nginx 示例:禁止上传目录执行 PHP
location ^~ /uploads/ {
location ~* \.(php|php5|phtml|phar)$ {
deny all;
}
}2. 后台模板与插件功能暴露
很多 CMS 或内部系统提供模板编辑、插件上传、主题安装等功能。如果后台账号弱口令或权限划分不清,这些功能就会变成高风险入口。
审计时建议确认:
- 是否允许在线编辑可执行脚本。
- 插件安装包是否校验签名或来源。
- 管理员操作是否有审计日志。
- 后台是否暴露在公网。
- 是否启用多因素认证或至少强密码策略。
3. 反序列化、表达式注入与命令执行
这类问题在 Java、PHP 和 Python Web 应用中都很常见。排查重点不是简单搜索某个函数,而是看“用户输入是否进入危险调用链”。
例如 PHP 中需要关注:
- unserialize 处理用户可控数据。
- include、require 拼接用户输入。
- preg_replace 历史危险用法。
- 命令执行函数拼接参数。
- 模板引擎或表达式引擎直接处理用户输入。
Java 应用中则重点看:
- 历史高危组件版本,例如 Struts、Spring、Shiro、Fastjson 等。
- 文件上传组件和解析库。
- 后台管理接口是否缺少鉴权。
- 动态脚本、表达式、模板渲染是否接收外部输入。
五、样本分析的边界
Webshell 样本分析可以帮助判断影响范围,但不建议在生产环境直接执行。可以将样本复制到隔离环境中做静态分析,必要时再做受控动态分析。
静态分析时主要看:
- 是否存在参数入口,例如读取 POST、GET、Cookie、Header。
- 是否包含文件操作、命令执行、数据库操作、网络连接等能力。
- 是否有混淆、加密、动态函数调用。
- 是否尝试落地其他文件或修改配置。
对于混淆脚本,不要急着运行解码结果。可以先替换危险函数为打印函数,在隔离环境中逐步还原逻辑。原则是只观察,不触发危险行为。
处置步骤建议
一次相对完整的处置流程可以按下面顺序执行:
- 确认告警真实性,记录文件路径、哈希、时间戳、权限、属主。
- 临时隔离受影响站点或限制异常入口访问。
- 备份可疑文件、访问日志、错误日志、应用日志和系统日志。
- 排查同目录、同时间窗口、同属主下的其他异常文件。
- 关联日志确认首次访问时间、上传入口和来源。
- 检查进程、网络连接、计划任务、启动项和异常账号。
- 审计并修复入口漏洞。
- 清理 Webshell、临时文件和异常持久化项。
- 轮换相关凭据,包括后台账号、数据库账号、服务器账号、API Key。
- 补充监控规则,复查是否复发。
加固要点
从经验看,以下几项投入不大,但对降低复发很有帮助。
- 上传目录与代码目录分离,上传目录禁止脚本执行。
- Web 进程使用低权限用户运行,不赋予不必要的写权限。
- 后台入口限制访问来源,启用强密码和多因素认证。
- 关闭不必要的在线模板编辑、插件安装功能。
- 定期比对代码目录完整性,核心文件纳入版本管理。
- 及时升级框架、CMS、插件和中间件。
- 保留足够周期的访问日志和应用日志,避免事后无日志可查。
- 对高风险函数、异常文件创建、Web 目录脚本变更建立告警。
文件权限方面,一个常见原则是:代码目录默认只读,运行时目录按需可写,上传目录不可执行。不要为了方便直接给整个站点目录 777 权限。
# 示例:谨慎调整权限,具体用户和路径需按实际环境修改
chown -R root:root /var/www/html
chown -R www-data:www-data /var/www/html/runtime /var/www/html/uploads
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;常见误区
- 只删除木马文件,不修入口。
- 只看 Web 目录,不看计划任务和异常进程。
- 发现可疑关键字就直接判定木马,忽略业务代码上下文。
- 生产环境直接运行可疑样本进行“验证”。
- 日志保留时间太短,导致无法还原攻击路径。
- 把 WAF 当成唯一防线,忽略代码和权限问题。
总结
Webshell 排查本质上是一次小型事件响应:先定位异常,再关联日志,还原入口,最后修复和加固。单点清理往往只能解决眼前问题,真正有价值的是建立可复用的检查清单和处置流程。
对中小团队来说,优先把三件事做好:上传目录禁止执行、后台权限收敛、日志可追溯。很多看似复杂的入侵事件,最后都能回到这些基础问题上。
推荐意见