跳转到帖子

背景

这篇整理来自几次应急排查中的共性经验:业务站点突然出现异常文件、可疑进程或被搜索引擎标记风险,最后追溯到上传点、后台弱口令、插件漏洞或历史遗留接口。很多复盘文章会直接给 IOC 或处置结论,但真正有长期价值的是把排查路径沉淀下来,方便下次遇到类似情况时能快速缩小范围。

本文只讨论防守视角下的日志分析、样本识别、代码审计和加固方法,不涉及攻击利用细节。示例命令也以本地自查和取证为主。

问题场景

常见的 WebShell 入侵现场通常会有几个信号:

  • Web 目录下出现异常 PHP、JSP、ASPX 文件,文件名看似正常,例如 cache.php、config_old.php、upload_tmp.php。
  • 访问日志中存在少量 POST 请求,响应码为 200,User-Agent 非常规,访问路径集中在上传目录或插件目录。
  • 服务器上出现可疑外连、异常计划任务、临时目录中的脚本文件。
  • 业务代码近期没有发布,但文件修改时间集中在某个时间窗口。

复盘时建议先明确三个问题:入口在哪里、落地文件是什么、后续动作有哪些。不要一开始就急着删除文件,否则容易丢失时间线和证据。

第一步:保护现场与划定时间窗口

如果条件允许,先做磁盘快照或至少备份 Web 目录、日志目录、系统任务配置。对线上服务压力较大时,可以先导出关键文件,不建议直接在原文件上操作。

常用的第一轮时间线排查:

find /var/www -type f -mtime -7 -printf '%TY-%Tm-%Td %TT %p\n' | sort
find /var/www -type f -newermt '2024-01-01 00:00:00' ! -newermt '2024-01-02 00:00:00' -ls
stat /var/www/html/uploads/cache.php

这里重点看两类文件:一是上传目录中的可执行脚本,二是业务代码目录中最近被改动的核心文件。很多后门不会新建文件,而是追加到已有文件末尾,尤其是入口文件、配置文件、模板缓存文件。

第二步:从访问日志反推落点

WebShell 的访问通常有一些特征:请求频率不一定高,但路径稳定;方法以 POST 为主;参数名可能很短;响应体大小相对固定。可以先按时间窗口过滤访问日志。

grep '01/Jan/2024' /var/log/nginx/access.log | grep 'POST' > /tmp/post.log
awk '{print $1,$4,$6,$7,$9,$10,$12}' /tmp/post.log | sort | uniq -c | sort -nr | head -50

如果是 Nginx,默认日志不记录 POST body,所以不能指望仅靠 access.log 还原所有细节,但足够定位路径、IP、时间和状态码。可进一步聚合可疑路径:

awk '{print $7}' /tmp/post.log | sort | uniq -c | sort -nr | head -30

排查时不要只盯 200,部分探测、上传失败、目录扫描会落在 403、404、500。它们对确认入口同样有价值。

第三步:识别 WebShell 与变形痕迹

简单的关键字搜索仍然有用,但不要只依赖单个特征。建议结合文件位置、修改时间、代码风格和危险函数使用情况综合判断。

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

PHP 场景中,经常看到的风险点包括:

  • 动态执行:eval、assert、preg_replace /e、create_function。
  • 命令执行:system、exec、shell_exec、passthru、proc_open、popen。
  • 编码混淆:base64_decode、str_rot13、gzinflate、gzuncompress 多层嵌套。
  • 文件操作:file_put_contents、fopen、fwrite 配合外部输入。

但需要注意,很多正常框架也会使用反射、缓存、序列化和文件写入,不能看到关键字就直接判定后门。比较可靠的判断方式是:外部输入是否未经约束进入动态执行或文件写入链路。

例如下面这种模式就需要重点关注:

// 风险模式示意:不要在业务中使用
$action = $_POST['action'] ?? '';
$data = $_POST['data'] ?? '';
if ($action === 'run') {
    eval($data);
}

实际样本通常不会这么直白,可能通过变量拼接、函数名拆分、编码还原等方式隐藏。审计时可以先格式化代码,再追踪输入源和危险汇点。

第四步:定位入口而不是只清理后门

只删除 WebShell 不解决问题。入口没有修复,文件很快会再次出现。常见入口可以按优先级排查:

  • 上传功能:是否允许上传脚本后缀,是否只做前端校验,是否存在双后缀、MIME 信任、解析配置错误。
  • 后台入口:是否存在弱口令、默认账号、暴露在公网的管理面板。
  • 第三方组件:CMS 插件、编辑器、文件管理器、历史版本框架。
  • 任意文件写入:模板编辑、日志写入、缓存生成、导入导出功能。
  • 反序列化链路:外部可控数据进入 unserialize、readObject 等危险流程。

