跳转到帖子

背景

WebShell 排查是应急响应里比较常见、也比较容易被低估的一类工作。很多站点被入侵后,最先看到的不是漏洞利用过程,而是异常文件、异常进程、可疑访问日志或者主机告警。真正难的地方在于:如何判断 WebShell 是否仍然可用、攻击入口在哪里、是否存在持久化和横向扩散。

这篇文章整理的是一次较典型的内网 Web 服务器排查思路,重点放在文件分析、日志关联、代码审计和处置闭环上。内容尽量偏方法论,不涉及攻击利用引导,适合做日常排查清单参考。

场景描述

某业务系统部署在 Linux 主机上,技术栈为 Nginx + PHP-FPM,应用目录存在历史遗留代码和多个上传功能。安全设备告警显示:某 PHP 文件存在高危木马特征,同时 Web 访问日志中出现少量异常 POST 请求。

初步信息如下:

  • 异常文件位于业务上传目录下,扩展名为 .php。
  • 文件修改时间集中在凌晨低峰期。
  • 访问来源 IP 较少,但 User-Agent 不稳定。
  • 业务目录中存在多个可写目录,权限管理较粗。

排查目标

这类事件不建议只删除单个可疑文件就结束。比较稳妥的目标应该包括:

  • 确认 WebShell 的数量、位置和影响范围。
  • 判断是否存在同类变种、隐藏文件或后门逻辑。
  • 定位可能的上传入口或代码缺陷。
  • 确认是否有命令执行、文件写入、数据库访问等后续行为。
  • 完成修复、加固和复盘,避免再次落地。

第一步:保护现场与基础取证

发现可疑文件后,建议先不要直接编辑或删除。可以先做副本留存,并记录文件元信息。这样后续关联时间线、确认入侵窗口时会更可靠。

cd /var/www/html

# 记录可疑文件信息
stat uploads/avatar/2024/xx.php
sha256sum uploads/avatar/2024/xx.php
ls -alh uploads/avatar/2024/xx.php

# 只读方式备份
mkdir -p /root/ir_backup/webshell_sample
cp -a uploads/avatar/2024/xx.php /root/ir_backup/webshell_sample/

如果环境允许,建议同时备份相关日志,避免日志轮转导致证据丢失。

