Update: 2021-01-18: 修正 CVE-2020-8861 分析过程
在 IoT 漏洞中,身份验证漏洞出现频率较高,并且能够造成的危害很大,通过身份验证的绕过,攻击者可以访问到很多敏感 API,甚至可以结合其他漏洞直接获取设备 shell,给用户带来重大损失。
CVE-2020-8864
2020 年 2 月 24 日,ZDI 团队披露了存在于 D-Link 多个型号路由器中的身份验证绕过漏洞,通过利用漏洞,攻击者可从 LAN 侧轻易的控制路由器,实现修改 admin 用户密码、篡改路由器默认配置、甚至结合其他漏洞实现蠕虫植入等操作。
漏洞基本信息
以下是从披露页面摘抄的漏洞信息
1 | This vulnerability allows network-adjacent attackers to bypass authentication on affected installations of D-Link DIR-867, DIR-878, and DIR-882 routers. Authentication is not required to exploit this vulnerability. |
此漏洞影响 DIR-867, DIR-878, DIR-882 路由器,漏洞产生原因大概是在处理 HNAP 请求过程中,由于缺少了对空密码的验证流程,导致攻击者可以使用空密码绕过身份验证,从而访问敏感 API 接口。
漏洞类型:身份验证绕过
漏洞威胁:较高 (8.8)
漏洞影响:攻击者绕过身份验证,从而访问敏感 API,执行敏感操作。
漏洞分析
可以去 ftp://ftp2.dlink.com/PRODUCTS/DIR-882/REVA/ 下载固件,这里我使用的是 1.10B02 25MB 版本,其中包含了未加密的固件,可以直接拿过来进行解包。
解包之后简单看一下整个文件系统,web 服务器使用的是 lighttpd,通过查看其配置文件,发现大部分请求都会被转发到 prog.cgi 进行处理。
拿到 prog.cgi 放进 Ghidra 进行分析,根据漏洞信息,我们需要寻找处理 HNAP 登录请求的代码,先搜索字符串 Login 看一下有没有什么线索。
找到了几个包含 login 的字符串,其中第一项 /HNAP1/login 感觉和请求有关,通过查找交叉引用,找到了函数
1 | undefined4 FUN_0041ed9c(int param_1) |
交叉引用此函数找到了判断 login 请求的函数
1 | undefined4 FUN_004249ec(int param_1) |
通过取得 /Login/Action 字段来判断这个请求是登录还是登出。于是可以定位到登录请求函数 hnap_login。
1 | undefined4 hnap_login(undefined4 param_1) |
这个函数的代码比较多,我用 C 写了一个简化版
1 |
|
前两个字符串代表用户的请求,后两个代表正确的字符串,代码判断逻辑是要求用户名等于 admin,这没有什么问题,但是在判断密码的时候,首先会使用 strlen 计算用户输入的密码长度,然后带入 strncmp 函数和正确的密码进行比较,如果用户输入的密码为空,那么最终参与 strncmp 比较的 len 就是 0,此时函数会默认返回 0。
于是验证成功就存在了两种情况,一是密码真的正确,二是密码为空,大家可以自己编译上面的代码试一下。
修复手段呢?可以在 strlen 计算密码长度之后对长度进行判断,如果等于零就直接返回登录失败。
经过测试,DIR 878 等型号的路由器对于 HNAP login 请求的处理是相同的,漏洞的成因也是一样。
CVE-2020-8861
影响 DAP-1330 Wi-Fi 拓展器。
漏洞基本信息
摘抄漏洞描述如下:
1 | This vulnerability allows network-adjacent attackers to bypass authentication on affected installations of D-Link DAP-1330 Wi-Fi range extenders. Authentication is not required to exploit this vulnerability. |
漏洞出现在处理 HNAP 请求中,对于 cookie 的处理不恰当可以导致身份验证绕过,攻击者可以访问敏感 API ,篡改管理员账户密码。
漏洞分析
首先去 ftp://ftp2.dlink.com/PRODUCTS/DAP-1330/REVA/ 下载固件,注意需要下载 v1.01B04 版本固件,因为在最新版中漏洞已经修复。
根据漏洞描述找不到太多的信息,通过搜索 cookie 字符串,找到了可能是用于处理 login 请求的函数,该函数位于 libhnap.so 共享库中,函数名 check_login_addr,代码如下
1 | int check_login_addr(undefined4 param_1,char *param_2) |
参考另一篇分析文章: https://wzt.ac.cn/2021/01/17/DCS-960L/
本漏洞成因和 ZDI-CAN-11352 相同,添加注释的代码如下
1 | if ( v44[51] != 1 |
验证密码的时候会获取 cookie 中的某个字段,然后按照以下算法
1 | key = public key + cookie |
计算得到 login_password。静态分析来看,cookie 和 LoginPassword 参数都是用户从外部传递的,这样就能控制最后计算得到的 login_password 结果,可以构造特殊的登录请求来绕过登录。
新版本中代码片段如下
1 | if ( v43[51] != 1 |
hmac_md5 的 key 被设置成 &v46[25],观察 setLoginInfo 函数片段
1 | case 6: |
v46 + 100 转换成索引形式就是 v46[25],它被定义成 PrivateKey。再来看 getLoginInfo 片段
1 | if ( strcasecmp(v4 + v8 + 8, "PrivateKey") ) |
其中 V7 就是上述的 v46[25],很明显,用户信息中本来就默认保存了 private key 这个值,但是旧版本中要先调用 hmac_md5 计算得到 private key,而且计算过程中带入了攻击者可控的数据,这样会导致验证绕过。
新版本中取消了动态计算 private_key 的过程,直接从已经保存的用户信息中获取,并且在 check_login_addr 函数中检查了 getLoginInfo 的返回值。
CVE-2020-8862
2020年2月21日,ZDI 团队披露了在 Dlink DAP-2610 路由器中存在身份验证绕过漏洞,漏洞成因是在处理登录请求的时候对于 password 处理不恰当。
漏洞分析
此设备使用 php 实现 web 端相关逻辑,我们采用补丁对比的策略进行漏洞定位。
首先根据披露信息可以得知,漏洞出现在处理 password 的逻辑中,那么首先搜索 login 字符串,查找和登录有关的代码,这里我在 web 目录下找到了 login.php 和 __login.php,这两个文件似乎和登录逻辑相关。摘抄相关代码如下
1 |
|
上面是 __login.php 的代码,从注释和逻辑上大致分析一下可以确定这里就是用于验证登录信息的位置,再来看看修复过的代码:
1 |
|
实际上存在差别的代码只有一句:
1 | 旧版本: |
新版本中验证了变量 $password_d 是否为空,然后才与 $LOGIN_PASSWD 进行比较。
那么这些变量是从哪里来的呢?通过查看 login.php 代码可以确定 $LOGIN_PASSWD 变量是用户输入的密码,而 $password_d 从上面的代码来看是从文件 /var/proc/web/hmac_md5/$session_uid/password_md5 读取的。
通过搜索 password_md5 ,发现 httpd 文件中包含此字符串,关键函数是 FUN_00012bb8,代码如下:
1 | undefined4 FUN_00012bb8(int param_1) |
通过交叉引用发现调用此函数的位置是处理 http 请求的主函数,内容较多这里就不贴代码了,大概逻辑就是匹配 http 请求的各个字段然后采取不同的操作,从上面的代码中我们可以发现 password_md5 文件内容似乎是从用户请求中取得的,我猜测是用户点击登录按钮之后会通过 php 代码计算出某些必要的数据,然后传递给 httpd 解析并保存到对应的文件中,之后在 __login.php 中进行验证,这样来看,一旦用户手动清空 password_md5 对应字段的内容,那么将导致 $password_d 变量为空,验证密码的逻辑就变成了
1 |
|
这样就可以绕过正常的登录验证,顺利进入后台。
官方的修复手段就是先判断 $password_d 是否为空,然后才进行比较。
CVE-2020-15633
2020 年 7 月 20 日,ZDI 披露了 Dlink DIR 系列路由器的一个身份验证绕过漏洞,此漏洞影响多个不同的路由器设备,攻击者通过构造特殊的 HTTP 请求即可触发漏洞,绕过登录验证逻辑,直接访问敏感接口。
漏洞基本信息
以下是从披露页面摘抄的漏洞信息
1 | This vulnerability allows network-adjacent attackers to bypass authentication on affected installations of D-Link DIR-867, DIR-878, and DIR-882 routers. Authentication is not required to exploit this vulnerability. |
此漏洞影响 DIR-867, DIR-878, DIR-882 路由器,漏洞产生原因大概是在处理 HNAP 请求过程中,验证用户登录的逻辑存在问题,导致攻击者可以构造特殊的 HTTP 请求绕过身份验证,从而访问敏感 API 接口。
漏洞类型:身份验证绕过
漏洞威胁:较高 (8.8)
漏洞影响:攻击者绕过身份验证,从而访问敏感 API,执行敏感操作。
漏洞分析
以 DIR-878 路由器为例,固件下载地址:ftp://ftp2.dlink.com/PRODUCTS/DIR-878/REVA/
请下载 1.20B05 版本,此漏洞在最新版中已经修复。
DIR 878 路由器的固件经过加密,binwalk 无法直接解包,解包手段可以参考 https://wzt.ac.cn/2019/09/18/D-Link_BUG/
解包之后找到关键文件 prog.cgi,此文件负责解析和处理 HTTP 请求。将它加载到 Ghidra 中即可开始分析。
根据披露信息,触发此漏洞的手段是在正常的 HNAP 请求后面添加 ‘?GetCAPTCHAsetting’,添加之后将数据包发送给路由器即可绕过身份验证从而访问任意的 API 接口。于是利用字符串搜索功能在目标文件中查找字符串 GetCAPTCHAsetting,得到几条交叉引用信息,其中位于 004d01a0 位置的字符串是我们重点关注的对象。
双击来到目标地址,发现如下信息:
1 | PTR_DAT_004d0194 XREF[3]: FUN_0041d81c:0041d928 (R) , |
类似于许多字符串的集合,并且两两之间偏移量都是 0x20。猜测此处是某种字符串列表,通过 PTR_DAT_004d0194 加上偏移量进行索引。
我们还可以使用 IDA 进行进一步的验证,将 prog.cgi 加载到 IDA 中,跳转到目标地址得到以下信息:
1 | .data:004D01A0 aGetcaptchasett:.ascii "GetCAPTCHAsetting"<0> |
IDA 对这部分数据识别的更加准确,正如我们的猜测,这里是一个字符串列表。
通过对列表首部地址的交叉引用,能找到使用这部分数据的代码,其中最关键的函数是 00423ecc,反编译结果如下:
1 | undefined4 allow_urls(int param_1) |
这个函数接收的参数是 webs_t 结构体,用于代表一个 web 请求。可以通过不断的交叉引用找到源函数 websSecurityHandler,gohead 中同名函数描述如下:
1 | websSecurityHandler implements the default security policy. It operates as a URL handler and is installed to run as the very first URL handler. If you require a replacement security policy, delete the websSecurityHandler and install your own with websUrlHandlerDefine. |
简单分析上面提到的函数逻辑,发现他会取出 webs_t 中下标为 0xe4 的数据并判断字符串列表中的数据是否出现在其中。通过分析 main 函数可以确定,0xe4 位置存放的是 Request_URI 指针,表示用户访问的 URL 链接。
如果字符串列表中的数据出现在 Request_URI 中,则允许访问。进一步分析发现这些硬编码的接口默认都是不需要身份验证就能访问的。例如 Login.html 是登录接口,EULA.html 是用户隐私协议等。
此函数的问题在于,它使用了 strstr 函数对用户输入的数据进行判断,如果用户访问一个本来需要身份验证的链接,然后在链接的后面添加这些字符串即可绕过身份验证逻辑。
漏洞测试:
首先抓包获取一个需要身份验证的 HTTP 请求:
1 | POST /HNAP1/ HTTP/1.1 |
这个请求发送到路由器可以返回正常的结果。然后构造一个非法的请求,在访问链接中添加 ‘?Login.html’:
可以看到构造的恶意 payload 能够绕过身份验证直接访问敏感接口。
此外我们可以结合这个身份验证漏洞以及命令注入漏洞实现无条件的 RCE。
1 | import requests |
- 本文作者: CataLpa
- 本文链接: https://wzt.ac.cn/2020/08/28/bypass_auth/
-
版权声明:
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。