上传场景建议检查 Web 服务器解析配置。很多事故不是上传校验单点失效,而是上传目录被错误配置为可执行。

# Nginx 示例:上传目录禁止脚本执行
location ^~ /uploads/ {
    location ~* \.(php|phtml|phar|jsp|asp|aspx)$ {
        return 403;
    }
}

同时建议把上传文件存储到非 WebRoot 路径,通过受控接口读取,或者至少使用对象存储并关闭脚本解析能力。

第五步:系统层面排查后续动作

WebShell 只是入口,后续可能会有持久化、横向移动或数据打包行为。Linux 主机可以重点看以下位置:

crontab -l
ls -al /etc/cron* /var/spool/cron 2>/dev/null
ps aux --sort=-%cpu | head
ss -antp
last -a | head
find /tmp /var/tmp /dev/shm -type f -mtime -7 -ls 2>/dev/null

如果发现可疑进程,不建议立即 kill 后就结束排查。先记录进程路径、启动参数、父进程、网络连接和文件句柄:

pid=12345
pwdx $pid
ls -al /proc/$pid/exe
tr '\0' ' ' < /proc/$pid/cmdline
ls -al /proc/$pid/fd | head

这些信息有助于判断攻击者是否已经从 Web 权限进入系统权限,以及是否存在其他落地文件。

第六步:代码审计中的几个高频误区

复盘代码时,比较容易踩以下几个坑:

  • 只查上传接口,不查文件解压、远程下载、模板编辑等“间接写文件”功能。
  • 只看新增文件,不看被追加的一句话代码或被替换的依赖包文件。
  • 只修业务代码,不检查 Nginx、Apache、PHP-FPM 的解析和权限配置。
  • 只封 IP,不修漏洞。攻击源经常变化,封禁只能作为临时措施。
  • 只升级主程序,不升级插件、主题、编辑器和历史遗留目录。

代码审计建议从输入源到危险操作建立链路。例如 PHP 项目里可以先找 $_GET、$_POST、$_FILES、php://input,再看数据是否进入文件写入、命令执行、SQL 拼接、模板渲染等位置。

加固建议

  • 上传目录禁止脚本执行,上传文件重命名为随机文件名,文件类型以白名单校验为主。
  • 后台管理入口增加访问控制和多因素认证,避免默认路径长期暴露公网。
  • Web 进程使用低权限账号运行,业务目录按最小权限设置,代码目录尽量只读。
  • 关闭不必要的危险函数,结合业务实际评估 disable_functions,不要盲目配置导致业务异常。
  • 建立文件完整性监控,对核心目录新增、修改、权限变化进行告警。
  • 日志集中化保存,避免攻击者取得单机权限后直接清理本地日志。
  • 定期清理历史测试文件、备份压缩包、旧版本插件和未使用的管理工具。

一个相对实用的权限基线是:代码发布目录由发布用户写入,运行时 Web 用户只读;需要写入的目录单独划分,例如 uploads、cache、logs,并对这些目录限制脚本执行。

事件复盘模板

建议每次事件结束后沉淀一份简短报告,至少包含以下内容:

项目说明
发现时间告警、用户反馈或人工巡检发现的时间
影响范围受影响域名、主机、目录、账号和数据范围
入侵入口漏洞点、弱口令、组件缺陷或配置问题
攻击时间线关键请求、文件落地、进程启动、外连行为
处置动作隔离、备份、清理、修复、升级、密钥轮换
长期改进监控、权限、发布流程、组件治理、审计规则

复盘报告不需要写得很花,关键是能回答“为什么发生、怎么发现、如何避免再次发生”。

注意点

  • 清理前先备份样本和日志,后续确认入口时经常需要回看。
  • 不要把文件修改时间作为唯一依据,时间戳可能被修改。
  • 不要忽略内网机器访问 WebShell 的情况,可能是跳板或自动化扫描器。
  • 涉及敏感数据时,优先确认是否存在读取、打包、导出痕迹。
  • 修复后要做回归验证,包括上传限制、目录解析、权限边界和告警触发。

总结

WebShell 事件的处理重点不是“找到一个可疑文件然后删除”,而是围绕时间线把入口、落地、执行、持久化和影响范围串起来。日志分析负责还原路径,样本识别负责确认行为,代码审计负责修漏洞,权限和监控负责降低下一次事件的影响。

长期看,最有效的办法不是堆更多工具,而是把上传目录不可执行、最小权限、组件治理、日志留存、文件完整性监控这些基础项做扎实。很多入侵事件之所以反复发生,问题往往不在某个单点漏洞,而在基础安全边界长期缺位。

代码审计与漏洞定位示意图
代码审计、调用链与关键函数定位示意

0篇意见

推荐意见

没有意见。

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