智能家居网络安全攻与防-阿里云开发者社区

开发者社区> 安全> 正文

智能家居网络安全攻与防

简介:

背景

物联网将会成为继互联网之后的下一个暴发点,目前以有不少公司已进入该领域。

智能家居作为物联网中最具有潜力的领域,网络安全是必须引起重视的课题。在互联网领域中,用户去安全性的敏感度并不是那个高。但是在智能家居领域中,如果系统被黑客攻击:半夜房门自动打开、无故解除安防系统、灯不亮等严重威胁到了用户的财产人身安全。

所以,智能家居想发展,安全性是决不可忽视的关键要素。


网络通信安全

任何信息在网络上传播能是能被第三者监听的。
一个局域网就像是一间会议室,里面坐了几个人,大家坐在一起相互交流。同时只允许一个人发言,不管是谁说话都能被在场的所有人听见。
通常情况下,只有被交流的对象才会在意对方说的话,其他人不会留意。
比如:屋子里有A,B,C,D四个人。如下是A与B之间的对话:
A:嘿B
B:嘿A
A:“告诉我银行卡密码吧”
B:“123321”
由于A不是对C与D说的话,C与D自然忽略这句话,但是他们是能听得见的
如果D是一个不怀好意的人,刻意留心他们的对话,是很容易窃听到关键信息的。
而且网络里还有ARP诈骗等手段,网络安全是岌岌可危的。

怎么办?两种思路:

方法一:不允许不相关的人进入会议室

就是不允许其它结点加入到局域网中来。
在wifi普及面非常广的时代,家家都有无线路由器,这要求用户严守wifi密码,严防泄漏。
这比较难,有时候wifi密码会在用户不知情的情况下泄漏。比如市面上存在一种叫“wifi万能钥匙”,这就是一种盗取用户已登陆wifi结点密码并共享给其它人的工具。这说明这个方法很难把控。
至于如何在这方面有所提升,已超出了我们智能家居所负责的领域。暂不讨论~

方法二:用别人听不懂的语言对话

做不到被听到,那就不让第3个人听懂也行。会议室里有A,B,C 3个人,A与B对英语交流,C在旁听到了,但不知道他们在说什么。
这是我们在安全方面可以做的。


智能家居系统介绍

该智能家居系统组织如下:
235334_sbDT_243525.png

  • Server: 云端服务器

  • SmartHost: 智能主机,负责将以太网中的数据能过Zigbee数据转发给Device

  • Device: 设备结点,常见的有灯、窗帘、门磁感应器,与SmartHost通过Zigbee连接

  • Client: 手机应用,有Android客户端与iOS客户端。接受用户的指令。当Client与SmartHost在同一局域网中,Client通过Wifi与SmartHost进行交互;如果不在同一个局域网,则通过与Server进行转发。

  • 假设局域网中来了一个不速之客Hacker,它启图操控家居设备。


攻与防

1. 无加密

如果Client与SmartHost之间的通信是明文的,那么没有安全性可言。只要黑客进入了家里的局域网,对网络包进行监听,很轻易地操控家里的设备。

通信过程

  1. Client-->SmartHost: Login: account John, password abc

  2. SmartHost-->Client: OK

  3. Client-->SmartHost: Open the door

  4. SmartHost-->Client: Done

攻击方式

Hacker监听到上面的通信,Hacker可以进行模拟Client进行登陆

  1. Hacker-->SmartHost: Login: account John, password abc

  2. SmartHost-->Hacker: OK

  3. Hacker-->SmartHost: Open the door

  4. SmartHost-->Hacker: Done

于是门开了。

分析

由于是明文,稍有头脑的Hacker就能分析出Client与SmartHost的通信协议。在盗取了用户的帐号与密码之后,Hacker就可以完全掌据整个家居系统。

防预级别:V 只能抵挡没有网络基础的攻击


2. static_key

由于上面问题的是明文数据传输,容易被Hacker分析。于是在上一版本的基础上使用特定的密钥对数据进行加密。

如下用()表示其中的内容是用static_key加密的

  1. Client-->SmartHost: (Login: account John, password abc)

  2. SmartHost-->Client: (OK)

  3. Client-->SmartHost: (Open the door)

  4. SmartHost-->Client: (Done)

由于上面是用密文进行通信的,Hacker不知道其容易是什么意思。但是,他知道只要把上面的话录制下来,重复播放一便就可以伪装Client开门了。

  1. Hacker-->SmartHost: (Login: account John, password abc)

  2. Hacker-->SmartHost: (Open the door)

结果门开了。

分析

