身份验证绕过以及命令注入
Authentication Bypass
基本信息
披露信息:https://www.zerodayinitiative.com/advisories/ZDI-20-1451/
漏洞评分:8.8(High)
漏洞描述:NetGear 部分路由器存在登录验证绕过漏洞,攻击者可以利用此漏洞绕过正常的登录逻辑直接访问后台接口,可以结合其他漏洞实现任意代码执行。
漏洞分析
根据披露信息,去网件官网下载到存在漏洞的固件:https://www.netgear.com/support/
ZDI 披露信息指出漏洞影响多个型号的设备,我们以 AC2400 为例分析。
下载 1.2.0.74 和 1.2.0.76 两个版本固件,分析公开漏洞一个比较实用的方法就是进行版本比较,常用工具包括 Ghidra、Bindiff、diaphora 等。(PS:IDA 7.5 支持 MIPS 反编译啦,可以使用 Bindiff 6)
首先对固件解包,固件没有经过特殊处理,直接 binwalk 一下即可。解开得到一个 Linux 文件系统,按照披露信息找到 /usr/sbin/mini_httpd 二进制程序,加载到 IDA。
Shift+F12 搜索字符串,漏洞位于处理用户请求的位置,所以直接搜索 Content-Length 或者其他请求头中会出现的字符串,通过交叉引用可以定位到函数 0x40A540 (1.2.0.74),其中存在以下代码片段
1 | fprintf(v4, "[%s::%s():%d] ", "mini_httpd.c", "handle_request", 1634); |
可以猜测这个函数叫做 handle_request,主要用于处理 HTTP 请求。
摘录两个版本的代码如下
1 | // 1.2.0.74 |
1 | // 1.2.0.76 |
比较两份代码,主要逻辑变化不大,但是新版中添加了 SSO 相关逻辑,即单点登录,猜测官方通过引入单点登录的手段对漏洞进行修复。
通过分析代码,可以定位到处理 login 请求的函数是 0x407FC0 (1.2.0.74),关键片段如下
1 | char *__fastcall maybe_login(int a1) |
我们观察到 login 函数开头对一个名为 currentsetting_flag 的标志位进行判断,如果不等于 1,就执行正常的 login 逻辑,否则会跳过 login 逻辑。最后对访客的 IP 地址进行判断,如果访客来自于公网,会丢弃相关请求。
那如果某处代码能控制这个变量为 1,就能绕过 login 直接访问后台内容。
通过交叉引用,在 handle_login 函数中找到了为这个变量赋值的位置
1 | if ( path_exist(path, off_427E50, v14) |
第 8 行会将 currentsetting_flag 设为 1,从这里向前分析限制条件,要求我们发送的请求
1 | 1. 访问的 URL 位于 off_427E50 指向的列表中 |
如果满足上面所述的条件,就会进入到 if 中,分别设置两个全局变量:multi_login_flag、login_or_not,并且如果 URL 中还包含 currentsetting.htm,就把 currentsetting_flag 设置成 1。
此外,maybe_login 函数只在 handle_request 函数中调用了一次,handle_request 函数中还调用了另一个比较关键的函数 execute_cgi。
httpd 只充当处理请求的角色,在确定了访问哪些接口之后,它会调用相应的 cgi 程序,execute_cgi 函数就负责解析和调用这些 cgi 程序。
在这个函数中还存在一些登录逻辑,相关代码如下
1 | strlcpy(v101, dword_429734, 10000); |
判断了 login_or_not 变量,如果不等于 0 就执行 login,同上,当构造满足特定要求的请求时,login_or_not 会被设置成 0,也能绕过这个逻辑。
1 | if ( !login_or_not |
上面这段代码判断多个变量的状态,和前一个判断 login_or_not 相同,有趣的是当满足条件进入 if,会打印
1 | no need verify for no auth or soap or genie.cgi |
某些接口确实不需要权限验证就能访问,但是在实现这项功能时使用了 strstr 而不是精确匹配,导致出现绕过的问题。
用某公网设备测试,AC2400 存在一个可以开启 debug 模式的接口,链接
1 | /setup.cgi?todo=debug |
默认情况下访问这个接口会得到 401
构造一个满足条件的 URL
1 | /setup.cgi?todo=debug&x=currentsetting.htm |
再次访问
可以看到成功访问了该接口,但可能是防火墙的原因,没法儿连接到 telnet。
还有一些可用的链接
1 | # https://gist.github.com/Donearm/978555 |
注:对于不同型号的设备,能够绕过验证的功能不完全一致,某些可以用于 GET 请求,另一些可能只对 POST 请求有效。某些可能只对 htm 页面有效,其它只对 cgi 有效。
新版的修复手段静态来看似乎是添加了单点登录,由于没有设备暂时无法验证新版固件的登录逻辑。
此外,NetGear 存在某些历史漏洞,也是登录验证绕过,触发方法是在 URL 中添加空字节或者添加 1.jpg 等字符串,参考链接:
1 | https://github.com/zer0yu/CVE_Request/tree/master/netgear |
Command Injection
基本信息
披露信息:https://www.zerodayinitiative.com/advisories/ZDI-20-1423/
漏洞评分:6.8(Medium)
漏洞描述:NetGear 部分路由器存在命令注入漏洞,拥有后台权限的攻击者可以利用此漏洞实现任意命令执行。
漏洞分析
还是以 AC2400 为例,披露信息中提到命令注入发生的位置是 funjsq_access_token 参数,在解包目录中搜索包含这个字符串的文件
1 | grep -r "funjsq_access_token" |
可以找到名为 setup.cgi 的二进制程序,IDA 载入,找到字符串并交叉引用发现相关函数如下
1 | int __fastcall sub_407C80(int a1) |
setup.cgi 主要负责实现后台的一些功能,某功能会用到参数 funjsq_access_token,在上面这个函数中解析出来之后直接带入函数 COMMAND (参数长度必须大于等于 6)。
经过查找,COMMAND 函数是 /lib/libscmisc.so 链接库导出的,相关代码如下
1 | int COMMAND(const char *a1, ...) |
把传入的参数写入 cmd_agent,它也是一个二进制程序,位于 /usr/sbin 目录下。IDA 简单分析发现它会执行写入其中的命令,那么显然这里存在命令注入的问题。
新版本代码
1 | int __fastcall sub_411840(int a1) |
funjsq_access_token 参数主要是帆游加速器这个功能使用的,从新版代码来看,似乎是中国特供的功能,新版本中加入了对语言的判定,如果是中文才进行下一步操作。
另外引入了函数 test_command_inject 对参数过滤,代码如下
1 | int __fastcall test_command_inject(const char *a1) |
要求参数中不能存在 /bin、/sbin、字符 ‘`’、字符串 telneted (从解压出来的固件中并没有发现 telneted 这个程序,似乎是开发人员多打了一个 e ?)。
静态来看这个漏洞并没有完全修复,虽然不能使用字符 ‘`’,但是依然可以用其他手段绕过。
可以结合以上两个漏洞实现无需身份验证的任意命令执行,手头暂时没有合适的设备调试,感兴趣的同学可以自己尝试构造一下利用脚本。
Buffer Overflow
基本信息
披露信息:暂无
漏洞分析
首先声明,我不确定这个漏洞能否触发,目前暂时没办法测试。
问题出现在新版本固件中(1.2.0.76),用 IDA 进行分析,定位到函数 handle_request,从第 979 行开始代码如下
1 | if ( strstr(v109, "?signature=") ) |
如果传入的请求满足以下条件
1 | 1. URL 中包含 ?signature= |
程序会先用 strstr 定位 ?signature= 的位置,然后跳过这个字符串,接着用 sscanf 函数将后续内容拷贝到变量 v229。
在拷贝的过程中没有判断源字符串长度,可能会导致溢出。不过 IDA 自动识别目的缓冲区大小为 2500 字节,能否传入这么长的 URL 暂时无法确定。
- 本文作者: Catalpa
- 本文链接: https://wzt.ac.cn/2021/01/13/AC2400_vuln/
-
版权声明:
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。