天府杯华硕会战的围剿与反围剿
2021-11-04 19:07:00 Author: paper.seebug.org(查看原文) 阅读量:70 收藏

作者:Yimi Hu & Light @胖猴实验室
原文链接:https://mp.weixin.qq.com/s/k1ouK1Gyxpped0ZK4H4h7g

1、前言

2021年7月中旬,天府杯正式公布今年的比赛题目,笔者也有幸参与了今年的天府杯比赛。按照PwnMonkey & DC0086公众号的技术方向,我们打算来聊一聊其中关于IoT设备的项目。本次天府杯一共有2个IoT设备作为攻击目标,其一是华硕路由器;其二是群晖NAS。

在这两个设备中,群晖NAS咱们就先放一放,因为天府杯上这个设备并没有被打下来;而华硕路由器可以拿来好好说一说。在华硕路由器被宣布为天府杯比赛项目之后,华硕做了2次更新,每次更新都会导致一群小伙伴呜呼哀哉,但是最终还是没有拦住优秀的攻击者。那么,在后文中,我们就一起来看看华硕路由器这个设备以及华硕官方的两次围剿。

PS:由于太久没有更新文章,排版技能生疏,导致昨天的文章格式稀烂,所以今天调整之后重新发了一遍,抱歉给各位同学带来了不好的体验。

2、设备摘要

相比于我们此前讨论过的各个设备,华硕路由器不用花太多时间在固件获取上,因为设备自带了telnetd,只需要在web管理页面设置一下,就可以直接使用telnet登陆设备,将需要分析的文件拿回本地。我们选用的路由器型号为RT_AX56U_V2,固件版本为3.0.0.4.386.42844,后文中也是以此型号和版本展开叙述。

在登陆设备之后,我们可以简单浏览一下端口监听情况,用以帮助我们选择目标进程,将端口监听情况做一点点整理和筛选,我们发现有以下几个进程可能会出现问题:

图片

图2-1 端口监听情况

上图被筛选出的5个进程分别是envrams、wanduck、cfg_server、httpd和infosvr,其他进程或者是第三方开源程序或者是仅监听了127.0.0.1端口。第三方开源程序维护者众多,在其中发现漏洞可能并没有那么容易;而仅监听本地端口的程序即便有漏洞也无法直接利用,所以把优先级放低一些。事实上,本文要提到的3个漏洞也的确出自这几个进程。

此外,由于华硕路由器的固件是遵守GPL协议的,所以我们可以在网上找到一些相关的代码,虽然我们没找到最新版的代码,但是以往代码同样很具备参考价值,其中梅林固件的代码很具备参考价值,链接如下https://github.com/RMerl/asuswrt-merlin.ng。在我们逆向过程不太顺利时,可以参考一下这里的代码。

3、第一次围剿

华硕官方在8月26日,更新了一个版本,除了修复大量已有CVE编号的漏洞之外,还修复了一个envrams暴露的问题,如下图:

图片

图3-1 华硕官方第一次围剿

上图中,红框部分即是导致大家呜呼哀哉的更新内容,我们来深入看一下。

如果用IDA分析过httpd或者cfg_server等程序,那么一定会发现华硕路由器的经常会调用nvram_开头的多个函数,如下图:

图片

图3-2 以nvram_开头的函数

这些以nvram_开头的函数,绝大部分是和设备的各种配置相关,其中set是保存或更新配置、get是获取配置。如果一直深入挖掘nvram_系列的函数,会发现最终会执行到和内核通信的socket,猜测华硕设备应该是通过这种方法提高了配置访问速度,并解决了同一个配置可能存在多个地方以及更新不同步的问题。

而我们将要讨论的envrams就是提供了一个获取和更新配置的接口。通过简单的逆向,就可以看到envrams监听了tcp5152端口,支持show、get、set、commit、rall等指令。原则上,envrams仅能获取和更新/mnt/nvram/nvram.nvm中的配置信息,见下图:

图片

图3-3 程序envrams可以获取和更新的配置信息

该文件中的部分配置信息如下图所示:

图片

图3-4 nvram.nvm中的配置信息

看起来,并没有什么值得一提的配置。实际上,我们可以在nvram.nvm中写入其他进程使用的配置信息,这样一来,设备在重启之后,nvram.nvm中的配置信息就会被加载到内核中,由于nvram.nvm的加载时机比较晚,所以会覆盖更新已有配置。举例来说,我在envrams中将x_Setting的值设置为0,如下图:

图片

图3-5 在envrams配置x_Setting为0

那么设备重启之后,x_Setting的配置就被更新为0了。这意味着,设备误认为自己刚刚被恢复出厂设置,打开web管理端口不需要输入用户名和密码即可直接登陆。由此,造成了非常严重的影响。

