AWD 比赛复盘:Web 服务加固、流量分析与批量修补

一、项目背景

AWD 比赛的特点是攻防同时进行:一边要维护自己的服务可用性,一边要分析漏洞、修补漏洞、排查后门,同时还要关注其他队伍的攻击流量。

相比普通 CTF 题解,AWD 更接近真实安全工作中的应急响应和安全运营场景。本文从一次 Web AWD 训练赛的角度,复盘赛前加固、文件备份、弱口令检查、WebShell 排查、漏洞修补、流量分析和批量脚本处理流程。

本文内容仅用于本地靶场、校内训练赛或授权比赛环境。

二、环境说明

项目 内容
比赛类型 Web AWD
服务类型 PHP Web 服务
系统环境 Linux
主要任务 保持服务可用、修补漏洞、分析攻击流量
常用工具 grep、find、diff、tar、ps、netstat、tcpdump、Python

AWD 中最重要的不是“会一个漏洞”,而是能快速把服务稳住,并建立可重复执行的排查流程。

三、赛前加固流程

1. 备份源码和配置

拿到靶机后第一步是备份,避免修补过程中误删文件,也方便后续做差异对比。

1
2
3
4
mkdir -p /tmp/awd_backup
tar -zcvf /tmp/awd_backup/web_$(date +%F_%H%M).tar.gz /var/www/html
cp /etc/nginx/nginx.conf /tmp/awd_backup/nginx.conf.bak 2>/dev/null
cp /etc/apache2/apache2.conf /tmp/awd_backup/apache2.conf.bak 2>/dev/null

备份完成后,记录当前 Web 目录文件数量:

1
find /var/www/html -type f | wc -l

后续如果文件数量突然增加,就要重点检查是否被写入 WebShell。

2. 检查弱口令

常见需要检查的位置:

  • Web 后台账号
  • 数据库账号
  • SSH 账号
  • 配置文件中的默认密码
  • 代码中硬编码的账号密码

快速检索配置文件:

1
grep -RniE "password|passwd|pwd|user|username|root" /var/www/html 2>/dev/null

如果发现默认密码,应立即修改,并同步更新配置文件中连接数据库的密码。

3. 设置目录权限

Web 目录权限过大时,攻击者可能上传或修改脚本文件。一般原则是:能只读就只读,必须上传的目录单独控制。

1
2
3
chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;

如果存在上传目录,可以单独设置:

1
2
chmod 755 /var/www/html/uploads
find /var/www/html/uploads -type f -name "*.php" -delete

真实比赛中不能盲目删除文件,删除前建议先备份可疑文件。

四、WebShell 排查

1. 按危险函数排查

PHP WebShell 常见危险函数包括:

1
2
3
4
5
6
7
8
9
eval
assert
system
exec
shell_exec
passthru
base64_decode
file_put_contents
preg_replace

排查命令:

1
grep -RniE "eval|assert|system|exec|shell_exec|passthru|base64_decode|file_put_contents|preg_replace" /var/www/html 2>/dev/null

需要注意:出现危险函数不一定就是 WebShell,很多正常业务代码也可能使用这些函数。判断时要结合文件路径、修改时间、代码上下文和访问日志。

2. 按最近修改时间排查

比赛过程中如果发现服务异常,优先查看最近被修改的文件:

1
find /var/www/html -type f -mmin -30 -ls

重点关注:

  • 上传目录中新出现的 PHP 文件
  • 图片目录中的脚本文件
  • 文件名伪装成 .jpg.php.ico.php
  • 内容高度混淆或只有一行代码的文件

3. 按异常后缀排查

1
find /var/www/html -type f \( -name "*.php*" -o -name "*.phtml" -o -name "*.phar" \)

对于上传目录,可以限制脚本执行。以 Nginx 为例:

1
2
3
4
5
location ^~ /uploads/ {
location ~ \.php$ {
return 403;
}
}

五、漏洞修补思路

1. SQL 注入修补

常见问题代码:

1
2
$id = $_GET['id'];
$sql = "select * from news where id=$id";

修补思路:

  • 对数字参数做类型转换。
  • 使用预编译查询。
  • 不直接拼接用户输入。

简单修补示例:

1
2
$id = intval($_GET['id']);
$sql = "select * from news where id=$id";

这只是临时修补方式,更推荐使用 PDO 预编译。

2. 文件上传修补

