2022 SDC 议题回顾 | 从后门到漏洞——智能设备私有协议中的安全问题
2022-11-9 17:59:44 Author: mp.weixin.qq.com(查看原文) 阅读量:29 收藏

大家好,我是来自绿盟科技格物实验室的魏凡,我主要的工作是挖这种嵌入式设备漏洞,物联网、工控、车联网都会涉及,只要是设备端的都会覆盖到。

本次带来的议题主要和物联网相关,接下来会分为4个部分来分享。第一部分是概述,第二部分会讲我对私有协议逆向分析的几个关键点的理解,这也可能会作为第三部分的一个铺垫。第三部分是本议题的核心内容,也是和标题相关的。标题为什么叫“从后门到漏洞”,相信大家一定都比较好奇。第三部分,在某私有协议漏洞挖掘之旅中,我会为大家揭秘为什么叫“从后门到漏洞”。最后一部分是总结与建议。

01

概述

首先开始第一部分:概述。智能设备的私有协议,一般来说我们会认为它是那种没有文档化的协议,所以说它格式是未知的。

一般来说有以下几个特点,从功能上来说,这个协议一般是用来作为运维管理或者服务发现。从监听的端口来说,一般来说是 TCP或者UDP的这样一个比较大的端口。大家看到有一些设备有些比较大的端口可能就得注意了,这可能是一个他用的私有协议。用这个协议的设备多数作为一个服务端存在,他会去接收客户端的请求去做一些事情。
它既然是服务端,其实我们在研究的时候可以去厂去厂商的官网找一找,可能会有一些这样的客户端。私有协议其实就是因为它格式是未知的,虽然说相对而言分析要稍微难一点,所以说公开漏洞比较少,大家如果有兴趣去看看搜搜CVE,这种设备类的,可能90%以上的都是这种HTTP、UPNP协议,私有协议可能比较少,但是私有协议一旦出现这种安全问题,影响都非常严重。
较早的时候,比如知名的华硕 udp 9999端口漏洞,当时影响非常严重,然后还有这种比较臭名昭著的磊科的后门,很多勒索组织都在用,大家应该都会了解一些。

02

私有协议逆向分析中的几个关键点

下面是第二部分,我会讲一下私有协议中的几个逆向分析当中的几个关键点。那么私有协议其实它也是协议,因为它是人设计的,所以它不会反人类,所以说格式和公有协议也都差不多,它也会有一个这种header加 body。

header一般来说会有这种魔数,魔数就是 magic number,作为标识一下唯一标识这个协议,然后可能会有版本号,包括操作码,还有一些长度域,甚至还会有一些校验和来校验头部。
body部分其实就比较偏数据部分。可能会有一个长度域加一个数据部分。当然比较复杂的可能会有这种body加header的这种来回嵌套,这种协议就相对而言比较复杂一点。那么我们了解完这个协议的一般格式之后,我们要开始分析这个协议,我们从哪里开始入手呢?
一般来说我们是想挖这种远程可利用的漏洞,既然要挖远程可利用漏洞,其实我们主要还是要看这种网络通信函数,就是远程我们可以给它发包这样的一个函数。
其实像recv和recvfrom它并不是绝对的,recv可以接受UDP的数据包。同样的recvfrom也可以用来接收 TCP的数据包,它们不是绝对的,其实看函数原型你就知道,它其实主要是参数的不一样,你参数怎么设置它怎么接收就行了。
但是有时候我们可能在协议的ELF文件里面找不着这个通用函数是什么,就得考虑一下是不是在它调用库里面。因为有的厂商可能会考虑到通用性,它会把比如这种网络通信函数给全部封装起来,封装成调用库给其他二进制文件调用,大家如果找不到通信函数的时候,可以考虑去这种调用库里面看一看。
了解完入口点和协议格式之后,静态分析其实已经差不多了,但是如果这个协议比较复杂、字段非常多的话我们就得考虑一下动态调试了,调试可能会对我们的分析会有很大的帮助。
有一位不知名研究员曾经说过,如果你拿到这个设备的调试权限,你这个漏洞挖掘的工作就成功了一半了,一般来说拿调试权限的思路也都比较常规,有很多大家可能都知道,比如说软件方面,设备自带ssh;硬件可能有什么JTAG,这种串口之类的,可以进去看一看。
我这里重点说两个方法,一个是这种修改固件增加调试后门。这种是我们用的比较多的,一般来说你这个设备的固件没有签名的话,我们就可以通过这种方式去改它这个设备的固件,再通过升级方式给它刷回去。
还有一个利用设备的已知漏洞,可能大家会问:你拿设备已知漏洞有啥用?它这个最新版本可能就没有这个漏洞。
但是我们可以考虑一下,这个设备如果可以降级的话,再加上它有那种可以RCE的漏洞,我们给它降个级,降到这种存在RCE的版本,然后我们再去patch升级程序,让他再升一个最新的,我们拿到最新的版本,其实就是有调试权限的,对这两个点大家可以着重注意一下。
功欲善其事必先利其器。我们拿到调试权限之后,以我的经验来讲,智能设备大部分都是arm和misp的,可能我会准备一些这种静态编译的一些小工具,比如放个gdbserver上去调一调,用的比较多的可能就是busybox/gdbserver/tcpdump,这个可以网上找,应该能找到比较多,然后也可以自己静态编译。

