朱钱杭,启明星辰ADLAB研究员,网名大菠萝。
随着物联网的普及,智能家居进入生活。虽然目前传统的操作系统、数据库越来越引起重视,但物联网的安全并没有引起重视,设备和云之间密码明文传输。
智能门锁安全
智能门锁涉及到很多的百姓家里面,但智能门锁的制造厂家从普通锁转换到门锁的过程当中,只在普通锁上面加了电控的控制器。在设计云、设计控制器的过程当中,他们认为这是一个密闭的环境,所以并没有进行安全保护。
第一个案例(出于对厂家的尊重和保密对本文测试的门锁厂家和型号保密)。本文测试的门锁,直接通过无线路由器控制那把门锁开锁。介绍两种情况,一种是知道密码的情况下把这把锁破解掉,另外一种就是不知道密码的情况下直接破解这把锁。
分析发现其实所有的指令从匹配到绑定设备,到开锁、锁门等等这些操作一共是用64个字节来完成的。为什么我们管它叫64个“圣旨”呢?这把锁和路由的通讯用的是UDP协议。我们知道UDP的特性,源可以伪造,可以任意广播,这是很方便的。另外一个就是,这把锁对于这64个字节不会去验证它的来源,不会去验证它是否可信,是否准确,会无条件的去执行。在这64个字节当中,SN是设备的序列号,就像车的号一样,在前挡风玻璃。如果你忘记带钥匙,厂家去应急处理的时候,能够直接通过序列号帮你开锁。所以序列号是直接写在锁的面板上面,只要打开盖子就可以看到,而且是对外的。State就是锁的状况,就是控制这把锁是开锁、锁门还是其他的操作。它的加密方式也是非常简单的,直接是两层。
通过开锁和路由之间通讯的,对比分析,从它的绑定到开门,这64个字节的模板里面,除了状态和序列号会改变以外,因为不同的设备会改变,而且不同的操作也会改变,其他地方是不变的。也就是说,这64个字节里面的62个字节,针对这个厂家这个型号的所有这把锁全部是管用的,全部可以起作用。你可以认为是厂家开发的时候偷懒的一种方式,也可能是因为产品经理急着让这个东西赶紧上市,赶紧推广到市场,我只能说厂家太自信了。
因为这把锁是云,可以通过无线路由去控制,所以在App Store或者是在Android的市场上面有厂家提供的App可以下载。App是谁都可以下载的,而且我们知道,现在App逆向也不是特别那么困难,这是我们把App逆向出来以后,我们发现在程序的代码里面,先不说654321是弱密码,这个厂家所有的锁用的都是这一个密码,654321在通讯,这是硬编码的。本身App,尤其是Android的话,放到上边里面,App可以做加固,但是这个厂家提供的完全没有做任何的加固。逆出来之后,清清楚楚的能够看到整个代码逻辑。
检测了5把电子门锁,可以说有4把电子门锁里面的Key是直接写死在代码里面的,这种情况可以说挺普遍的。控制这把门锁的逻辑非常简单,一种情况对方知道你的无线密码,手机连到你的无线里面直接访问这把锁。我们知道它是UDP的,可以是广播的方式。我们看到这个Mop是Find,是代表了你以什么样的方式作用于这把锁。当锁收到你的Find指令的时候,会直接把自己的SN序列号告诉到你的App里面。Key也就是654321,刚才的硬编码已经逆向出来了,这两个关键的东西我们都拿到了。第二步发送的数据包,只要Mop改成Open开锁的状态,直接就把门锁打开了。我们还试过更好玩的,如果我们用广播包去做的话,直接放到桌子上的6把锁全部解开了,完全不会去考虑来源是否可信。
下面是没有Wi-Fi密码的时候如何做?
我们说了SN号是写在锁上面的,为了厂家维修。如果到了门口,推向面板,也开启这把锁,是通过云来控制的。这里有一个问题,SN号需要需要你下载,硬编码是654321,发送指令包,这把锁就能大。最恐怖的事情并不是在这里,我们发现这把锁的SN序列号是有规律的。我们抽的6把锁里面,有3把锁是连号的,我们可以看到这4位数在变。无论在哪儿,我下载完这个App,把数字从头到尾排一遍,是不是家家户户的门都开了。服务器会觉得你好有钱,各地都有房产,都能开门。
简单总结一下,这个锁没有绑定手机端,设备号可以预测,App本身也没有做加固,云这边还有一个问题,就是刚才我说的暴力检测SN号,云没有做尝试次数的阻断,你可以任性的去尝试,不停的去尝试。
智能手表安全
智能手表是用来防止小孩丢失的,上面有GPS定位,可以跟自己家的孩子对话。目前看上去这些表都是比较安全的,它不会像锁那么脆弱,去连Wi-Fi路由等等,它是通过3G、4G通讯的,自己又有比较强的加密通讯的模式。同时我们知道,如果说你要去劫持3G、4G,不是不能做到,第一个是设备,第二个是时间和场地,你还要有目标人,整个过程会变得很复杂,成本高、耗费时间。如果说你是针对某家的小孩,如果针对他的智能手表搞一些坏事情的话,付出的代价是比较大的,成本和时间都是比较多的。但是问题就出在这个智能手表App的云上面,这个App谁都可以安装,没有智能手表也可以安装这个App,也可以去注册,也可以绑定设备。这个App的问题出在重置密码,我们知道,你要拿对方的账号,只要重置密码就行了。如果说我针对某户人家的小孩有恶意的话,我知道他的手机号,总会有一个手机号会注册给他们家小孩的智能手表上面,知道手机号并不难。我只要知道手机号,就可以劫持这个手表。从表面上看,这个App因为是手机发送序列号,密码又是6位数字加字母,排列组合方式有568亿次,如果用电脑去尝试的话比较困难,这个速度尝试的比较慢,1秒钟100次,实际上我们尝试的速度比这个快得多,这个速度是远远不够的,肯定不能用这个方式去暴力尝试。
再往下走就是手机重置密码的时候,如果我们知道手机号,不能暴力破解密码的话,我们尝试账号找回。账号找回的情况下,厂家有可能考虑到你换手机,允许你新的手机号注册进去,这个时候手机就需要收一个验证码。我知道这户人家的手机,要劫持这家小孩的智能手表,我肯定会用他的手机号,但是验证码会发到他的手机上面,我不可能找他要验证码,这个很容易引起别人的警觉,这种方式似乎是安全的。我们抓了一下数据包,就是App跟云这边的数据包,手机找回密码,发送验证码的数据包。他的验证码是4位的,提交验证码的数据是4位的,并且全部是数字。这个验证码本身是比较简单的。
我们来理想化一下,这4位的验证码我们从4个0排到4个9999的话,其实如果1秒尝试100次的话,我们100秒就能排列完,而且这个云对暴力尝试也没有做阻断。我们知道验证码是有时间的,一般来说验证码发给你,让你去试这个验证码,通常短信里都会告诉你,差不多30秒到50秒的时间。
这个智能手表的另一个问题就是,它的App会产生一个签名的串,当然这个串是不确定的,并不是设备编号,是一个App里面带出来的。我们尝试了几次发现,每次签名串跟验证码是一一对应的。我不知道厂家为什么这么设计,厂家在设计这个产品的时候一定有一张表,这个表里面有两列,一列是签名串,一列是验证码。在服务器云那边,你发送的这个签名串就会扔给你对应的验证码。在App里面,也有这张表,我不知道厂家为什么这么设计,这样就导致所有的验证码是可见的,而且本身App是可逆向,可修改,意味着你可以修改签名串,你就会知道他给你什么验证码了,这是第一个漏洞。
另外一个漏洞更可笑,当你提交错误的验证码,服务器给你返回的时候,会把正确的验证码给你反馈回来。这个事情其实不能怪程序员,我简单说一下,2001年的时候我写过一些数据库的攻击,但是那个时候我写了一篇文章,那个时候想过一个问题,就是为什么这种漏洞会出现。其实你们可以去新华书店,去海淀图书馆,看那些教你编程的那些书,甚至包括以前早期的MSDN上面的样例。所有上面的代码都是有问题的,不会教你如何防注入,如何防跨站,甚至讲HTML的书上面会非常明确的告诉你,你要做验证,在本地做验证减少服务器压力。这不是程序员的错,教科书上面就是这么教我们的。这个案例我们可以说一半以上的智能设备上面都遇到了,减轻服务器压力,验证码由App本地来处理,他可能认为App不像电脑上的程序,不会有人看源代码,不会有人去破解。我们现在做互联网站,做服务的开发人员有一个很大的区别,就是做物联网开发的人员,他们现在的思想还是在5年前、10年前那种想法,就是用户一定是按我所想的方式去用这个产品的,他绝对不会超过我想像的范围,他肯定是这么想像的。这个智能手表就不用说了,那么多问题,甚至连验证码都原封不动的反馈给你的话,这个智能手表可以直接App连接到那个智能手表去控制。这个是登录页面,之后到第二个页面,正常来说,第二个页面应该是检查的,确认你的确是登录过了。但是这个智能手表云的第二个页面是直接可以敲地址进去的,敲地址进去的时候,我们看到在底下有令牌,令牌的问题只在登录第一个页面的时候做验证,第二个页面去操作这块手表的时候只是通过User ID来判断的。也就是说它的做法是在数据库里面产品的列表,后面判断就是一个User ID,去操作这个设备,中间没有做验证。如果你去分析这个App的话,自己买一块智能手表,你分析它整个流程的话,我知道第二个页面的路径,直接就可以跳到第二个页面。暴力一个User ID的话,可以把这个厂家卖出去的智能手表全部可以控制,这也是很弱的漏洞,至少现在看来,比那个还要弱,一开始认为是很安全的。
车联网安全
车联网的。其实厂家犯了一些错误,他的App,我们知道车联网通过App去连接那个汽车,检查它的油号、胎压,包括24小时定位这辆车。他的App基本上每半年更新一次,但是他犯了一个错误。一个老的App有一个功能就是重置密码,这个重置密码的页面是有一个缺陷的,就是URL跳转,原始验证有没有通过,直接第二个密码带着那个参数扔上去。虽然他的App是更新了,但是服务器云上面这个第二个链接还在。所以你只要构造豹纹,直接访问第二链接的话,一样的账号可以重置现有的密码。在用户购车的时候,在4S店我们知道,现在车联网基本上是拿你的油箱,大多数是用手机号作为用户名注册的,这个手机号也是很容易拿到的。再就是车架号,我们知道车的前挡风玻璃全部都有车架号,所有的都是。验证码跟前面那个一样,直接反馈到本地校验,反馈过来的验证码直接写在上面了,重置验证码,手机短信交互,刚才说过了类似的漏洞,就不说了。我们拿它反馈过来的验证码,再还给他,输入新密码的时候,直接就验证成功。这是登录进来以后的页面。
为什么我说故事还没结束呢?这个一开始我们想得很简单,就是进去以后拿到账号就可以控制车了,就可以远程开锁了。但是实际上不是那么回事,还有第二层服务密码。在拿到第一层密码的时候,只能去看这辆车的信息,比如油耗、胎压,不能控制。第二层服务密码正常的流程需要打厂家的400电话,他要核对你的车主身份,信息全部核对完之后才会给你重置密码,所以这条路肯定是走不通的。那么没办法,我们只能去逆向这个App,IDA是个好东西,我们逆向这个App之后,发现所有的操作都是自己创建的那些API的接口。当然作为第二层密码绕过登录的话,我们肯定关注的是登录的接口,就是Log Manager那个接口。这个是HTTPS通讯的,做得很安全,我们Hook了这个通讯之后,我们发现字符排列是基于Base64的。我们尝试用Base64去解,我们以为这个事情就可以解决了,但是解完之后我们发现是有乱码的,说明这个方式肯定不对,不完全是标准的Base64,肯定这里面会有猫腻。因为不可能是传输乱码的方式。我们看到前面的都是明文码,Password,设备号和时间值,这些东西都是明文,都是我们正常能理解的。只有后面那一串是乱码,这里面一定是有问题的因为正确的解开应该完全是明文。
我们再跟着逆向出来的代码往里面走,我们发现是JWTEncoder的加密方式,这是比较常见的加密方式。我们从代码里面也能看到,它是用两个小数点隔开三个串,前面两个是Base64,用一个固定的Key加密以后,再用小数点拼到第三部分。我下面写了一个公式,加密方式基本上就是这样,前面两个自己做Base64拼起来,第三部分是前面两个拼起来,用固定的Key去做。但是这里又犯了一个错误,就是我们说的电子门锁的错误,就是它的Key是写死在代码里面的。如果这个Key是动态的话,这件事情做到这里就结束了,没法再往下进行了,因为是写在代码里面的,就意味着整个加解密部分我们都可以还原了。
我们自己写了一段代码来尝试能动性生成这样的加密串。在生成加密串的时候,我们发现跟它实际的有一些不匹配。实际上他做了一些手脚,把Base64里面的算法自己做了一些小改动,不是标准的Base64算法。知道它的改动方式以后,只有字符替换方式以后,我们就可以完全模拟出它的加密串了。它传输的是GZIP的,解开之后拿到的也是Base64串,并且我们发现,它也是基于JWTEncoder来做的,也是那个Key,所以对于我们来说全部都是明文了,全部都解开了。
到这里登录过程就全部分析完毕了。这个车最后我们能做到的就是知道车主的手机号,我们就可以远程开锁,24小时知道车的定位,还可以把车打着。因为我们知道,现在的车互联有一个功能,就是冬天空调暖风可以预热,所有车的空调风暖一定是通过发动机热量的小水箱提供的,所以发动机一定会打着。至于自动挡的那个锁是锁着的,动不了的,其实90%的锁里面就是一个塑料的卡扣,撬开以后就可以直接坐车了。这个车大多数的通讯指令,分别是开锁、关锁和24小时定位,就是随时可以知道这个车的位置,这其实对于车主来说是比较隐私的事情。这个洞是去年我们搞车联网的时候发现的,应该后来已经补了,后来我们没有再跟进,但是我相信它在App这一块,应该还有很多问题可以挖出来。
中间整个过程里面,我直接过滤到命令这一块,因为中间还有一些小技巧,就是如何越权,从一个账户跳到另外一个账户。首先我自己手上有一个App的账户,有车联网的账户。我中间有一些小技巧,可以跳转到其他车的车主上面,直接操控他的车,这些小技巧今天我不能公布,因为对厂家当时确认是要保密的。
今天对于物联网的安全我挑了三个比较贴近我们身边的,包括智能手表、门锁和车联网。物联网目前安全问题很多,而且我们说状态也是差不多在5年前到10年前的,最大的原因一个是技术封闭,他们不太愿意接受外来的新的安全观念或者是防护措施,我甚至碰到过这样一件事情,我们在做风险评估的时候,他们很像那种在线交易系统的厂家。当时我们发现那个服务器上有洞,而且补丁也是半年前就出来了。他们有一句话给我的印象特别深,就是我这个补丁打了要死机了,你担责任吗?真的就是这么回事。对于传统厂家也是这样,他们的第一目的只要是能用就行,任何修复方式、防御措施串到他们的设备里面,给他们加入进去之后,他们非常担心的就是如果出了问题我可以担责任,现在没有人黑这个设备,平平安安的运行,这是没有问题的。补丁困难,对于车联网这一块,除了特斯拉以外,包括宝马、奥迪、英菲尼迪、福特里面的设备和系统,我问过一些厂家,我身边有很多朋友是做汽车行业的,他们跟我说,一旦发现漏洞,你让我们全部召回吗?不可能的事情,只能等下一代产品再说。但是物联网的安全的确是一个很严峻的问题,而且就在我们身边,近在咫尺,就是这么简单。
提问:原来我搞过一个自行车的系统,那个系统比较低级,直接破了沙盒之后过去了,最可笑的是Windows7的系统,不打SPE的补丁,很容易的拿下了,是一个城市的自行车系统,在终端上直接搞到了数据,数据只是原封不动的看了一下。最后给他们通知的时候,他们也是同样的话语,就是如果我这个系统出了问题的话,我们负不起这个责任。他说他们的系统由于是定制版还是什么原因,说一打SPE补丁的话就会出问题,我想问一下是这样吗?
朱钱杭:是简化过的Win7,我们做过外面的ATM机上面的设备,打补丁之后,有可能真的是蓝屏了,里面的系统文件是不全的,只要能够跑起来就OK了。
提问:大家都知道,也是世界公认的,Windows是一个公认的靶系统,从来没有正式存在过。我是一个新人,就想问一下为什么不会基于Linux开发呢?
朱钱杭:从开发情况来说,Windows的程序员要远远多过Linux的程序员,原因就是MSDN做得太好了。在Linux底下你开发,用其他的开发语言可能出来会好很多,但是毕竟只是一种脚本。在Linux底下做开发的话,帮助文档的确有,要你自己去开源社区里面一个个去找,甚至有些时候要你自己一口口啃代码。微软把SDN做得太好了,全部翻译成中文,有什么看不懂的,没有比这个更方便的事情了。包括现在,我们说全宇宙最牛的开发平台是什么?当你敲下一个小数点的时候,所有后面的关键字提示全部列出来了,你把代码写出来的时候,甚至会给你标出来哪个地方写错了,没有比这个更加聪明的平台了,所以大家都去开发Windows,这是很简单的道理。
提问:菠萝兄你好,我想问一下客户端和服务通讯这种情况怎么保证安全?你有什么建议没有?你刚才就说通过抓包,研究里面的规则,还有通过逆向。有没有一个比较推荐的方法去防范这样的问题?我们不说物联网,我看你刚才逆向了一个应用,不管是Android还是iOS,都可以逆向,都可以抓包。你对于这一块有没有什么建议?服务端和客户端通讯方面。
朱钱杭:通讯这一块,跟传统的支付基本上差不多,动态Key,非对称加密,多层校验,基本上是这样,只不过现在很少厂家去做而已。
提问:不管是公钥还是私钥,只要破解App端都可以拿得到?
朱钱杭:如果是公司钥的话,拿不到私钥没有用。
提问:如果是这样的话我可以伪装,可以模拟客户端发请求。
朱钱杭:你是可以模拟客户端发请求,但是你只能拿到4个密钥的中间2个,也就是说,你只能拿到单方向通讯的数据,另外一个方向回来的你是拿不到的。
提问:如果说我把App都破解的话,我就可以重装App,自然可以抓取数据。
朱钱杭:你完全逆向App,完全破解出来,完全模拟这个App,把双向的数据明文全部拿到,这是没错的。你想知道这个防御方法是吗?
提问:我想这一块有没有成熟的解决方案。
朱钱杭:以我目前知道的情况是没有的,我实话实说,真的是这样。如果说你能把App全部破解出来的话,整个模拟出来的话真的是没有。因为全部通讯,包括代码逻辑,包括整个判断措施,你全部都能模拟了,你就是开发商。你问我如何去防御?Android所以做得比较好一点,苹果因为要求要检测你的程序,你不能去那种自己定制的。以前是Android比较容易被逆出来,现在是苹果的比较容易被逆出来。