上传漏洞是 AWD 中常见入口。临时加固可以从以下几个方面处理:

  • 限制文件后缀。
  • 检查 MIME 类型。
  • 重命名上传文件。
  • 上传目录禁止脚本执行。
  • 禁止双后缀绕过。

示例检查逻辑:

1
2
3
4
5
6
$allow_ext = ['jpg', 'png', 'gif'];
$ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));

if (!in_array($ext, $allow_ext)) {
die("invalid file type");
}

3. 命令执行修补

危险写法:

1
2
$host = $_GET['host'];
system("ping -c 1 " . $host);

修补思路:

  • 避免调用系统命令。
  • 必须调用时使用白名单。
  • 使用 escapeshellarg 处理参数。

示例:

1
2
3
4
5
$host = $_GET['host'];
if (!preg_match('/^[a-zA-Z0-9\.\-]+$/', $host)) {
die("invalid host");
}
system("ping -c 1 " . escapeshellarg($host));

六、流量分析

1. Nginx/Apache 日志分析

常用日志位置:

1
2
3
4
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/apache2/access.log
/var/log/apache2/error.log

统计访问最多的 IP:

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

统计访问最多的路径:

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

筛选疑似攻击 Payload:

1
grep -Ei "union|select|sleep|benchmark|base64|eval|assert|upload|cmd=|shell" /var/log/nginx/access.log

2. tcpdump 抓包

如果怀疑有攻击流量持续打入,可以临时抓包:

1
tcpdump -i eth0 -w /tmp/awd_traffic.pcap

抓包后可以用 Wireshark 分析 HTTP 请求、上传行为和异常 Payload。

3. 判断攻击成功迹象

需要重点关注:

  • 攻击请求返回 200。
  • 上传目录出现新文件。
  • Web 日志中出现可疑参数后,系统出现异常进程。
  • 同一 IP 先扫描、再上传、再访问上传文件。
  • error.log 中出现 PHP 报错或执行痕迹。

七、批量排查脚本

比赛中手工排查效率不够,可以写一个简单脚本快速统计可疑文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import os
import re
from datetime import datetime

web_root = "/var/www/html"
rules = [
r"eval\s*\(",
r"assert\s*\(",
r"system\s*\(",
r"shell_exec\s*\(",
r"passthru\s*\(",
r"base64_decode\s*\(",
r"file_put_contents\s*\(",
]

pattern = re.compile("|".join(rules), re.IGNORECASE)

for root, dirs, files in os.walk(web_root):
for name in files:
path = os.path.join(root, name)
try:
with open(path, "r", encoding="utf-8", errors="ignore") as f:
content = f.read()
except Exception:
continue

if pattern.search(content):
mtime = datetime.fromtimestamp(os.path.getmtime(path))
print(f"[!] {path} modified: {mtime}")

脚本作用:

  • 递归扫描 Web 目录。
  • 匹配常见危险函数。
  • 输出文件路径和修改时间。
  • 辅助定位可疑 WebShell 或被篡改文件。

八、比赛中遇到的问题

1. 修补后服务不可用

原因通常是修补过急,误删业务文件或改错权限。解决方式:

  • 修改前先备份。
  • 每次只改一个点。
  • 修改后立即访问首页和关键功能。
  • 保留回滚包。

2. WebShell 没清理干净

常见原因:

  • 只删了一个入口文件,没有清理变种。
  • 忽略了上传目录。
  • 忽略了图片目录中的脚本。
  • 没有结合访问日志定位落点。

3. 只修漏洞不看日志

AWD 中只修代码不看日志,很容易错过攻击者已经写入的后门。正确流程应该是:

1
备份 -> 查日志 -> 找入口 -> 修漏洞 -> 查 WebShell -> 验证服务 -> 持续监控

九、复盘总结

本次 AWD 训练的重点不是单个漏洞利用,而是建立一套比赛中可执行的防守流程:

  • 先备份,保证服务可回滚。
  • 快速检查弱口令和敏感配置。
  • 通过危险函数、修改时间和异常后缀排查 WebShell。
  • 根据访问日志还原攻击路径。
  • 对 SQL 注入、文件上传、命令执行等入口做临时修补。
  • 使用脚本提高重复排查效率。

从求职角度看,AWD 复盘能体现安全运营、应急响应和渗透测试的综合能力。后续可以继续完善成自动化工具,例如加入日志统计、WebShell 特征库、文件哈希对比和 HTML 报告导出。