Webshell 到底是什么:从后门原理、发现方法到防守策略

Webshell 到底是什么:从后门原理、发现方法到防守策略

很多人第一次听到 webshell,会把它理解成“黑客上传了一个脚本文件”。这个理解不算错,但还是太轻了。

更准确一点说,webshell 是攻击者放进 Web 服务器上的一个持久化入口。它通常长得像普通脚本、普通页面,甚至普通插件的一部分,但作用不是提供业务功能,而是让攻击者能继续执行命令、读写文件、横向移动,或者重新拉起其他后门。MITRE ATT&CK 也把它归到 T1505.003 Web Shell,本质上就是把服务器软件组件当成持久化载体。

这类东西之所以麻烦,不在于“神秘”,而在于它非常贴近正常 Web 运行环境。它借的是现成的 HTTP/HTTPS 流量、现成的脚本解释器、现成的站点目录和权限模型。Microsoft 在 IIS 检测文章里提到,Web exploitation 和 web shell 仍然是现实环境里很常见的初始入侵点与持久化手段;而且恶意 IIS 模块甚至可以把通信藏进参数、请求头、请求体里,让日志和常规文件扫描都更难看出来。

所以这篇文章不打算讲“怎么做一个 webshell”,而是讲三件更实际的事:

  1. webshell 后门通常是什么样
  2. 你怎么在服务器上发现它
  3. 真正有效的防御优先级应该怎么排

一、webshell 后门通常长什么样

先说结论:webshell 不一定像一个单独的 shell.php 文件那样显眼。

最常见的几种形态,大概有这些:

1)伪装成正常业务脚本

比如一个看上去很普通的 PHP、JSP、ASPX 文件,文件名叫:

  • login.php
  • db-old.php
  • cache.asp
  • global.aspx
  • error.jsp

它们可能混在上传目录、临时目录、主题目录、插件目录里,表面看只是“功能文件”,实际会在收到某个特定参数后执行系统命令。

2)被注入到现有文件里

这比单独放一个文件更常见,也更难查。

攻击者未必新建文件,而是把几行恶意逻辑塞进已有入口文件、模板文件、公共 include 文件,或者某个你平时根本不会打开的 helper 文件里。这样做的好处很明显:不容易触发“新文件告警”,也更像正常代码变更。

3)伪装成插件、模块、扩展

在 IIS、CMS、WordPress、Exchange、SharePoint 一类系统里,后门未必只是脚本文件,也可能是模块、扩展、主题文件,或者站点运行时会自动加载的组件。Microsoft 提到的恶意 IIS 模块就是这一类:它不一定表现成“某个可疑页面”,而可能挂在请求处理链路上,直接拦截和改写请求、响应。

4)功能极简,但足够维持入口

别把 webshell 想得太“全功能后台化”。很多 webshell 的实现很短,可能只干一件事:

  • 执行命令
  • 写入第二阶段载荷
  • 回显文件内容
  • 接收参数后解码执行

攻击者不一定需要一个华丽控制面板,只要能保持可重复进入就够了。

二、webshell 一般是怎么进来的

从防守角度看,webshell 很少是“凭空出现”的,它通常是前面某个安全问题的结果。

最常见的入口包括:

1)文件上传点失守

这是最经典的一类。OWASP 在文件上传安全指南里强调,上传功能如果只检查扩展名、信任 Content-Type、把文件直接放进 webroot,风险会非常高;更稳妥的做法是扩展名白名单、类型校验、重命名、权限控制、存储到 webroot 之外,并在可能时接入 AV 或沙箱扫描。

这背后的现实逻辑很简单: “可上传” + “可被 Web 解释执行”,基本就是 webshell 最舒服的落点。

2)已知漏洞未修补

很多真实事件不是因为对方“技术特别高”,而是因为目标站点还挂着已知 RCE、任意文件写入、认证绕过或组件漏洞。打进去以后,再落一个 webshell 维持入口,就是非常常见的后续动作。MITRE 的过程样例里也反复能看到,攻击者在 Exchange、OWA、ERP、IIS 等暴露服务上放 webshell 作为持续访问手段。