其实Hacker不知道Client与SmartHost的具体内容是什么。他可能猜到是在登陆系统,然后是发命令开门的动作。但他无法得知通信的结构,也无法获取用户的帐号与密码。它只能说模仿Client的“发音”与SmartHost进行对话,达到控制设备的目的。

防预级别:VV


3. 加时间戳

针对上面Hacker的攻击,我们做了改进。通常,Hacker不会在监听到了命令之后立即执行。而是在等主人不在家了再执行上面的开门命令。那么,我们在密文域中加一个字段:Timestamp(时间戳)。

通信过程

  1. Client-->SmartHost: (201509261543, Login: accout John, password abc123)

  2. SmartHost接收到命令,当前系统时间为2015-09-26 15:44,与Client提供的命令误差在5分钟以内,通过检查。

  3. SmartHost-->Client: (201509261544, OK)

  4. Client接收到命令,当前系统时间为2015-09-26 15:43,与Client提供的命令误差在5分钟以内,通过检查。

  5. Client-->SmartHost: (201509261548, Open the door)

  6. SmartHost接收到命令,当前系统时间为2015-09-26 15:49,与Client提供的命令误差在5分钟以内,通过检查。

  7. SmartHost-->Client: (201509261549, OK)

  8. Client接收到命令,当前系统时间为2015-09-26 15:48,与Client提供的命令误差在5分钟以内,通过检查。

攻击过程

Hacker监听到了上面的整个过程,在主人离开了家,在21:09实施攻击。

  1. Hacker-->SmartHost: (201509261543, Login: accout John, password abc123)

  2. SmartHost接收到命令,当前系统时间为2015-09-26 21:09,与Hacker提供的命令误差超出5分钟,丢弃。

攻击失败。

分析

由于Hacker不知道static_key,不知道Client-->Server的明文是什么。所以他无法提取其中的帐号与密码信息。同时,他也没有办法更改密文中的timestamp。所以,无法成功突破。

防御等级:VVV

通抵御普通的Hacker攻击在时间间隔较长的指令伪装攻击。


5. 加序列号

上面的方式能抵挡超过5分钟的命令伪装,但是不能解决5分钟内的命令伪装问题。于是,我们在上一版的基础上,在指令中加添了Serial域,即序列号,用于防止短时间内的重复指令。

在通信中,我们会随机生成一个Serial:xxxxxxx,接收方收到指令后,会去查 SerialTable看5分钟内有没有xxxxxxxxx存在。
如果没有找到,则处理该命令,然后将xxxxxxx加入到SerialTable中。 如果找到,则丢弃该指令。

由于系统只保存5分钟的Serial,不会有太大的查表负担。

如此与时间戳结合使用,便可以彻底解决Hacker伪装命令的问题。

分析

与timestamp相似,由于Hacker无法获得明文,所以他没有办法修改里面的timestamp与serial。将已发送过的数据包再发一次,必然导致失败。

6. static_key泄密灾难

上面的安全措施看起来比较完善了。但是,它有3个前提条件:

  1. 加密算法过于强硬,无法逆运算

  2. 暴力破解代价大

  3. 第三方无法获得通信的加密算法与密钥

对于问题1,我们可能采用国际上公认的加密算法进行加密,如openssl中的Aes。
对于问题2,我们可以使得加密的密钥过于复杂,比如128字节的密钥进行加密。如果使用暴力破解,其代价太大。

问题3是最大的问题。
有句话叫作:“日防夜防,家贼难防”,由于用于加密的密钥是写在代码里的。开发工程师是再清楚不过了,加密的密钥非常容易泄漏。

一旦static_key泄密,那么所有的加密如同没有加密!Hacker所向披靡如入无人之地


解决思路一:

不允许普通的开发工程师涉及加密算法与加密密钥。将加密算法的设计实现工作交给公司核心人士去实现。其它普通的研发工程师只能拿到一个二进制的静态库或动态库。

但这也有一点需要注意的,不管是生成什么样的加密过程,加密的密钥必须不能是明文。比如:


const char *encrypt_key = "adi3dfa;9era";
...


因为生成的二进制文件里有保存明文,可以轻易地用工具搜出来。如:


strings libEncrypt.a


就会列出库中的所有明文。好奇心强的工程师很容易地就从中找出你的加密密钥了。
就算工程师没有泄密,Hacker自己去买台SmartHost,对程序用strings分析,也是能很轻松找出static_key的。

必须是动态生成的。如:


//! 这个名字别启得太明显,要大众化点
char encrypt_key[128] = {0};

//! 这个名字别启得太明显,要大众化点
void GenerateEncryptKey() 
{
    //! 在这里通过某种算法生成encrypt_key中的密钥 
}


这样,不能轻而易举地获取到。但是,这也不是说获取不到了,只要单步跟踪调试,也能获取,只是麻烦了点。

