Overview
地址解析协议(ARP)是一种通信协议,用于发现给定 IP 地址的链路层地址,即 MAC 地址。ARP 协议没有任何的安全措施,ARP 缓存投毒攻击是针对 ARP 协议的常见攻击。使用这种攻击,攻击者可以欺骗受害者接受伪造的 IP-to-MAC 映射,使受害者的数据包被重定向到伪造的 MAC 地址的计算机上,从而导致中间人攻击。
本次实验包括以下主题:
- ARP 协议
- ARP 缓存投毒攻击
- 中间人攻击
- Scapy 编程
首先,我们使用了请求、响应和免费 ARP 数据包进行 ARP 缓存投毒攻击。然后在攻击的基础上,实现了中间人攻击,所有的数据流经中间人,可以被中间人读取并修改。
Environment Setup using Container
我们使用容器来构建实验环境,其中 Host M 是攻击者,Host A 和 Host B 分别是两个受害者。因为 ARP 缓存投毒攻击只能在局域网中进行,因此,这三台机器必须位于同一个局域网 10.9.0.0/24 中。
- 共享文件夹
- 特权模式:通过
privileged: true
来实现。特权模式能在运行时修改内核参数(使用 sysctl),例如开启 IP 转发。
数据包嗅探,我们可以运行 tcpdump -i 接口名称 -n
来嗅探特定接口上的数据包。由于 Docker 的隔离机制,容器只能嗅探到自己的数据包,除非使用了主机模式,而主机可以嗅探到所有的数据包。通常,在主机上,Docker 创建的网络接口名称以 br 开头,而在容器中通常以 eth 开头。
也可以通过 Wireshark 来嗅探数据包。
Task 1: ARP Cache Poisoning
Task 1.A (using ARP request),在 Host M 上,构造一个发送给 B 的 ARP 请求包来将 A 的 IP 地址绑定到 M 的 MAC 地址,这样在 B 给 A 发送数据包时,实际上会被发送给 M。
我们使用的代码如下,注意,在链路层使用的 MAC 地址为全 1,表示广播;在 ARP 数据包中 MAC 地址为全 0,这是要求。sendp() 直接发送数据链路层包,send() 发送的是网络层数据包,会自动封装链路层报头。
from scapy.all import * |
首先,我们将 Host B 的缓存全部清空。可以使用 arp -n 查看缓存,使用 arp -d ip-address 删除缓存。然后,我们在 Host M 上执行如上的攻击代码,并查看 Host B 的 ARP 缓存,结果如下。接下来,Host B 去 ping Host A,再去查看 arp 缓存表,结果如下:
观察抓包到的结果如下:
第一第二个数据包就是我们的 ARP 欺骗。然后第三个数据包说是发送给 10.9.0.5,但是因为 ARP 的缓存是假的,实际上发送给了 Host M,我们通过第三个数据包的目的 MAC 地址就可以看出,ARP 欺骗成功了。
而后续其他的数据包是因为开启了 IP 转发,M 发现接收到的数据包不是自己的,就会去找到正确的那个数据包!下面的时间会涉及到,暂时不管它就好了。
Task 1.B (using ARP reply),在 Host M 上,构造一个发送给 B 的 ARP 响应包来将 A 的 IP 地址绑定到 M 的 MAC 地址上。ARP 响应包使用的是单播,我们需要提前知道 B 的 MAC 地址。如下 op=2 表示是 ARP reply 包。
from scapy.all import * |
我们发现在 B 中有 A 的 ARP 缓存时,接收到构造的 ARP reply 包后,缓存更新了。
而下图,我们在删除了 ARP 缓存后,执行上述代码,发现 B 中没有创建新的 ARP 缓存记录。
Task 1.C (using ARP gratuitous message)。免费 ARP 包,简单来说,就是主动发出响应包,用于通知网络中其他设备有关发送者的信息,也即广播自己的 IP-to-MAC。免费 ARP 包具有如下特定:
- 源 IP 和目的 IP 地址是一样的,因为广播不需要目的 IP 地址。
- 目的 MAC 地址是全 1。
- 没有 reply 包。
from scapy.all import * |
Task 2: MITM Attack on Telnet using ARP Cache Poisoning
下面就是本任务实验的拓扑图。
Step 1 (Launch the ARP cache poisoning attack)。首先,M 要欺骗 A,让其误以为 M 是 B;然后,M 要欺骗 B,让其误以为 M 是 A。
from scapy.all import * |
**Step 2 (Testing)**。关闭 M 的 IP 转发,然后 A 和 B 互相 ping,发现 ping 不通。
其中 -c 1
表示发送一个 ping 数据包,如果一直 ping,前面 ping 不通一会之后就会 ping 通。
**Step 3 (Turn on IP forwarding)**。开启 IP 转发后,发现可以 ping 通。
**Step 4 (Launch the MITM attack)**。首先,在开启 IP 转发或者关闭中间人攻击的条件下,建立 telnet 连接。发现输入数据如 sss 可以正确回显。然后我们开启中间人攻击并关闭 IP 转发,发现数据无法回显,这是因为数据被 M 接收了,没有响应。
在 M 上运行如下嗅探并欺骗代码,将捕获的数据包的数据修改为 Z。
from scapy.all import * |
结果如下,输入任何字母,全部变成了 Z。
在 Telnet 窗口输入的任何字符,都会触发一个 TCP 数据包。也就是说,输入一个字符,就会发送一个 TCP 包给 Telnet 服务器,其中只包含一个字符,除非你输入的特别快。发送一个字符给服务器后,服务器会回复一个相同的字符给客户端,并显示在屏幕上。
因此,如果连接断开,输入的字符无法经过一个来回,就不会有任何显示;如果在来回的任何一个地方,数据被修改了,那么显示的就是修改后的数据!
Task 3: MITM Attack on Netcat using ARP Cache Poisoning
基本和上面一样,只不过上面是一个字符,这里一次发送的是一个字符串,如果替换后长度不变,那么和上面一模一样,但是如果改变了长度,就需要多做一些工作了,具体而言就是 IP 头部的总长度也需要改变。