伏特漏洞扫描-IoT设备安全解决方案

# 前言

随着智能硬件的兴起,大量智能家居和可穿戴设备进入了人们的生活,根据Gartner 报告预测,2020年全球IOT物联网设备数量将高达260亿个。但是由于安全标准滞后,以及智能设备制造商缺乏安全意识和投入,物联网已经埋下极大隐患,是个人隐私、企业信息安全甚至国家关键基础设施的头号安全威胁。试想一下,无论家用或企业级的互连设备,如接入互联网的交通指示灯,恒温器,或医用监控设备遭到攻击,后果都将非常可怕。

# 0x01 物联网安全需求

物联网根据业务形态主要分为工业控制物联网、车载物联网、智能家居物联网。不同的业务形态对安全的需求不尽相同。

工业控制物联网:涉及到国家安全、再加上目前工业控制网络基本是明文协议很容易遭受攻击。目前安全公司有威努特、匡恩网络等且在市场中已经有很好成效。主要产品形态:工控防火墙、工控漏洞挖掘、主机白名单产品。安全需求基本是传统安全的思路。

车载物联网:涉及财产安全及驾车人生命安全。国外相关安全厂商产品形态大致是OBD防火墙、云端大数据分析异常监控等。安全需求集中在车载核心物联网硬件安全及嵌入式设备安全上。

智能家居物联网:涉及到个人及家庭的隐私和数据安全。同时,由于近期各种DDOS、僵尸网络等安全事件的爆发,所以智能家具设备安全问题迫在眉睫。本解决方案主要面向与智能家居物联网方向。

# 0x02 IOT设备通用漏洞按风险技术类型分布

2017年CNVD收录IOT设备漏洞类型分别为权限绕过、拒绝服务、信息泄露、跨站、命令执行、缓冲区溢出、SQL注入、弱口令、设计缺陷等漏洞。其中,权限绕过、拒绝服务、信息泄露漏洞数量位列前三,分别占收录漏洞总数的23%,19%,13%。而对于弱口令(或内置默认口令)漏洞,虽然在统计比例中漏洞条数占比不大(2%),但实际影响却十分广泛,成为恶意代码攻击利用的重要风险点。

img

# 0x03 目前IoT设备安全测试的难点

  1. 物联网设备数量和数据流量大,测试点不完全
  2. 没有统一相关漏洞管理等平台,不方便漏洞跟踪
  3. 测试任务量与人员数量不匹配
  4. 目前市面暂时无法找到针对IoT设备的自动化安全测试工具

# 0x04 以机顶盒为例的IoT设备解决方案

结合目前IoT设备安全测试的难点及伏特漏洞扫描云平台本身的产品优势,目前提出了一个关于以机顶盒为例的IoT设备解决方案。

伏特漏洞扫描产品的一大技术创新是被动扫描,该功能主要优势有:

  • 无人员干预,全局持续化监控业务线, 弥补基于爬虫的主动扫描短板, 使监控范围更加完整。
  • 全流量监控,解决了代理流量身份鉴别、权限划分、目标域限制等问题导致的相关功能无法测试难点
  • 测试点更加全面,支持OWASP TOP 10、系统服务漏洞、框架漏洞、常见服务弱密码检测、通用CSM漏洞插件等

根据机顶盒相关网络架构,及伏特漏洞扫描器本身技术特点,采用如下接入方式:

img

具体步骤如下:

  1. 测试人员按照正常功能测试,操作机顶盒
  2. 机顶盒连接端口镜像交换机,流量走正常业务流程的同时被镜像到监控平台
  3. 流量监控平台监听所有进入的流量,并存储到redis扫描任务队列
  4. redis扫描任务队列分发到后端伏特分布式扫描平台
  5. 后端进行全流量漏洞扫描

0x04 技术实现部分代码

Redis客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class redis():
def __init__(self,host, port, password=None, count=1):
...
def rpush(self, key, value, expire=None):
self.r.rpush(key, value)
if isinstance(expire, int):
self.r.expire(key,expire)
def rpop(self, key):
n = 0
KV = {}
list = []
result = self.r.rpop(key)
if result == None:
return None
else:
return result

流量监控平台使用python的libpcap模块

1
2
3
4
// 设置监听的流量规则
pc = pcap.pcap()
pc.setfilter("tcp")
tracker={}

捕捉流量包(包括接受和发送的所有流量)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for ts, pkt in pc:
...
ltuple=(src,tcp.sport,dst,tcp.dport)
rtuple=(dst,tcp.dport,src,tcp.sport)
try:
tracker[ltuple]
try:
tracker[ltuple]['out']+=data
except KeyError:
tracker[ltuple]['out']=data
tracker[ltuple]['lastseen']=time.time()
except KeyError:
...
tracker[rtuple]['lastseen']=time.time()

对捕捉的流量进行处理、提取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
for connection in tracker.keys():
# print tracker[connection]
if time.time()-tracker[connection]['lastseen']>600:
del tracker[connection]
continue
...
try:
if tracker[connection]['in'] and tracker[connection]['out']:
data=tracker[connection]['in']
data+=tracker[connection]['out']
uri=re.search("(GET|POST) ([^\r\n]*)( HTTP/)",data,re.IGNORECASE)
postreg = re.compile("\r\n\r\n(.*?)HTTP/1",re.S)
postdata = re.findall(postreg,data)
webserver = re.search("server: ([^\r\n]*)",data,re.IGNORECASE)
...
if uri:
for i in uri.string.split('\r\n'):
if i.startswith('Cookie:'):
cookie = i
大爷,赏个铜板呗!