03

某私有协议漏洞挖掘之旅

第三部分是我们的核心内容,也就是我们的标题“从后门到漏洞”。这里我得强调一下,我这里讲的所有漏洞,我们都已经报给厂商了,然后厂商也已经确认修复过了。
一个比较偶然的机会,我们拿到了一个某厂商的智能设备,我们发现它开了一个比较大的端口,他用了一个私有协议,我们也没查到这个协议相关的文档、官网上也没有这种协议的管理客户端,我们就对它比较感兴趣,准备开始分析它。
首先我们先考虑一下它协议的入口点在哪里,这个协议比较有意思,一般来说很少能见到这种私有协议,还会去用这种SSL那种加密去传输的,它就用的是 Cyassl_read和Cyassl_write,但是它这个协议是它这个设备是作为一个服务端,但是它只单向认证,相当于他不认证客户端,任何客户端都会给他发信息。不是双向认证,可以参考一下这种https这样的一个双向认证这样的一个思路。
常规的漏洞挖掘思路是什么?我们拿到协议之后,我们分析完入口点其实就可以跟踪数据流向。我这边画了一个图,是我这个设备 ELF文件里面协议的数据流向,从 ssl_read开始,然后逐步往后跟,看看它这个数据包到底传的怎么校验的。
然后逆向分析其实就ok了。但是大概看了一下这个协议其实相当复杂,字段特别多。
我这里提出了一个非常规的这样一个挖掘思路,我们先可以主观考虑一下我们智能设备的常见协议,我们是怎么挖漏洞的。比如说我们看到有一个设备,它有一个upnp协议,我们一般会测一下它是不是存在这种接口的命令注入,因为它很多参数都带到了iptables里面。
然后比如拿到一个MQTT的协议,我们可能第一反应是它这个协议是不是存在这种未授权访问的情况,为什么我们会这样去想呢?
因为我们了解这个设备协议到底是做什么的,它有什么功能,我们就能快速的定位到这个协议,它哪些地方可能比较脆弱,我们认为协议的脆弱点就是容易出现漏洞的地方,我们就考虑一下我们能不能把思路用到我们这种挖掘私有协议上面。我们既然是以发现漏洞为导向,有时候不需要对这个格式太过于纠结,我们可以先看一下这个协议它到底是干什么用的,接着对脆弱点进行一个重点突破和分析,然后看一下会不会有这样的一个漏洞。
我们这个厂商设备协议功能非常简单,就两个功能。一个是reboot,一个就是restore factory,把这个设备恢复到这样一个出厂设置,它这个功能比较简单。大家看到这个功能会想起什么呢?会觉得可能就是一个这种运维管理类的这样一个协议,就是那种技术人员用来做运维的。
我们考虑到这种协议,第一反应是什么?我们会觉得这个协议它可以reboot和restorefactory,是否能够不通过这种认证,就能去调协议的的这种接口,我们就去考虑这个协议,重点去看这个协议逻辑,看有认证逻辑那个函数,然后我们其他的前面什么乱七八糟的什么checksum不看了。
这个协议的认证逻辑它是会取一个全局变量作为一个初始的一个字符串,这个字符串会经过三次的处理,最后和用户传的串进行一个比较,从这里看好像是有一个这种认证的过程。
它会把一个初始串处理三次,然后和用户传的一个串进行比较,然后三次处理。大概是这样的,第一次是一个移位和混淆的操作,它这里会和两个特殊的字符串进行一个移位和混淆的操作,然后后续两次都是一个标准的MD5的算法,写了一个md5_digest的函数,然后调的标准的md5_init、md5_digest和md5_final。这里IDA没有把 Md5算法都给识别出来,从md5_init里面4个链接变量可以看出。这里我详细的把这个逻辑给大家描述一下。
这个逻辑相对而言还是比较复杂的,设计的比较巧妙,我们看一下这个逻辑好像没啥问题,那么看一下它初始字符串怎么来的。
因为它后面一系列的变化都是依据初始字符串过来的,调用认证函数之前,它有个函数将会给全局变量去赋一个值,比较有意思的是它直接把一个固定字符串admin拷贝到全局变量上去。
我们只要传一个这种固定的字符串,admin经过三次变换后的一个凭证,就是这样一个16字节的hash值,然后就可以完成认证过程,相当于我们就可以控制设备的重启或者恢复出厂设置了。
其实大家可以想一下,这个协议从设计来说是比较精妙的,首先它的传输就用的 ssl,在很多私有协议里面都根本看不到。
然后我们就根据这个协议里面的那些字符串,它里面有一些字符串,还有一些协议名之类的,我们去搜了一下,比较有意思的是我们找到一个专利。
从这个协议专利的摘要和名称,大家也可以大概看出来,就是一种设备网络设备的控制方法,也和我们想的一样。它就是用来控制设备的,就是用来做这种运维的。
比较有意思的是这个专利的就是所有权方并不是我们刚才搞的厂商,它是另一个厂商。然后这个事情我们觉得挺有意思,我们可能研究的时候,大家会觉得这种SDK之间的复用比较常见。这种协议的调用我说实话我都是第一次见,我们就赶紧去搞这个厂商,就找了一个专利所有权的厂商的设备。
我们先去看了一下,我们之前觉得这个协议这么复杂,不可能说功能就那么简单。这个功能就比较全了,除了前面提到的重启和恢复出厂设置以外,还能修改设备的各种配置,它还可以通过tftp传一个固件过去用于设备升级。
其实这种模式在IOT设备挺常见的,喜欢用这种tftp来搞固件更新。它这个功能就比较全了,其实它和web的功能其实就相差无几了。它功能非常强大,对得起它这么复杂的格式了,我们赶紧拿之前 poc打一打。结果发现没打成功,我们赶紧去看看这个初始字符串是怎么来的。
它用web管理员密码作为初始字符串去生成后面凭证,功能其实和web也差不多,然后它用一个web密码很合理。我们再看看他认证有没有其他的问题。
我们重点就关注它 md5_digest的函数,它会调用md5_init/md5_update/md5_final,我们发现它第三个参数是一个长度,是参与运算的长度,然后它会判断一下它参与的长度,这个长度是不能为0的。如果是0的话,相当于它会直接退出,这个函数会直接return。
比较有意思的是这个长度是我们可以控制的,它这个长度是我们这个协议的数据包里面的一个字段是用户可控的,我们就这有这样一个认证绕过的这样一个方法。
更有意思的是它传入tftp这个文件名,它也是我们协议数据包里面一个字段,它的本意肯定就是说你传一个文件名,我tftp过来,然后我给你设备更新一下,结果这个文件名也是用户可控的,然后结合我们前面认证绕过直接就给他rce了。
这个厂商设备种类非常多,啥他啥都卖,然后我们就考虑一下这个漏洞是否是通用的,它是不是能打其他的设备,然后我们就找到了一个它的另一类设备。
然后从功能上来讲,它和我们看到的第一类设备其实差不多,这个地方也比较搞笑,它这个地方也可以认证绕过,它传入的长度,还是在数据包里面被用户控制了,而且 md5_digest的算法中却没有验那个长度,但是它不会退出,它会继续运算。
对于一个标准的MD5算法来说,你传入MD5的参数为0的时候,它不是说就是报错或者什么,它会生成一个固定的串。你无论传入什么,你input是什么,它最后output永远都是这样一个hash值,相当于也让我们就控制0,传这样一个16字节的hash,然后我们又可以过第二类设备了,搞到这两类设备之后,我们其实就在想一个问题,好像厂商的开发虽然不一样,但它好像对md5_digest情有独钟,老喜欢在这个地方搞点什么不一样的事情。
然后我们就考虑对这个厂商的设备进行一个比较全面的评估,看一下它到底到底有多少种这种可能存在的问题。我们最后又找到一类设备,它存在另外一个问题,还是按照我们前面提到的那种认证算法进行认证,它也是第一次参与MD5不可控,第二次是用户可控的,然后它这里的话就处理的比较好,它对那个长度进行的判断,不能为0,而且它会对返回值进行一个校验。
不能为0我就为1对吧?我们考虑把 md5_digest的运算长度搞成个1,相当于最后就只变成了只有一个字节参与 MD5运算,相当于我们参与运算的值就在0x00~0xff之间,这256个字节,相当于我们会生成256种hash。
我们就利用我们写的代码生成一个所谓的字典,有256个hash,而且它这个协议没有去设尝试的最大次数。
我们可以无限发这种请求,这个实现绕过实现过程就是这样的,我们构造一个数据包,然后控制那个长度为1,遍历我们刚才生成的一个256字节的hash字典。然后我们发送到设备端,看一下返回值,因为错的时候返回值是另一种情况,对的时候它返回值是不一样的,然后我们拿到正确的hash之后,我们就可以任意控制我们这个设备,也就是说我们在厂商的设备里面发现了三种完全不同的这种绕过方式。
这里我小结一下,我们从这三个漏洞里面可以看得出来,虽然它厂商这几种设备它都是一个厂商生产的,它针对我们私有协议的实现上,也会出现那种相似的脆弱点,你看它们三个全都在md5_digest那里出了问题。
第一个是不验证返回值,第二个它不验证这种传入长度,第三个可能它有这种意识,可能它会觉得我要验一下这个长度不能为0,但是它验的不能为0,可以为其他值对吧?相当于验了又好像没验?最后结果反正都是被绕过了,它也高明不到哪去。

