来自GRIMM的安全研究人员Adam Nichols和来自越南互联网服务提供商VNPT 的研究人员d4rkn3ss分析报告了一个影响Netgear路由器的严重的栈缓存溢出远程代码执行漏洞,漏洞CVSS 评分为8.8分,漏洞影响79种不同型号的Netgear路由器的758种固件版本,受影响的固件中最早的版本是2007年发布的。远程攻击者利用该漏洞可以以root权限执行代码,并接管设备。
影响路由器:
AC1450 D6220 D6300 D6400 D7000v2 D8500 DC112A DGN2200 DGN2200v4 DGN2200M DGND3700 EX3700 EX3800 EX3920 EX6000 EX6100 EX6120 EX6130 EX6150 EX6200 EX6920 EX7000 LG2200D MBM621 MBR624GU MBR1200 MBR1515 MBR1516 MBRN3000 MVBR1210 CR4500 R6200 R6200v2 R6250 R6300 R6300v2 R6400 R6400v2 R6700 R6700v3 R6900 R6900P R7000 R7000P R7100LG R7300 R7850 R7900 R8000 R8300 R8500 RS400 WGR614v8WG R614v9WG R614v10 WGT624v4 WN2500RP WN2500RPv2 WN3000RP WN3100RP WN3500RP WNCE3001 WNDR3300 WNDR3300v2 WNDR3400 WNDR3400v2 WNDR3400v3 WNDR3700v3 WNDR4000 WNDR4500 WNDR4500v2 WNR834Bv2 WNR1000v3 WNR2000v2 WNR3500 WNR3500v2 WNR3500L WNR3500Lv2 XR300
关键点:Netgear R7000,版本1.0.11.100_10.2.100及之前,未认证绕过获取到ROOT权限。
PoC代码参见:https://github.com/grimm-co/NotQuite0DayFriday/tree/master/2020.06.15-netgear
版本 V1.0.11.208_10.2.101(已经修复):http://support.netgear.cn/Upfilepath/R7000-V1.0.11.208_10.2.101.chk
版本 V1.0.11.100_10.2.100(存在漏洞):https://www.downloads.netgear.com/files/GDC/R7000/R7000-V1.0.11.100_10.2.100.zip
调试的程序:httpd
静态分析:IDA
获取文件系统:binwalk
程序调试工具:gdbserver、IDA
串口调试工具:Hyper Terminal软件、TTL转USB转接板
Netgear R7000路由器真机测试,可以在某宝上或者某鱼上购买,价格不贵(学到的知识是无价的)。
Netgear R7000路由器自身带有串口引脚,所以就没必要太过于费劲寻找串口引脚。如下图所示,是已经连接好的串口。
如下图是USB转TTL转接板,本人为什么先把这个工具插入到USB口,而不是USB转TTL转接板连接杜邦线(正常是提前连接杜邦线,USB转TTL转接板连接USB口,再打开Hyper Terminal,最后开启路由器,数据就会在Hyper Terminal显示),再去连接USB口,是有原因的,主要是因为,如果提前连接好杜邦线,再插入到USB口,那就获取不到信息(不信可以自行尝试,本人之前也遇到过类似的坑,脱坑后一直想着这个点)。
打开Hyper Terminal软件,调整好信息(Netgear R7000路由器使用默认信息即可,不用修改信息),点击确定。
开启路由器,等待几秒钟,再将杜邦线插入到TTL转USB转接板上(按着GND-GND、RXD-TXD、TXD-RXD的接法接),如下图所示。
此时就会在Hyper Terminal上打印信息。当打印启动完成后,获取到ROOT权限,便可以进行下一步的调试工作。
进入到路由器后,使用wget下载gdbserver程序进行调试(由于Netgear R7000是arm架构,所以需要下载arm架构的gdbserver)。
根据网上曝光的poc来看,漏洞点是在如下图的地址所示,只要能控制v9的大小,便可以溢出s的值。但是想触碰到漏洞点,必须要绕过 strcmp(src,"*#$^") ,而 src 必须是*#$^,否则无法绕过,src是我们可以控制的数据,所以绕过这个函数并不难。只要在 *#$^ 数据的后面放入00便可以轻松绕过。
想要到达漏洞点,还有两个点需要绕过,s1(全部的数据) 必须存在name="mtenFWUpload",而且name="mtenFWUpload"的数据之后需要存在 \r\n\r\n,所以在构造数据的时候必须是name="mtenFWUpload" ... \r\n\r\n。
可以看到R1寄存器(src的值)的值是我们控制的长度,而且这个长度是可以溢出到返回值地址处。
没有执行memcpy之前R0的值(s的值)是没有数据的,执行之后,就覆盖了构造好的数据。
运行到POP处,此时的SP的地址是0XBE911E54,就是已经被覆盖成了BBBB,由于ARM架构的特性,它会先将BBBB...IIII的数据存放到R4-R11的寄存器中,真正复制给PC的值是0X003D000,所以最终的返回值地址是0X003D000。
经过构造,程序会跳转到0X003D000地址处,将SP(此时的SP已经是0xBE911E78,所以是utelnetd -p 8888 -l /bin/sh的值)赋值给R0,并传给system函数执行命令,达到任意命令执行漏洞的效果。
图7.1(V1.0.11.208_10.2.101)是已经打过补丁的,限制了v9的长度,而图7.2(V1.0.11.100_10.2.100)并没有对v9的长度进行限制,才导致溢出漏洞。
图 7.1
图 7.2
这个漏洞原理相对来说比较简单,挺适合入门的大白
串口调试时要注意TTL转USB转接板接入。
构造的poc中必须有*#$^,而且后面必须跟00,否则无法绕过strcmp。
0X003D000是很好的执行点,不需要跳转到libc库中,相对来说利用还是比较简单的。
导致溢出的原因,没有限制用户数据的长度。
本文作者:知微攻防实验室
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/154697.html