实现防御ARP劫持与主动反击

1. 前言

ARP协议由于是明文且无状态的,因此ARP劫持在内网中是最容易实现的攻击方式。

朋友最近在学习网络安全,然后我和他处在同一个局域网下面,他用ARP劫持攻击了我的电脑(玩笑性质),导致我无法正常上网。出于反击,在理清思路后,利用Gemini 3.1 Pro写了一个Python脚本,实现主动防御ARP劫持与主动反击。

这篇文章主要介绍ARP劫持的防御与主动反击的思路。

2. 攻击原理

关于ARP的具体工作原理以及断网/流量劫持攻击方式,可以参看我以前写的文章:

简单来说,ARP劫持分为双向ARP劫持和单向ARP劫持。单向 ARP 劫持是指攻击者只欺骗了本机的上下行流量中的其中一条,而双向 ARP 劫持是指攻击者同时欺骗了本机的上下行流量。上行流量也就是到网关的流量,下行流量也就是从网关来的流量。

攻击者向本机发送伪造的单播ARP响应报文,导致本机将网关IP对应的MAC地址错误地绑定到了攻击者的MAC地址上,这会使本机原本发往网关的数据被二层转发到攻击者的MAC地址上,导致本机上行流量被劫持窃听或者被丢弃

攻击者向网关发送伪造的单播ARP响应报文,导致网关将本机IP对应的MAC地址错误地绑定到了攻击者的MAC地址上,这会使网关原本发往本机的数据被二层转发到攻击者的MAC地址上,导致本机下行流量被劫持窃听或者被丢弃

3. 防御

3.1. 静态ARP

在了解了攻击原理后,便可以对症下药进行防护以及主动反击攻击者。

对于上行流量的 ARP 劫持防护,可以通过在本机设置静态ARP表项,将网关IP对应的MAC地址静态绑定,这样在和网关通信前就不会通过ARP协议来获取网关的MAC地址了,而是直接读取静态ARP表项中的MAC地址,以此来忽略攻击者的ARP响应报文,确保本机发往网关的上行数据被正确转发。

Windows设置永久静态ARP表项的命令如下:

1
2
3
4
5
6
7
8
9
10
11
# 查看网卡索引编号
netsh interface ipv4 show interfaces

# 添加静态ARP表项(假设网卡索引编号为9,网关IP为192.168.1.1,网关MAC地址为e0-ae-a2-44-a8-08)
netsh -c interface ipv4 add neighbors 10 192.168.1.1 e0-ae-a2-44-a8-08

# 查看静态ARP表项(假设编号为9)
netsh interface ipv4 show neighbors 10

# 删除指定网卡所有静态ARP表项(假设编号为10)
netsh -c interface ipv4 delete neighbors 10

上述命令需要使用管理员权限运行。更详细以及linux的设置方法可以参看这篇教程:

3.2. 主动防御

对于下行流量的 ARP 劫持防护,也可以通过在网关设置静态ARP表项,将本机IP对应的MAC地址设置为正确的本机MAC地址,从而忽略攻击者的ARP响应报文,确保网关发往本机的数据被正确转发。不过大部分路由器都不支持设置静态ARP表项,因此这种方法在实际中并不可行。我的解决方法是主动防御,通过脚本不停的向网关单播发送自己真实的 MAC 信息,这样网关的 ARP 表项刚被攻击者改写,零点几秒内又会被自己发出的真实响应改回来,也就是 ARP 表项竞争,只要自己的发包速率快于攻击者,就能保持网关上自己的真实 MAC 地址始终为最新。

4. 反击

对于反击,可以通过检查所有广播 ARP 响应报文以及发给自己的单播 ARP 响应报文,如果声称自己是网关但是 MAC 地址对不上预定义的网关 MAC 地址,就说明被ARP劫持上行了,这时将立即将发送此 ARP 响应报文的源 MAC 地址定义为攻击者的 MAC 地址,向其发送单播ARP响应报文,欺骗攻击者将本机IP对应的MAC地址错误地绑定到全零地址 00:00:00:00:00:00 上,使攻击无法与本机二层通信,以及发送单播 ARP 响应报文欺骗攻击者将网关 IP 对应的 MAC 地址也错误地绑定到全零地址 00:00:00:00:00:00 上,使攻击无法与网关通信,使攻击者上行链路断网,同时向整个内网进行ARP存活探测,提取源 MAC 与攻击者 MAC 完全一致的设备的 IP 地址,将其定义为攻击者 IP,接着向网关单播发送ARP响应报文,欺骗网关说攻击者 IP 对应的 MAC 地址也是全零地址 00:00:00:00:00:00,使攻击者下行链路断网

如果检查到有广播 ARP 响应报文声称是自己但是 MAC 地址对不上预定义的本机 MAC 地址,就说明攻击者正在欺骗网关,伪装成自己来ARP劫持下行,这时也将此广播 ARP 响应报文的源 MAC 地址定义为攻击者的 MAC 地址,并且扫描获取攻击者的 IP 地址,对其执行上面的反击措施。不过实际情况中,攻击者通常是单播发送ARP响应报文给网关,以此来欺骗网关劫持我们的下行,在本机上是检测不到攻击者发给网关的单播报文(数据未经过本机网卡),因此下行防护主要提现在主动防御上

4.1. 源码

下载脚本:

guardian.py

该脚本依赖scapy库,用于发送和接收ARP数据包。使用前需要先安装scapy库:

1
python -m pip install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple scapy

如果自动获取本机IP、MAC地址以及网关IP、MAC地址失败,则需要手动配置这些信息。

4.2. 演示

本机已提前绑定了网关的静态ARP表项:

alt text

启动脚本:

alt text

局域网的Nethunter 设备上使用 arpspoof 工具进行 ARP 劫持本机的下行:

alt text

由于 arpspoof 欺骗本机上行是单播发给网关的,因此本机无法检测出攻击行为。但是由于脚本会主动防御,和arpspoof进行ARP表项竞争,快速覆盖arpspoof的虚假ARP表项,导致arpspoof难以生效,但是还是会有轻微的超时丢包:

alt text

继续使用 arpspoof 工具进行 ARP 劫持本机的上行:

alt text

本机会立即检测到上行的ARP劫持行为并进行主动反击:

alt text

本机依旧能正常上网,但还是会有轻微的超时丢包,使用浏览器基本察觉不出网络异常:

alt text

攻击者被反击后,将会断开上下行的网络连接,导致无法上网:

alt text

4.3. 缺陷

实际上这个脚本有个缺陷,那就是他适合反击不懂原理的人使用arpspoof之类的简单工具进行的ARP劫持,如果攻击者也是用scapy之类的灵活脚本进行劫持,并将ARP响应报文中的源MAC地址进行了伪装,则会导致反制失效。如果伪装的源MAC地址是局域网中其他设备的MAC地址,则会导致反击误伤其他人,如果伪装的是不存在的源MAC地址,则反制失效。所以还是要根据实际情况来判断是否需要开启反制功能。

不过对于伪装源MAC地址,部分系统(如Windows)会丢弃与网卡的真实 MAC 不一致的报文。并且部分系统有严格ARP学习和状态验证机制,当连上网络时会先学习到正确的网关MAC地址,之后收到伪造MAC报文时不会立即相信,会是向真实网关发送单播ARP请求探针,如果网关回包了,则会丢弃伪造包并维持原状态。