3)后台口令弱、权限过大

CMS、面板、部署工具、文件管理器被撞库或弱口令拿下后,攻击者未必要立刻做复杂动作,最直接的就是写一个后门进去。 这类场景在中小团队、自建站点、历史项目里并不少见。

4)供应链和插件生态问题

特别是 CMS、主题、低质量插件、历史扩展,常见问题不是“主程序很脆”,而是外围生态很脆。对个人站长和小团队来说,这比 APT 叙事更现实。

三、怎么发现 webshell:别只盯着“可疑文件名”

发现 webshell,最容易踩的坑,是把排查理解成“全盘搜 eval”。

这当然有用,但远远不够。更靠谱的做法是把排查拆成四层:文件、时间线、行为、流量/日志

四、第一层:查文件异常

1)先找最近新增或最近改动的脚本文件

Linux 上可以先看近几天被修改过的 Web 目录文件:

find /var/www -type f \( -name "*.php" -o -name "*.jsp" -o -name "*.aspx" -o -name "*.asp" \) -mtime -7 -printf "%TY-%Tm-%Td %TT %p\n" | sort

如果站点路径不止一个,也可以把 Nginx/Apache 虚拟主机目录一起扫。

Windows / IIS 环境可以用 PowerShell 看最近改动的脚本文件:

