CVE-2021-32030 & CVE-2021-20090
CVE-2021-32030
2021 年 5 月,来自 Atredis 的安全研究者披露了一个影响几乎所有 ASUS 路由器的身份验证绕过漏洞,利用该漏洞,未经授权的攻击者可以直接访问到后台管理接口,由于 ASUS 路由器在后台提供了开启 ssh 的功能,攻击者只需修改管理员密码并开启 ssh 即可获取 root shell。
漏洞分析
固件下载链接:https://dlcdnets.asus.com/pub/ASUS/wireless/RT-AX56U/FW_RT_AX56U_30043848253.zip
我们以 RT-AX56U 为例,使用 binwalk 对固件解包(解包之后有可能只会得到一个 100000.ubi 文件,可以使用 ubi_reader 继续解包)。解包后在 /usr/sbin/ 目录下找到一个叫做 httpd 的程序,此程序用于处理用户发送的 HTTP 请求。
我们用 IDA 分析程序,搜索 httpd_handle_request 字符串可找到处理请求的入口位置,另外,由于 ASUS 路由器采用了一些开源组件,根据 GPL 规则,ASUS 在(数个版本之前)其官网发布了路由器的源代码,并且衍生出梅林等优秀的官改版固件,我们可以在 github 上找到 merlin 固件项目,利用源代码辅助分析。
httpd_handle_request 函数逻辑简述如下:
首先对请求进行简单解析,利用 strncasecmp 等字符串操作函数从用户请求中匹配出一些结构,并将这些数据赋值到对应的变量。
1 | if ( !strncasecmp(v4, "Referer:", 8u) ) |
然后过滤 URL,防止出现路径穿越。
1 | if ( v28 == 47 |
之后根据用户访问的 URL 和 Method 执行不同逻辑,但所有需要身份验证的接口都要经过函数 auth_check(sub_5B560),此函数从 Cookie 中获取 asus_token 参数的值,然后带入 sub_59588 进行检查
1 | int __fastcall sub_59588(const char *a1) |
我们注意到函数先从配置文件中获取 ifttt_token 参数的值,然后将 asus_token 和它比较,如果两者相等,则输出
1 | IFTTT/ALEXA long token success. |
同时返回 1,表示身份验证通过。
但是在设备的默认配置下,IFTTT 功能没有开启,这导致 ifttt_token 默认值为空, 此时如果用户传入的 asus_token 也是空值,则 strcmp 会返回 0 表示比较成功,这样就能绕过后续的检查,实现身份验证绕过。
新版 auth_check 函数将代码修改为
1 | if ( *a1 && *nvram_safe_get_0("ifttt_token") && (v2 = nvram_safe_get_0("ifttt_token"), !strcmp(a1, v2)) ) |
首先判断 asus_token 是否为空,避免用户传入空值的情况出现,从而修复了此漏洞。
参考链接
https://www.atredis.com/blog/2021/4/30/asus-authentication-bypass
CVE-2021-20090
2021 年 4 月,Tenable 安全研究者披露了影响 Arcadyan 系列网络设备的一些漏洞,后续经确认,有多个厂商采用了 Arcadyan 开发的系统套件,从而遭受这些漏洞的影响。
漏洞分析
根据披露信息,Arcadyan 提供的组件被多个网络设备厂商使用,我们以 ASUS DSL-AC88U 为例进行分析。
固件版本:1.10.05_Build502,下载后 binwalk 即可解包。
关键文件:/usr/sbin/httpd
IDA 加载分析,首先可以定位到名为 process_request 的函数,传入参数为解析后的 http 请求结构体,此函数关键代码如下
1 | url_decode(&req->url); |
首先调用 url_decode 函数对 url 进行解码,然后调用 sub_DEB0 函数对 url 进行判断,关键代码如下
1 | int __fastcall sub_DEB0(const char *url) |
此函数从一个 allow_urls 列表中获取值,内容如下
1 | /images/ |
先获取 allow_urls 一项的长度,然后用 strncasecmp 函数和用户传入的 URL 比较,如果相等则返回 1,此时 req->is_url_valid 为 1。
之后回到 process_request 函数,判断 req->is_url_valid 的值,如果它等于 1,则不会执行 check_auth_0 函数,相当于当用户访问静态资源时,自动跳过身份验证。
随后判断 method,如果是 POST,则执行 process_post。
1 | void __fastcall process_post(struct_req *req) |
将 URL 传入 sub_DF50 函数,代码如下
1 | int __fastcall sub_DF50(const char *url) |
再将 URL 传入 sub_167A8,代码如下
1 | int __fastcall sub_167A8(int url) |
简单来讲,此函数会将形如 /aaa/../bbb 转换成 /bbb。
转换之后,回到 sub_DF50 函数,将 URL 和 maybe_post_handlers 列表中定义的 handler 比较,如果比较成功,就回到 process_post 用 exec_cgi_script 执行对应的 handler 函数。
于是我们可以构造如 /images/../apply_abstract.cgi 类似的请求,程序先匹配到 /images,绕过登录,然后替换 /../ 导致后续访问的是 /apply_abstract.cgi 接口,实现身份验证绕过。
参考链接
https://zh-cn.tenable.com/security/research/tra-2021-13?tns_redirect=true
总结
身份验证绕过是一类影响比较严重的漏洞,通过此类漏洞可允许攻击者访问到后台更多敏感接口,通过组合利用漏洞可实现对设备的完全控制,从我们复现过的漏洞来看,身份验证绕过基本有以下几类
- 设备的登录功能对于用户名/密码处理不恰当,攻击者可通过传入空值/硬编码值/可本地计算的值来通过验证流程。
- 设备的会话管理存在问题,攻击者通过控制 Cookie 值绕过会话检查。
- 设备对于用户访问的资源路径处理不恰当,攻击者通过路径穿越/插入特殊字符串等通过身份验证,但实际访问到敏感接口。
- 设备区分了 PC 和 app 请求,app 请求可能存在弱校验。
- 设备直接暴露了敏感接口,攻击者通过访问这些接口得到认证信息。
- 本文作者: CataLpa
- 本文链接: https://wzt.ac.cn/2021/08/13/bypass_auth2/
-
版权声明:
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。