华硕官方对这个漏洞的修复方案极其简单粗暴,给iptables增加了一条规则限制了5152端口的访问,如下图:

图片

图3-6 华硕官方修补方案

4、第二次围剿

华硕官方在10月7日,又更新了一个版本,其中修复了一个信息泄露问题,如下图:

图片

图4-1 华硕官方第二次围剿

上图中,红框部分即是导致大家呜呼哀哉的更新内容,我们来深入看一下。

此处信息泄露出现在httpd进程中,使用IDA载入httpd之后,可以在程序中找到路由表,如下图所示:

图片

图4-2 httpd进程路由表

上表中,每六行为一个结构体,以高亮的六行为例:其中第一行为访问的url;最后一行表示是否需要登陆,0代表不需要;倒数第二行为处理函数,其中do_ej是一个小型的页面解析器。

上图中的asp和htm的页面都是可以在未登陆状态下用get请求直接访问的。但逆向看代码之后,便可知do_ej在解析过程中也能处理post请求,而且能接收一个名为current_lang的参数。顾名思义,该参数可以用于控制页面的显示语言。可以在IDA中找到关于current_lang参数的处理逻辑,如下图所示:

图片

图4-3 current_lang参数处理逻辑

可以看到snprintf的最大长度为0x10字节,如果我们输入的长度超过0x10,那么原本的“%s.dict”就会被顶出去。例如,我们输入“/////etc/shadow”作为current_lang的值,如下图所示:

图片

图4-4 错误current_lang参数值

那么字符串在被格式化以后,将是下图中的样子:

图片

图4-4 错误地格式化字符串

在上图中,可以看到原本的“%s.dict”已经消失了。

如果继续执行该程序,那么/etc/shadow的内容将会通过http直接回显出来,如下图所示:

图片

图4-4 http回显shadow文件内容

华硕官方对这个漏洞的修复方案是限制a1参数的长度和内容,如下图所示:

图片

图4-5 华硕官方修补方案

5、最后一战

虽然华硕两次更新修复了很多问题,但最终还是没能阻止各位攻击者。最终的问题出现在cfg_server中,当多个华硕路由器通过AiMesh组网之后,会出现cfg_client和cfg_server之间的通信。类似httpd进程,可以在该程序中也找到多个路由表,其中一个是tcp7788端口的路由表,如下图所示:

图片

图5-1 cfg_server进程路由表

通过IDA逆向分析之后,可以推断出tcp7788端口的通信格式为TLV(Type-Length-Value)报文格式,其中,T即路由表中的编号;V是aes加密数据内容及其crc32值。看到这里,就能顺其自然地想到如果L为不合理的值会怎样,其实漏洞就是出现在这里了。

我们可以按照下图所示的方法构造恶意的发送数据:

图片

图5-2 恶意payload头部

上图中,我们选择第0x28号请求,将长度设置为0xFFFFFFF4,crc32值设置为0,由此绕过程序的crc32校验,见下图中R0和R3寄存器:

图片

图5-3 绕过crc32校验

然后,在AES解密过程中,会触发整数溢出,导致malloc错误的内存大小,如下图所示:

图片

图5-4 malloc前整数溢出

可以看到,上图中R11值为0xFFFFFFF4,而malloc长度仅仅为0x4。

接下来,由于声明的内存长度小于实际长度,就会造成堆溢出,导致AES解密数据写入后续溢出的堆内存中。接下来只要考虑怎么利用这个溢出写入,并不麻烦,如果后续内存中有个函数指针或者其他什么有用的数据可以被覆盖,我们就有了可乘之机。事实上,只要合理布局内存,就可以让后面出现一个可以利用的函数指针,而cfg_server并没有开启ASLR,所以利用过程并不复杂,我们可以这样操作:

各位,十分抱歉,这里容笔者先卖个官子,待固件完成更新修复之后,我们可以再回过头来详细讨论。不过,话说回来,都已经提示到这里了,相信各位读者只要自己分析一下也能解决这个漏洞利用

6、小结

本篇就先写到这里,希望耐心读到这里的各位有所收获。除了今年以外,华硕路由器还是去年天府杯的项目之一,其中漏洞也很有意思;此外,在去年8月极光无限还报了个华硕路由器未授权栈溢出漏洞,感兴趣的话可以去看看相关的信息。最后,很感谢对本文提供帮助的各位,有@Suzhang、@halo以及@tkmk等人,多谢。还有,本文中有很多结论和推测为我们个人的推测,如果不当指出,可以联系我们做更正。


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1751/



文章来源: http://paper.seebug.org/1751/
如有侵权请联系:admin#unsafe.sh