mkdir -p /root/ir_backup/logs
cp -a /var/log/nginx/access.log* /root/ir_backup/logs/
cp -a /var/log/nginx/error.log* /root/ir_backup/logs/
cp -a /var/log/php-fpm/*.log /root/ir_backup/logs/ 2>/dev/null
注意:线上业务环境处理时要控制动作范围。大规模递归扫描、压缩全站文件、直接重启服务,都可能影响业务或破坏现场。

第二步:文件层面排查

WebShell 常见特征包括混淆函数、动态执行、异常编码、短变量名、非业务路径 PHP 文件等。但不能只依赖关键字判断,因为很多正常框架也会使用反射、回调或序列化相关能力。

可以从可写目录开始查找异常 PHP 文件:

# 查找最近 7 天变更的 PHP 文件
find /var/www/html -type f -name "*.php" -mtime -7 -print

# 查找上传目录中的 PHP 文件
find /var/www/html/uploads -type f \( -name "*.php" -o -name "*.phtml" -o -name "*.phar" \) -print

# 查找隐藏文件和非常规扩展
find /var/www/html/uploads -type f -name ".*" -print

再结合关键函数做初筛:

grep -RIn --include='*.php' -E "eval\s*\(|assert\s*\(|system\s*\(|shell_exec\s*\(|passthru\s*\(|proc_open\s*\(|popen\s*\(|base64_decode\s*\(|gzinflate\s*\(" /var/www/html 2>/dev/null

这里需要注意两点:

  • base64_decode、gzinflate 并不天然等于恶意代码,需要结合上下文。
  • 有些 WebShell 会用字符串拼接、变量函数、字符编码等方式规避简单 grep,需要人工复核。

第三步:样本代码分析要点

分析可疑 PHP 文件时,可以先不执行代码,优先静态阅读。常见关注点如下:

  • 是否读取了请求参数,例如 $_POST、$_GET、$_REQUEST、php://input。
  • 是否存在动态函数调用,例如 $func($arg)。
  • 是否存在解码、解压、拼接后再执行的逻辑。
  • 是否有文件写入、删除、目录遍历、命令执行相关调用。
  • 是否伪装成图片、缓存、模板、日志文件。

例如某些后门会把关键函数拆开拼接,静态特征不明显:

$a = 'ba' . 'se64' . '_decode';
$b = 'cre' . 'ate' . '_function';
$c = $a($_POST['x']);
$b('', $c);

这类代码的核心风险不在于某个单独函数,而在于“外部输入经过处理后进入动态执行路径”。代码审计时应重点标记这条数据流。

第四步:日志关联分析

文件确认后,需要反查访问日志。可以从文件名、目录名、修改时间附近入手。

# 根据可疑文件名定位访问记录
grep "xx.php" /var/log/nginx/access.log*

# 查看某时间段附近的访问情况
zgrep "12/Mar/2024:02:" /var/log/nginx/access.log* | head -n 50

# 统计访问可疑文件的来源 IP
zgrep "xx.php" /var/log/nginx/access.log* | awk '{print $1}' | sort | uniq -c | sort -nr

分析日志时建议关注这些字段:

  • 首次访问时间:可能接近文件上传或验证时间。
  • 请求方法:异常文件如果大量接收 POST,风险较高。
  • 状态码:200、500、403 都有意义,500 可能是执行失败或环境不匹配。
  • Referer:若来自上传接口或后台页面,可能指向入口。
  • User-Agent:脚本化访问通常较杂乱,但不能单独作为判断依据。

如果 Nginx 日志没有记录请求体,可以结合 PHP-FPM slowlog、应用日志、安全设备日志进一步确认是否发生过命令执行或文件操作。

第五步:定位入口漏洞

WebShell 落地通常离不开文件写入能力。常见入口包括上传校验缺陷、后台编辑模板、任意文件写入、解压缩目录穿越、插件漏洞、弱口令后台等。

以上传功能为例,审计时可以检查:

  • 是否只依赖前端校验文件类型。
  • 后端是否只检查扩展名,未验证 MIME 和文件内容。
  • 是否允许上传到 Web 可执行目录。
  • 是否存在双扩展名、大小写扩展、特殊后缀解析问题。
  • 文件名是否由用户完全控制。
  • 是否存在历史兼容配置导致上传目录可执行 PHP。

Nginx + PHP-FPM 场景下,还要检查 PHP 解析范围是否过宽。例如不应让上传目录中的脚本被 PHP-FPM 处理。可以通过 location 策略限制:

location ^~ /uploads/ {
    types { }
    default_type application/octet-stream;
    add_header X-Content-Type-Options nosniff;

    location ~ \.php$ {
        return 403;
    }
}

如果业务允许,更推荐上传文件使用对象存储或独立静态域名,并确保该位置没有脚本执行能力。

第六步:主机侧检查

确认 WebShell 后,还需要判断攻击者是否进一步操作主机。可以检查进程、计划任务、启动项、临时目录和账号变化。

# 查看异常进程
ps auxf

# 查看网络连接
ss -tunap

# 检查计划任务
crontab -l
ls -al /var/spool/cron/ /etc/cron.* 2>/dev/null

# 检查近期修改文件
find /tmp /var/tmp /dev/shm -type f -mtime -7 -ls 2>/dev/null

# 检查登录记录
last -a | head
lastlog | head

如果发现异常下载器、反连进程、挖矿程序或陌生账号,需要扩大响应范围。单纯清理 Web 目录已经不够,应考虑主机隔离、凭据轮换和镜像级取证。

第七步:清理与加固

处置阶段建议按顺序进行,避免清理了文件但入口还在,导致短时间内再次被写入。

  • 先确认入口漏洞,临时下线或限制对应功能。
  • 备份样本和日志后清理 WebShell 及同类文件。
  • 修复上传、文件写入、模板编辑等危险功能。
  • 调整上传目录权限,禁止脚本执行。
  • 检查 Web 目录属主属组,避免 Web 用户拥有不必要写权限。
  • 轮换后台账号、数据库账号、服务器账号等敏感凭据。
  • 补充监控规则,覆盖新增 PHP 文件、异常 POST、可写目录变更。

权限收敛示例:

# 示例:代码目录只读,上传目录单独可写
chown -R root:root /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;

chown -R www-data:www-data /var/www/html/uploads
find /var/www/html/uploads -type d -exec chmod 750 {} \;
find /var/www/html/uploads -type f -exec chmod 640 {} \;
权限配置需要结合实际部署用户调整。不要机械复制命令到生产环境,尤其是多应用共用目录的老环境。

常见误区

  • 只删文件不修入口:这是最常见的复发原因。
  • 只看 WebShell,不看日志时间线:容易漏掉横向移动和二次投放。
  • 完全依赖特征扫描:混淆样本、业务混杂代码会带来漏报和误报。
  • 没有保留样本和日志:后续复盘、定责、规则沉淀都会受影响。
  • 把上传目录放在可执行路径:这是 WebShell 落地后可用的关键条件之一。

建议的长期监控点

监控项价值建议
Web 目录新增脚本发现异常落地文件重点监控 uploads、cache、tmp、template
异常 POST 请求识别后门交互行为关注低频但固定路径的 POST
PHP 危险函数调用辅助发现命令执行结合 EDR、审计日志分析
可写目录权限变化发现持久化准备动作对 Web 用户可写范围做基线
计划任务变化发现主机持久化记录 crontab 和系统 cron 变更

总结

WebShell 排查不是“找到一个可疑文件并删除”这么简单。比较可靠的处理方式,是把文件样本、访问日志、代码入口、主机行为串成一条时间线,再围绕入口修复和权限收敛做闭环。

实际工作中,建议沉淀三类东西:一是可写目录和脚本执行权限基线,二是上传和文件写入功能的审计清单,三是适合自身业务的日志检索规则。这样下次遇到类似事件时,排查效率会高很多,也更容易判断影响范围。

服务器与云环境安全示意图
服务器、云资产与权限边界梳理示意

0篇意见

推荐意见

没有意见。

游客
抱歉,你的帖子内容包括我们不允许的字词。请编辑你的帖子,删除下面高亮的屏蔽字。
添加意见…