Get-ChildItem -Path "C:\inetpub\wwwroot" -Recurse -Include *.aspx,*.ashx,*.asmx,*.php `
| Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } `
| Sort-Object LastWriteTime `
| Select-Object LastWriteTime, FullName

这一步的目的不是“直接命中 webshell”,而是先把调查范围缩小。 很多时候,异常点不是文件名,而是修改时间和业务发布时间对不上

2)搜索高风险执行函数

以 PHP 为例,先做一轮关键字扫描:

grep -RInE "eval\s*\(|assert\s*\(|system\s*\(|exec\s*\(|shell_exec\s*\(|passthru\s*\(|base64_decode\s*\(|gzinflate\s*\(|preg_replace\s*\(.*\/e" /var/www

这条命令不是判定规则,只是筛查入口。因为这些函数本身并不等于恶意,但它们和混淆、动态执行、命令调用组合在一起时,值得重点看。

3)关注“看起来不像业务代码”的痕迹

例如:

  • 一大段不可读的 Base64
  • 很短但高度混淆的单行脚本
  • 文件头部或尾部突然多出一段解码执行逻辑
  • 上传目录里出现可执行脚本
  • 图片、日志、缓存目录里出现脚本扩展名
  • 正常前端模板里突然调用系统命令

这些都不一定百分百是 webshell,但都值得拉高优先级。

五、第二层:对时间线做交叉验证

单看文件内容,误报会很多。 更有效的办法是把文件改动时间访问日志、漏洞利用时间、发布记录放在一起看。

建议你交叉核对:

  • 文件最后修改时间
  • Nginx / Apache / IIS 访问日志
  • WAF 告警时间
  • CI/CD 发布时间
  • 管理员登录日志
  • 系统补丁变更记录

例如你发现一个 cache.php 是凌晨 03:12 被改的,而那天没有发布;同一时间段访问日志里还有异常 POST 请求、非常规 User-Agent、404 页面触发大量参数提交,那就比“grep 出了 eval”更像真实线索。

六、第三层:看进程和父子关系

真正有价值的告警,往往不是“文件里有危险函数”,而是 Web 服务进程拉起了不该拉起的系统命令

MITRE 2025 年新增的检测策略就明确强调,可以通过“Web 服务器行为 + 文件执行链”来识别 webshell,重点看 Web 服务进程是否触发了脚本解释器、shell、系统工具等异常子进程。

Linux 上可以先看由 Web 用户拉起的可疑进程:

ps -ef | egrep 'www-data|nginx|apache|httpd|tomcat'

再重点盯这些异常行为:

  • nginx / apache / php-fpm 拉起 shbash
  • Web 进程拉起 curlwget
  • Web 进程调用 pythonperlnc
  • Tomcat / Java Web 进程突然执行系统命令
  • 短时间内频繁创建临时文件或压缩包

如果你的环境有 EDR / Sysmon / auditd,这层的价值会比静态扫文件高很多。

七、第四层:查访问模式和请求特征

webshell 通信经常藏在正常 HTTP 请求里,所以建议重点看这些模式:

  • 某个很少访问的脚本持续被请求
  • 请求参数极短但高频
  • POST 请求体里出现明显编码串
  • 某个 404/500 页面也能稳定返回 200 或固定长度响应
  • 非浏览器 User-Agent 长时间访问后台脚本
  • 来自单一 IP 的周期性探测与命令回连

Nginx 上可以先做最基础的日志聚合:

awk '{print $1, $7, $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -50

如果怀疑某个后门文件:

grep "suspicious.php" /var/log/nginx/access.log

IIS 环境则要重点关注:

  • w3wp.exe 的异常子进程
  • 非常规请求头
  • 针对不存在页面却能触发不同响应的请求
  • 模块、处理程序、站点配置的异常变动

Microsoft 也特别指出,恶意 IIS 模块可以把通信藏在参数、Body、Header 甚至 HTTP Method 中,还能篡改日志可见性,这也是为什么只看 URL 维度经常不够

八、一个更靠谱的排查顺序

如果你怀疑站点已经有 webshell,我更建议按这个顺序处理:

第一步:先保留证据,不要急着删文件

这是很多团队最容易犯的错。 看到可疑文件,第一反应就是删。结果文件是删了,真正的入侵路径、横向痕迹、二阶段载荷全没了。

更稳妥的做法是:

  1. 先备份可疑文件
  2. 记录 hash、权限、时间戳
  3. 导出相关访问日志
  4. 记录当前进程、网络连接、计划任务
  5. 再进入隔离和清理

Linux 示例:

sha256sum /var/www/html/suspicious.php
stat /var/www/html/suspicious.php
cp /var/www/html/suspicious.php /root/forensics/

第二步:判断它是不是“单点文件”,还是“已取得持续控制”

真正要回答的问题不是“这是不是 webshell”,而是:

  • 攻击者是只写了一个文件?
  • 还是已经拿到后台账号?
  • 还是已经写入计划任务、systemd、启动项、计划任务、IIS 模块、SSH key?
  • 还是已经把数据库、对象存储、CI 凭据一起拿走了?

如果只删掉前端看到的那个脚本,而不处理初始漏洞、账户、密钥、扩展模块,通常还会再回来。

第三步:修入口,再清后门

顺序非常重要。 比如问题来自文件上传绕过,那你应该先关闭上传点或切断对外服务,再清理落地文件。否则你删一次,对方再传一次,等于白做。

九、怎么防 webshell:优先级比“堆产品”更重要

讲防护时,最怕写成一串口号。 实际上,对大多数团队来说,真正有价值的是下面这几个优先级。

1)把“上传后可执行”这件事先堵死

这是收益最高的一项。

按照 OWASP 的建议,上传安全至少做到这些:扩展名白名单、不要信任 Content-Type、服务端重命名、限制大小、只给授权用户上传、文件尽量放到 webroot 之外,必要时再走杀毒或沙箱。

如果你的网站确实要让用户上传文件,一个很实用的原则是:

上传目录只允许存储,不允许解释执行。

比如 Nginx 可以显式禁止上传目录中的脚本执行:

location /uploads/ {
    autoindex off;
}

location ~* ^/uploads/.*.(php|php5|phtml|jsp|jspx|asp|aspx)$ {
    deny all;
}

Apache 也可以在上传目录关闭脚本执行能力:

location /uploads/ {
    autoindex off;
}

location ~* ^/uploads/.*\.(php|php5|phtml|jsp|jspx|asp|aspx)$ {
    deny all;
}

注意,这些配置是否生效取决于你的部署模式,但核心思路不变: 让上传目录成为“纯文件区”,而不是“可执行区”。

2)最小权限,不给 Web 进程多余写权限

很多 webshell 能持久化,不是因为它太高级,而是因为 Web 服务账号写权限太大。

至少要检查:

  • Web 进程是否能写整个站点目录
  • 是否能写配置文件
  • 是否能写插件/主题目录
  • 是否能写 system 目录、计划任务目录、启动目录
  • 容器是否挂了过大的宿主机卷权限

一个很朴素但有效的原则是:

  • 需要运行的目录给读权限
  • 必须写的目录单独隔离
  • 代码目录默认只读
  • 配置和密钥分离存放

3)补丁管理别掉队

这听起来老生常谈,但现实里 webshell 落地最常见的前提,还是暴露组件有漏洞。 Web 服务器、中间件、CMS、插件、主题、管理后台、文件管理器,这些都应该纳入补丁节奏,而不是只盯操作系统。

4)为“Web 进程拉起系统命令”建立告警

对检测成熟度稍微高一点的团队,这条很值。

因为静态特征会变,文件名会伪装,编码方式会变,但下面这些行为很难说得过去:

  • w3wp.exe -> cmd.exe / powershell.exe
  • apache2 / nginx / php-fpm -> sh / bash
  • tomcat -> /bin/sh
  • Web 进程调用下载器和压缩工具

这类父子进程链,比“关键字搜到了 eval”更接近真实入侵行为。MITRE 的检测策略和 Microsoft 的 IIS 调查建议,本质上也都在强调这一层。

5)保留日志,而且别只保留三天

如果没有访问日志、进程日志、认证日志,很多 webshell 事件最后只能停留在“好像被挂马了”。

最少建议保留:

  • Web 访问日志
  • 错误日志
  • 反向代理/WAF 日志
  • 后台登录日志
  • 文件完整性变更记录
  • 关键系统进程创建日志

对于个人站长和小团队来说,不一定一开始就上很重的 SIEM,但至少别把基础日志全关掉。

十、给个人开发者和小团队的现实建议

如果你不是大厂安全团队,而是自己管服务器、自己发版本、自己装插件,我会更建议你把精力放在这四件事上:

1)减少暴露面

不用的后台、测试目录、旧入口、历史面板、演示站点,能关就关。 很多 webshell 不是从主业务入口进来的,而是从你忘了的旧系统进来的。

2)少装来源不明的插件和主题

对 CMS 用户来说,这条经常比“上更强的 WAF”更实际。 很多问题压根不在你主程序,而在第三方生态。

3)把上传目录和代码目录彻底分开

这是非常值得做的工程化改动。哪怕麻烦一点,也比事后清后门便宜。

4)给服务器做最基础的完整性巡检

哪怕没有高级安全平台,也应该至少有:

  • 定期列出最近变更文件
  • 定期核对关键目录 hash
  • 定期检查异常计划任务/启动项
  • 定期看一次访问日志热点

这不性感,但非常有用。

十一、最后的判断

webshell 不是一个“神秘黑客名词”,它本质上是攻击者把 Web 运行环境变成自己的遥控入口

真正难的地方也不在于理解这个概念,而在于两点:

  1. 它很像正常 Web 代码和正常 HTTP 流量
  2. 它往往不是根因,而只是入侵完成后的一个结果

所以如果你只把注意力放在“删掉那个可疑文件”,通常不够。更合理的做法是:

  • 从上传、漏洞、弱口令、插件生态里找真正入口
  • 从文件、时间线、进程链、访问模式四层交叉排查
  • 从“上传不可执行、最小权限、及时补丁、行为告警、日志保留”几个优先级先做起

对于开发者来说,这件事最值得关注的点不是恐慌,而是工程常识: 只要一个系统允许“不可信内容进入 Web 可执行路径”,webshell 风险就一直存在。

这不是玄学问题,而是架构和运维纪律问题。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