简介:
文章首发于云众可信:https://www.sec-in.com/article/953
译文声明
本文是翻译文章,文章原作者Vincent Lee,文章来源:https://www.thezdi.com
译文仅供参考,具体内容表达以及含义以原文为准
引言
去年,我们披露了两个影响多种NETGERA产品的身份验证绕过漏洞ZDI-20-1176(ZDI-CAN-10754)和ZDI-20-1451(ZDI-CAN-11355)。这两个漏洞分别由一位匿名研究人员和名为1sd3d(Viettel网络安全)的研究人员发现,同时,这两个漏洞都位于mini_httpd Web服务器中。虽然这两个漏洞有着相似的产生原因,并且产生漏洞的位置非常接近,但是,两位研究人员是在两组不同的路由器中发现的该漏洞,并且两位研究人员对漏洞的利用方式各有不同。对比这些研究人员如何处理相同的问题,并推测他们如何通过不同的途径实现可行的利用的最终目标是一件很有趣的事情。
漏洞概述
由于GNU通用公共许可证(GPL)的要求,NETGEAR已发布了其固件的源代码。通过分析NETGEAR提供的固件的GPL版本,可以用最直接的方式理解这两个漏洞。在此博客文章中,我们将分析NETGEAR R6120路由器的GPL固件版本1.0.0.72。如果您也想尝试,可以从供应商的网站上找到固件。
根据固件源代码,我们可以知道Web服务器是基于mini_httpd开源项目的1.24版本的。该漏洞位于NETGEAR附加的代码中,因此不会影响上游开源的Web服务器。
该main()
函数位于mini_http.c中。该函数负责设置Berkeley风格的套接字,SSL和循环监听。为了处理并发的HTTP请求,当接收到TCP连接时,Web服务器会分叉自身,以在子进程中单独处理每个连接。这是main()
来自NETGEAR的GPL固件源代码中mini_http的编辑功能:
1 | 558 int main(int argc, char \*\*argv) |
接下来,handle_request()
从第1502行开始的函数将接管并处理分支之后的所有HTTP处理。
1 | 1499 /\* This runs in a child process, and exits when done, so cleanup is |
该函数首先初始化一些变量,然后使用辅助函数get_request_line()从第1608行的套接字中读取HTTP请求的请求行。然后handle_request()
函数继续使用strpbrk()
来将HTTP请求方法与请求行分开。请求行的其余部分存储在第1611行的名为path的变量中,该函数继续处理请求路径和请求。
从第2106行开始,事情变得很有趣,多条件if语句首先检查path
路径是否与数组no_check_passwd_paths
中的字符串之一匹配。这是在第409行使用path_exists()
定义的(在sc_util.c
中定义)。if语句还会检查path
变量是否包含子字符串“ PNPX_GetShareFolderList”。如果满足两个条件中的任何一个,那么need_auth
变量将设置为0,该need_auth
变量将完全执行其通告。设置为0时,将跳过身份验证。以下代码段显示了如何定义字符串的no_check_passwd_paths
数组:
1 | 406 /\* Ron \*/ |
精明的读者现在应该已经发现了该漏洞。从main()
到handle_request()
,该程序从未处理过存在属于请求行的请求参数的情况。如果攻击者发送的HTTP请求的请求参数包含no_check_passwd_paths
数组中的任何字符串,则攻击者可以满足在第2106行中定义的if条件并绕过身份验证。
PoC和开发
匿名研究人员提供了一个简单的PoC来演示此漏洞(ZDI-20-1176):
1 | http://<router ip>/passwordrecovered.htm&next\_file=update\_setting.htm |
view rawNETGEAR-R6120-1.0.0.72-snippet-4.console hosted with ❤ by GitHub
此PoC允许攻击者无需身份验证即可查看身份验证后的页面passwordrecovered.htm
。可以通过在浏览器中导航到以上路径来测试此PoC。
最后,研究人员提供了一个附加的PoC,允许攻击者查看路由器的管理员密码,以完全控制报告中的设备。
对于ZDI-20-1451,研究人员(1sd3d)注意到该程序实际上尚未解析出该path
变量中的HTTP版本,如果只是将它们简单地附加到请求中HTTP版本的末尾,strstr()
则将与“ PNPX_GetShareFolderList”匹配并满足在第2110行中定义的if条件以绕过身份验证。
1 | GET /passwordrecovered.htm HTTP/1.1PNPX\_GetShareFolderList\\r\\n |
view rawNETGEAR-R6120-1.0.0.72-snippet-5.console hosted with ❤ by GitHub
然后1sd3d使用了绕过身份验证的命令注入ZDI-20-1423(ZDI-CAN-11653)链接此漏洞,以完全控制设备。
白盒与黑盒
匿名研究人员的报告从白盒代码审核方处理了该漏洞,而1sd3d的报告从黑盒使用Ghidra及其反编译器进行了逆向工程处理。考虑到这一点,我们可以推测到为什么他们使用不同的方法利用了这些漏洞,并在不同的路由器集中发现了这些漏洞。
ZDI-20-1451的易受攻击的代码包含在#ifdef PNPX
预处理程序指令中。当从白盒侧访问时,很难判断PNPX
指令是否在编译时定义。易受攻击的代码可能没有编译到最终固件中。实际上,此代码的确没有编译到NETGEAR R6120无线路由器的固件中。
因此,编写脚本来查找ZDI-20-1176的易受攻击的源代码模式是使用GPL源代码时查找可利用固件的更可靠方法。自然,匿名研究人员选择利用未包装在任何预处理程序指令中的no_check_passwd_paths
数组来继续开发。
从黑匣子RE端接近时,您所看到的就是CPU所看到的。但是,goto语句,摩根定律(de Morgan’s Law)以及缺少变量名通常会掩盖反编译代码中的漏洞逻辑。使用研究人员的反编译代码检查时,ZDI-20-1451在这两个漏洞中更为明显。
提交者报告中显示了Ghidra中NETGEAR R7450固件的反编译代码视图。
相当独特的“PNPX_GetShareFolderList”字符串使跨不同设备的固件搜索相同漏洞变得更加容易。通过strings
运行二进制文件并搜索字符串应具有足够好的准确性。编写脚本以在反汇编程序中搜索ZDI-20-1176肯定需要一些脚本向导。
结论
每种方法都有其优势和盲点。在这种特定情况下,他们俩都到达了相同的目的,但在利用时却采取了不同的方法。这证明了没有一种方法是完美的。但是,可能只有一种方法可以使您在下一个Bug搜索旅程中走得更远。就是说,精通这两个方面从长远来看是有益的。
在瞬息万变的突发事件和按时交货的产品开发世界中,NETGEAR开发人员应该在此缺陷发布之前在代码审查方面做得更好。除了need_auth
变量之外,在代码的后半部分声明no_need_check_password_page
局部变量也不会使人们对代码充满信心。幸运的是,在新产品和固件中,NETGEAR似乎正在摆脱这种技术负担沉重的代码库。
脚注
我们通常可以从漏洞报告中推断出研究方法。但有一个重要的警告是,为了清晰起见,研究人员可能已决定从提交的内容中省略其黑盒或白盒的工作,并在博客中进行整个比较。如果真是这样,那么至少您已经学到了有关两个路由器错误的知识。
您可以在Twitter @TrendyTofu上找到我,并关注该团队以获取最新的利用技术和安全补丁。
发布时间: 2021-03-16
最后更新: 2023-07-21
本文标题: 无线路由器中白盒和黑盒漏洞搜寻之间的战斗
本文链接: https://foxcookie.github.io/2021/03/16/无线路由器中白盒和黑盒漏洞搜寻之间的战斗/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!