04

总结与建议

通过从后门到这三个漏洞这样一个漏洞挖掘过程,我们得警惕一下这种私有协议的供应链漏洞,因为后续我们对其他地方又进行了一些研究,我们发现不止我们前面看到这几个厂商在用这个协议,还有其他一些厂商也在用这个协议,我们传统的供应链漏洞可能大部分都处在这种SDK上,这种供应链漏洞可能比如你发现一个,然后报给最上游的供应商,可能第一反应就能把这种漏洞给修掉了。但是像这种协议相关的可能修都不好修,而且也不好发现,觉得更加隐蔽和非常的难以修复。
最后是给厂商的开发人员的建议,其实我觉得协议的设计和实验上应该尽可能的去用白名单。
比如我们讲的协议,设计上它用的SSL觉得很安全,但是这个协议很明显不是给这种普通用户用的,因为普通用户它可以通过web管理。完全可以增加一个客户端校验,就是你服务端也要校验客户端的证书,相当于这个协议只能厂商去用,你们其他人根本用不着,这样攻击者也用不着对吧?这样不就可以避免很多问题。
包括我们看到的三个这种绕过的漏洞,那就像最后一个开发一样,他可能觉得这个不能为0,那就做了一个不能为0的判断,但是有没有考虑到这里本来应该是个长度应该就是16对吧?因为输入和输出都是一个hash,长度为什么不直接写死写成一个16,就不会出现这种问题了。采用这种白名单的设计思想,就可以避免很多这种情况。
最后我还有几句话想说,我个人觉得像这种智能设备这一块,目前碎片化还是非常严重的,每个厂商它这种套路、设计思路都不一样,没有一个非常通用的一个套路去挖漏洞,但是管它白猫黑猫,挖到漏洞就是好猫。今天我的演讲如果能给大家带来一些启发,我觉得就挺开心的,谢谢大家。

文章来源: https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458482967&idx=1&sn=5f9b0c570ffdd586f04083e6a062c4f0&chksm=b18e499d86f9c08b79b760a5ee53c73682189a98fcfb9121108cf913b8f32b6366f90209b0fc#rd
如有侵权请联系:admin#unsafe.sh