引言
在我们上一次的公司团建中,Doyensec团队乘坐邮轮游览地中海沿岸。虽然每个停靠点都很精彩,但作为极客,我们需要用必要的黑客活动来打破日常泳池派对的单调。我们的负责人Luca和John准备了三个挑战,让我们绞尽脑汁寻找解决方案。每个挑战的目标都是分析一个没有已知漏洞利用的真实漏洞,并尝试自己制作漏洞利用。这些漏洞分为三类:物联网、Web和二进制利用;我们都选择了自己想要处理的类别,分成团队开始工作。
这个团体活动的名称是"!exploitable"。对于那些不知道这是什么的人(我之前也不知道),它指的是微软为WinDbg调试器制作的一个扩展。使用!exploitable命令,调试器会分析程序的状态,告诉你存在什么类型的漏洞以及它是否看起来可利用。
漏洞分析
我们被分配调查的漏洞是Tenda AC15路由器固件中的缓冲区溢出,即CVE-2024-2850。咨询中还链接到一个GitHub上的markdown文件,其中包含更多细节和一个简单的概念验证。虽然仓库已被删除,但Wayback Machine存档了该页面。
GitHub文档将该漏洞描述为基于堆栈的缓冲区溢出,并说明可以通过路由器控制面板API的/goform/saveParentControlInfo端点的urls参数触发。然而,我们立即注意到咨询中存在一些不一致之处。首先,附加的截图清楚地显示urls参数的内容被复制到使用malloc分配的缓冲区(v18)中,因此溢出应该发生在堆上,而不是堆栈上。
该页面还包括一个非常简单的概念验证,旨在通过发送带有大负载的请求来使应用程序崩溃。然而,我们在这里发现了另一个不一致之处,因为PoC中使用的参数简称为u,而不是咨询文本中描述的urls。
环境搭建
第一步是建立一个运行易受攻击固件的工作环境。通常,你需要获取固件,提取二进制文件,并使用QEMU进行模拟。但我们在船上,网络连接非常不稳定,没有StackOverflow我们无法完成所有工作。
幸运的是,有一个名为EMUX的惊人项目,专为漏洞利用练习而构建,正是我们所需要的。简而言之,EMUX在Docker容器中运行QEMU。令人惊叹的部分是它已经包含了许多易受攻击的ARM和MIPS固件(包括Tenda AC15);它还负责网络、修补特定硬件检查的二进制文件,并且预装了许多工具(如带有GEF的GDB),这非常方便。
漏洞调查
二进制分析
我们启动了Ghidra,花了一些时间理解代码,同时修复变量和函数的名称和类型,希望能更好地了解函数的功能。幸运的是,我们做到了,以下是函数功能的概述:
- 分配所有堆栈变量和缓冲区
- 将body参数读入单独的堆分配缓冲区
- 保存设备名称和MAC地址
- 将time参数拆分为time_to和time_from
- 为解析和存储家长控制规则在堆中分配一些缓冲区
- 解析其他body字段——主要是调用strcpy和atoi——并将结果存储在一个大的堆缓冲区中
- 执行一些健全性检查(例如,规则已存在,达到最大规则数)并保存规则
- 发送HTTP响应
- 返回
漏洞利用策略
利用策略是实现一个简单的ROP链来调用system()并执行shell命令。ROP代表面向返回的编程,包括在堆栈中写入一堆返回指针和数据,使程序跳转到内存中的某个位置,并从其他函数借用小的指令片段(称为gadget)运行,然后到达新的返回指令并再次跳转到其他地方,重复该模式直到链完成。
我们使用ropper寻找类似于pop {r0}; pop {pc}的gadget,但在其地址中没有空字节的情况下不容易找到合适的。幸运的是,我们实际上在libc.so内部找到了一个很好的pop {r0, pc}指令,一举两得。
完整利用
|
|
利用程序完美运行,并向系统添加了一个新的"backdoor"用户。然后我们可以简单地通过Telnet连接获得完整的root shell。
结论
活动结束后,我们进行了一些调查,发现我们最终利用的特定漏洞已知为CVE-2020-13393。据我们所知,我们的PoC是该特定端点的第一个有效利用。然而,由于该平台已有大量其他利用程序,其实用性有所降低。
尽管如此,这个挑战是一次很好的学习经历。我们得以更深入地研究ARM架构,并提高了我们的漏洞开发技能。在没有可靠网络的情况下一起工作,也使我们能够分享知识并从不同的角度解决问题。