解决思路二:

信条:不能将加密算法设计者自己挡在外的加密算法不是好算法!

摒弃static_key的加密方法,每个产品在出厂时都有一个特有密钥unique_key,并且在服务器的数据有表。

以下以[]表示被unique_key加密的数据

SmartHost登陆Server

用户购买了SmartHost后,SmartHost首次启动,登陆Server。

  1. SmartHost-->Server: (uid=xxxxxxxx)[timestamp=201509291255, serial=82342, I am SmartHost, model=M1, Log in]
    注意:SmartHost在介绍自己uid时是用static_key加密,之后使用unique_key加密。

  2. Server-->SmartHost: [Allow]
    Server从数据包中提取了uid,从数据库中查找到对应uid的unique_key,用unique_key加密回复的数据。

  3. 之后的数据包都是用SmartHost的unique_key进行加密。

如此,只有数据库的super administor有权限得知对应uid SmarHost的unique_key。

Client与SmartHost

用户要使用Client绑定SmartHost,但Client本身不知道SmartHost的uid,也不知道SmartHost的unique_key。如何与SmartHost通信?
在 SmartHost 的背后有一个二维码,就是该SmartHost的unique_key。用户用Client上的二维码扫扫功能,获取该SmartHost的unique_key。

通信过程:

搜索SmartHost
  1. Client用UDP广播数据包:[timestamp=201509291255, serial=24234, tell me your IP address]

  2. SmartHost收到数据包后,用unique_key进行解密,验证timestamp域,发现结果正常 ,表示解密成功,证明该数据包正是发给自己的。于是回复UDP包:[timestamp=201509291255, serial=3234, ip_address=192.168.x.x]

  3. Client收到UDP数据包,用unique_key进行解密,得到了SmartHost的IP地址。

如果同时出现2个以上的SmartHost,只有使用了对应unique_key的SmartHost才能通过timestamp验证(错误的unique_key解密所得的timestamp是没法通过时间戳验证的)。

绑定SmartHost

后面的与主机交互过程都使用unique_key进行加密。

Client与Server

用password的md5sum当作unique_key进行通信,默认带timestamp与serial验证。

注册帐号

Client-->Server: (Regist: account=Lucy, password=98789) Server-->Client: (Done)

服务器在接收到该注册信息后,会将password的md5sum作为unique_key与client进行数据加密。以下以[]表示用unique_key加密的数据。

在注册时,加密等级是很低的。

登陆
  1. Client-->Server: (Login: account=Lucy)[timestamp=201509292100] 告诉Server自己的account,然后Server根据account到数据库查

    表,获得unique_key,并用其解密timestamp,再进行时间域校验。通过则表示登陆成功,否则表示失败。

  2. Server-->Client: [timestamp=201509292100, OK]

模拟破解

对于不了解通信协议的Hacker,即使使用包伪装与重发包的方式已经是束手无策了。
这里的Hacker,是指协议的设计者或对协议非常熟悉的人,假设他们:

  • 已获得static_key与加密解密算法

  • 不能接触到服务器与机密数据

  • 不能接触到用户手上的SmartHost

行动:
假设Hacker已通过某种方法加入了SmartHost的局域网。

  1. 通过监听器,捕获到了SmartHost的登陆包,得到SmartHost的uid。由于没有unique_key,得不到SmartHost与服务器的通信内容。但他知道密文解密后的明文内容,可能使用暴力破解法进行破解。但是时间成本太高。

  2. 如果监听到Client的注册过程就可以,因为注册数据包是用static_key加密的,可以破解。Hacker可以获得用户的密码,进而算出md5sum的unique_key的。用这个来伪装真正的Client,对SmartHost进行操控。
    此方法的关键点在于要抓到注册数据包,一个用户只有一次,而且要在与Hacker所在局域网中进行才有可能被抓到。如果打算对SmartHost进行攻击时,用户早都已经注册了帐户。

  3. 诱使用户使用盗号码木马App,从Client的手机中窃取Client保存在手机系统中的文件。从而获取Client的帐号密码,以及SmartHost的unique_key。

从上可得出,通过监听方式来破解似乎只有暴力破解法了。而更可行的破解方案还是盗号木马。
因为我们总得在手机上保存主机的unique_key与用户的帐号与密码。否则就得每次让用户去扫SmartHost背后的二维码,每次都让用户重新输入帐号密码登陆。用户肯定受不了。

关于上面的安全性问题该如何解决,博主还没有想到合理的解决方案,欢迎讨论。上面的讨论如有纰漏,欢迎指正。


博主从事智能家居领域研发,欢迎关注!

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

分享:
+ 订阅

云安全开发者的大本营

其他文章