对互联网业务来说,最高频的安全事件不是服务器被提权,而是网站被传了 Webshell(网页后门):攻击者通过一个上传漏洞或反序列化漏洞,往 Web 目录塞了个 shell.php/cmd.aspx,之后就能随时命令执行、翻数据库。
这类事件响应有鲜明的”Web 特色”:入口证据主要在访问日志里,后门证据主要在文件里。这篇把排查链路讲清。
所有排查仅用于你自有或已授权的业务系统。排查前备份 Web 目录与日志,保护现场再动手。
第一步:从访问日志找”异常请求”
Web 服务器的访问日志(Nginx 的 access.log、Apache 的 access_log、IIS 的日志)记录了每一次请求的 URL、来源 IP、状态码、User-Agent。入侵往往留下痕迹:
# 找返回 200 的可疑脚本访问(如访问了 shell 文件)
grep -Ei "\.(php|asp|aspx|jsp|jspx)\?" access.log | grep " 200 "
# 找常见漏洞利用特征(SQLi/上传/遍历)
grep -Ei "(union select|into outfile|/../|%00|cmd=|exec=|eval\()" access.log
# 找扫描器特征(sqlmap、AWVS、御剑等 UA)
grep -Ei "(sqlmap|awvs|nessus|masscan|nmap|python-requests)" access.log
# 按时间窗口看某 IP 的全部请求
grep "192.0.2.10" access.log
顺着可疑 IP 的完整请求序列,往往能还原出”先扫漏洞、再利用成功、最后传马”的全过程——这就是入口线索。
第二步:识别 Webshell 特征
Webshell 本质是”能被 HTTP 触发执行系统命令的网页脚本”。常见特征:
- 文件名可疑:
shell.php、x.php、upload.asp、随机名如a1b2c3.jsp。 - 内容含危险函数:
- PHP:
eval、assert、system、exec、passthru、proc_open、create_function。 - ASP/ASPX:
eval、Execute、Process.Start、Server.CreateObject("WScript.Shell")。 - JSP:
Runtime.getRuntime().exec、ProcessBuilder、JShell。
- PHP:
- 体积小但功能全,常带密码参数(如
?cmd=whoami、?pass=xxx)。 - 近期创建/修改,且位于上传目录或非常规路径。
# 在 Web 目录搜高危函数(节选)
grep -rEi "(eval\(|system\(|exec\(|passthru|Runtime\.getRuntime)" /var/www/html --include=*.php
# 找近期新增/修改的文件
find /var/www/html -mtime -7 -type f
# 看文件大小异常小的脚本
find /var/www/html -name "*.php" -size -2k
第三步:定位并利用时间关联
关键技巧:用文件修改时间反查日志。当你找到 shell.php 的创建时间是 03:14,就去日志里查 03:14 前后谁访问了能上传/写文件的接口——多半就是传马的那次请求。两者一关联,入口漏洞就坐实了。
# 看某文件精确修改时间
stat /var/www/html/uploads/shell.php
# 然后去日志查该时间窗口的请求,定位上传动作
第四步:判断利用了哪个漏洞
光删文件不够,必须知道”洞在哪”,否则补不上还会再被传。结合日志特征推断:
- 大量
POST /upload带图片马 → 文件上传漏洞。 POST带{"@type":...}→ Fastjson 反序列化。- URL 带
class.module=/Spring特征 → Spring 表达式/数据绑定。 - 带
../或%2e%2e→ 路径遍历/文件包含。 - 带
union select→ SQL 注入(可能进一步写文件)。
这一步需要你对本站用的框架/组件有了解(参见”Java 生态漏洞""Web 安全”等子分类),把日志特征和已知漏洞对上号。
第五步:清理与验证
- 隔离:把站点切到维护页或临时下线涉事接口,阻断继续被利用。
- 清除:删除确认恶意的 Webshell 文件;恢复被篡改的页面/模板(从干净备份或版本库拉)。
- 修补:修复入口漏洞(打补丁、改代码、加 WAF 规则)。
- 验证:清完后观察访问日志是否还有可疑请求;用文件完整性校验(对核心目录算哈希基线,比对是否再有改动)。
- 溯源:确认攻击者是否借 Webshell 进一步读了数据库、建了系统账户、做了提权——若有,按主机应急流程继续查。
常见误区
- 只删 shell 不修漏洞:删了一个,明天又传一个,陷入”打地鼠”。
- 只清 Web 不查主机:攻击者可能已借 Webshell 提权、建了系统后门,Web 干净了主机还被控。
- 不看日志直接全盘恢复:恢复后不知道漏洞在哪,等于没处置根因。
- 把正常业务脚本误删:
eval等函数在合法框架(如模板引擎)里也会出现,需结合上下文判断,别误伤。
进阶:文件完整性监控(FIM)
与其每次出事再查,不如平时给 Web 目录建哈希基线:
# 生成基线
find /var/www/html -type f -exec sha256sum {} \; > /evidence/web-baseline.txt
# 事后比对,找出被新增/篡改的文件
sha256sum -c /evidence/web-baseline.txt # 列出变更
find /var/www/html -type f -exec sha256sum {} \; | diff - /evidence/web-baseline.txt
配合 OSSEC/Wazuh 等 HIDS 做实时 FIM,文件一被改就告警,能把”事后救火”提前成”事中阻断”。
自测题
- 为什么 Web 入侵的入口证据主要在访问日志、后门证据主要在文件?
- “用文件修改时间反查日志”能帮你得到什么结论?
- 只删 Webshell 不修漏洞,为什么是无效处置?
- 文件完整性监控(FIM)在 Web 应急里解决什么问题?
实战要点与深度解析
Web 应急里最容易被低估的环节,是只删 shell 不修业务逻辑漏洞。举个典型:某站有个”头像上传”功能,只在前端做了图片类型校验,后端没校验,攻击者传了 shell.php。应急人员删了 shell,却没改后端校验,三天后攻击者又传一个。这类”业务逻辑缺陷”(而非单纯文件上传漏洞)靠 WAF 特征也难拦,因为请求看起来就是”正常上传了一张图”。根治必须回到代码层:后端强制校验文件头、重命名随机化、上传目录禁执行、存储与执行分离(传到对象存储而非 Web 目录)。
再谈一个进阶手法:内存马(无文件 Webshell)。传统 Webshell 是落盘的 .php/.jsp 文件,用 find 加关键字就能搜到。但高级攻击者把恶意代码注入到运行中的 Web 容器内存(如 Tomcat 的 Valve、Spring 的 Controller 动态注册),磁盘上根本没有文件,传统文件扫描完全失明。排查内存马要靠:看 Web 容器是否有异常加载的类、是否有非预期的 Filter/Valve、用专用工具(如 copagent、arthas)dump 内存分析。这再次说明”文件层检查”有盲区,必须结合进程/内存层。
关于 时间线反查的精确度:前面讲”用 shell 文件的 mtime 反查日志”。但要注意,攻击者可能篡改文件时间(touch -d 改 mtime/atime)来误导溯源。所以不能只信文件时间,要交叉验证:看 Web 日志里该 URL 首次被访问的时间、看应用审计日志、看版本控制系统(Git)里该文件是否曾被提交——多源时间对不上,就说明有人动了手脚。溯源的本质是”多源互证”,单一时间戳不可尽信。
还有一个运维侧的长效动作:把 Webshell 检测融入 CI/CD。与其每次出事再救,不如在代码上线前就用安全扫描(SAST、依赖扫描、敏感函数检测)拦住危险代码,并在上线后用 HIDS/文件完整性监控持续盯 Web 目录。把”事后应急”前移到”事前预防 + 事中阻断”,才是 Web 安全的成熟形态。
最后提醒:删除前务必先取证。很多应急人员看到 shell.php 第一反应是 rm,结果攻击者用的哪个漏洞、从哪来的、有没有顺手拖库,全成了谜。正确顺序是先 cp 留证(算哈希)、再分析、最后清除,并把样本提交情报平台丰富 IOC。
进阶速记与误区辨析
Web 入侵排查里同样有几组容易让人半途而废的情况,专门辨析。
第一组,删马与修洞。把 Webshell 文件删掉只是把症状拿掉,真正的入口漏洞还在,过两天又会被传一个。处置必须顺着文件创建时间去反查日志,找到是利用了哪个漏洞传进来的,把洞补上才算闭环。
第二组,落盘马与内存马。传统 Webshell 是磁盘上的脚本文件,用搜索关键字就能找到。但高级攻击者把恶意代码注入到运行中的容器内存里,磁盘上根本没有文件,传统文件扫描完全失明。排查不能只盯文件,还要看进程和内存里的异常加载。
第三组,文件时间与真实时间。攻击者可能篡改文件的时间来误导溯源,所以不能只信文件自己的时间戳。要把 Web 日志里该地址首次被访问的时间、版本控制系统里该文件是否曾被提交这些多源时间拿来互证,对不上的就说明有人动过手脚。
第四组,事后救火与事前预防。每次出事再救火成本极高,更成熟的做法是把危险代码检测融进上线前的检查,并在上线后用文件完整性监控持续盯着 Web 目录。把事后应急前移到事前预防和事中阻断,才是 Web 安全的成熟形态。
速记收尾:删马必修洞、落盘还要看内存、时间要多源互证、救火不如早防。四句话对应 Web 应急四个关键判断点。
这一篇你该记住的
- 入口在日志:用 access.log 找可疑脚本访问、漏洞利用特征、扫描器 UA。
- Webshell 特征:可疑文件名、危险函数(eval/system/Runtime.exec)、近期修改、位于上传目录。
- 用文件 mtime 反查日志时间窗口,锁定上传动作与入口漏洞。
- 结合日志特征判断利用了哪类漏洞(上传/反序列化/表达式注入/遍历/SQLi)。
- 清理顺序:隔离 → 删马+恢复 → 修漏洞 → 验证 → 溯源主机。
- 进阶用 FIM 建哈希基线,变”事后救火”为”事中阻断”。
下一篇我们专门讲 日志分析与溯源,把时间线还原出来。