
核心要点(TL;DR)
- 挂马排查先看日志再比文件:日志定时间窗,哈希定被改文件。
- 用 find 按修改时间排序能快速缩小可疑文件范围。
- 建立哈希基线后定期比对,是发现静默篡改的最低成本手段。
- 清理后必须复验并修补入口,否则挂马会反复出现。
网站突然被搜索引擎标红、页面被插入陌生跳转,或者用户反馈打开就弹窗——多数运维的第一反应是「赶紧删掉可疑文件」,但删错文件可能让站点直接白屏,删漏文件则几天后再次被挂。真正高效的网站被挂马怎么检测,靠的不是肉眼翻目录,而是两条可验证的线索:Web访问日志的异常请求,以及文件哈希与时间戳的差异比对。本文给出一套可以直接照着敲命令的排查流程,帮你从「怀疑被挂马」走到「精确定位恶意代码」。
一、先定时间窗:从访问日志找异常请求
挂马的本质是攻击者写入或篡改文件,而写入动作通常伴随一次HTTP请求。所以第一步不是扫文件,而是缩小时间范围。
先看日志规模与格式,确认是Nginx还是Apache:
ls -lh /var/log/nginx/access.log*
zcat /var/log/nginx/access.log.*.gz | wc -l然后按几个高价值维度筛选:
- 高频POST:正常站点POST集中在登录、表单接口,若某IP短时间大量POST到陌生路径,高度可疑。
- 异常路径:包含
eval、base64、.php.、%00等特征的URL。 - 可疑UA与扫描器:空UA、sqlmap、nikto等工具指纹。
- 状态码分布:大量404后紧跟200,往往是在探测上传点。
awk '{print }' access.log | sort | uniq -c | sort -rn | head -20
awk ' ~ /POST/ {print }' access.log | sort | uniq -c | sort -rn | head
grep -Ei 'eval|base64|%00|\.php\.' access.log | tail -50把可疑请求的时间戳记下来,形成一个大致的时间窗,例如「6月12日 02:00 至 04:30」。这个窗口就是下一步文件比对的靶区,能把全站几万个文件缩小到几十个候选。
二、建哈希基线:用 sha256sum 做完整性比对
哈希比对的原理很直接:文件内容只要改动一个字节,SHA-256 值就会完全不同。前提是有一份「可信基线」。
如果此前没有基线,先用同版本源码包或最近一次备份生成参照清单:
cd /var/www/html
find . -type f -name '*.php' -print0 | xargs -0 sha256sum > /root/baseline.sha256
# 与当前站点比对
sha256sum -c /root/baseline.sha256 2>/dev/null | grep -v ': OK$'输出中标记为 FAILED 的文件即为内容不一致项。注意两点:缓存文件、上传目录、日志类文件会产生大量正常差异,比对前应排除;模板与配置文件被改动属于高优先级信号,需逐个人工确认。
若完全没有历史基线,可退一步用修改时间排序,同样能快速定位:
find /var/www/html -type f -mtime -7 -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort -r | head -50把结果与第一步的时间窗对照,落在窗口内、且不属于正常发版时间的文件,嫌疑最大。
三、关键词扫描:在候选文件中找恶意特征
时间与哈希只能告诉你「哪些文件变了」,还需要确认「变的是不是恶意代码」。对候选文件做特征扫描:
grep -rniE 'eval\(|base64_decode|gzinflate|str_rot13|assert\(|$_(POST|GET|REQUEST)\[.*\]\(' /var/www/html --include='*.php' -l常见的挂马特征包括:
- 单行超长混淆代码,变量名随机如
$GLOBALS['a1b2c3']; - 文件头部出现
<?php @eval($_POST[...])一类一句话木马; - 正常JS文件末尾被追加
document.write远程脚本; .htaccess中被加入AddType application/x-httpd-php .jpg之类的解析劫持。
同时检查隐藏文件与异常权限,攻击者常把webshell命名为 .index.php 或放在图片目录:
find /var/www/html -name '.*' -type f
find /var/www/html -type f -perm -o+w
ls -la /var/www/html/uploads | head四、交叉验证:确认入口与影响范围
找到可疑文件后不要立刻删除,先做三件事交叉验证:
- 用
stat查看修改时间,是否落在日志时间窗内; - 回查日志,该文件路径是否被外部实际请求过,请求来源IP是谁;
- 检查同目录、同时间段的其它文件,判断是单点篡改还是批量植入。
这一步决定了清理范围。若只删一个文件而入口(如过期的上传组件、弱口令后台)仍在,通常一周内会再次被挂。建议同步检查数据库中的异常管理员账号、计划任务 crontab -l 与系统账号 /etc/passwd 新增项。
五、清理复验与防护清单
确认恶意文件后,先改名隔离而非直接删除,观察站点是否正常,再彻底清除并复验:
mv suspect.php /root/quarantine/suspect.php.bak
# 清理后重新生成基线并比对
find . -type f -name '*.php' -print0 | xargs -0 sha256sum > /root/baseline_new.sha256| 检查项 | 操作要点 | 优先级 |
|---|---|---|
| 入口修补 | 升级CMS与插件,修改后台与数据库口令 | 高 |
| 上传目录 | 关闭脚本执行权限,限制文件类型 | 高 |
| 文件完整性 | 定时哈希比对,异常即告警 | 高 |
| 日志留存 | 日志异地备份,保留不少于30天 | 中 |
| 权限收敛 | 站点目录去除other写权限 | 中 |
在防护建议上,一次性排查只能解决当下问题,长期需要把哈希比对与日志告警做成常态机制。AegisX 提供网站文件完整性监控与Web攻击告警能力,可在文件被篡改或出现可疑请求时及时通知,把「事后排查」前移为「事中阻断」。
行动建议:今天就为站点生成第一份哈希基线并异地保存,同时确认Web日志保留策略;下次再遇到挂马告警,按「日志定窗口—哈希找差异—关键词确认—交叉验证—隔离复验」五步执行,排查时间可从数小时压缩到几十分钟。
常见问题(FAQ)
网站被挂马了,第一步应该做什么?
先别急着删文件,第一步是保留现场并确定时间窗。立即备份当前站点目录与近7天Web访问日志,记录发现时间,然后从日志中筛出可疑IP、异常UA和高频POST请求,锁定大致入侵时间段。有了时间窗,后续用文件修改时间与哈希比对才有明确靶区,避免全盘盲扫。
文件哈希比对需要提前准备吗?
需要。哈希比对的前提是有一份可信基线。建议在站点上线或每次发版后,对核心目录执行 sha256sum 生成清单并异地保存。若此前没有基线,可临时用同版本源码包或备份做参照,也可退而用修改时间排序加关键词扫描替代,但准确度会下降。
日志被清理了还能排查挂马吗?
仍可排查,但难度上升。可转向文件侧证据:按修改时间排序找异常文件、扫描 eval/base64_decode 等危险函数、检查 .htaccess 与计划任务、对比备份差异。同时查看系统层的 auth.log、cron 记录与数据库中的可疑管理员账号,尽量还原入侵路径。
怎么判断找到的是不是真正的恶意代码?
看三点:文件修改时间是否落在异常时间窗、内容是否含混淆编码或远程加载代码、是否被外部请求实际访问过。三者交叉验证可信度最高。对疑似文件先改名隔离而非直接删除,观察站点是否报错、日志是否仍有异常请求,确认后再彻底清除。
清理完挂马后如何防止再次发生?
关键是堵住入口并建立持续监测。修补CMS与插件漏洞、修改全部后台与数据库口令、关闭上传目录脚本执行权限,然后部署定时哈希比对与日志告警。AegisX 可提供网站文件完整性监控与Web攻击告警能力,把一次性排查转为常态化防护。