@@ -228,93 +228,95 @@ def columnExists(columnFile, regex=None):
228228 columns .extend (_addPageTextWords ())
229229 columns = filterListValue (columns , regex )
230230
231- table = safeSQLIdentificatorNaming (conf .tbl , True )
231+ for table in conf .tbl .split (',' ):
232+ table = safeSQLIdentificatorNaming (table , True )
232233
233- if conf .db and METADB_SUFFIX not in conf .db and Backend .getIdentifiedDbms () not in (DBMS .SQLITE , DBMS .ACCESS , DBMS .FIREBIRD ):
234- table = "%s.%s" % (safeSQLIdentificatorNaming (conf .db ), table )
234+ if conf .db and METADB_SUFFIX not in conf .db and Backend .getIdentifiedDbms () not in (DBMS .SQLITE , DBMS .ACCESS , DBMS .FIREBIRD ):
235+ table = "%s.%s" % (safeSQLIdentificatorNaming (conf .db ), table )
235236
236- kb .threadContinue = True
237- kb .bruteMode = True
238-
239- threadData = getCurrentThreadData ()
240- threadData .shared .count = 0
241- threadData .shared .limit = len (columns )
242- threadData .shared .files = []
237+ kb .threadContinue = True
238+ kb .bruteMode = True
243239
244- def columnExistsThread ():
245240 threadData = getCurrentThreadData ()
241+ threadData .shared .count = 0
242+ threadData .shared .limit = len (columns )
243+ threadData .shared .files = []
246244
247- while kb .threadContinue :
248- kb .locks .count .acquire ()
249- if threadData .shared .count < threadData .shared .limit :
250- column = safeSQLIdentificatorNaming (columns [threadData .shared .count ])
251- threadData .shared .count += 1
252- kb .locks .count .release ()
253- else :
254- kb .locks .count .release ()
255- break
245+ def columnExistsThread ():
246+ threadData = getCurrentThreadData ()
256247
257- if Backend .isDbms (DBMS .MCKOI ):
258- result = inject .checkBooleanExpression (safeStringFormat ("0<(SELECT COUNT(%s) FROM %s)" , (column , table )))
259- else :
260- result = inject .checkBooleanExpression (safeStringFormat (BRUTE_COLUMN_EXISTS_TEMPLATE , (column , table )))
248+ while kb .threadContinue :
249+ kb .locks .count .acquire ()
261250
262- kb .locks .io .acquire ()
251+ if threadData .shared .count < threadData .shared .limit :
252+ column = safeSQLIdentificatorNaming (columns [threadData .shared .count ])
253+ threadData .shared .count += 1
254+ kb .locks .count .release ()
255+ else :
256+ kb .locks .count .release ()
257+ break
263258
264- if result :
265- threadData .shared .files .append (column )
259+ if Backend .isDbms (DBMS .MCKOI ):
260+ result = inject .checkBooleanExpression (safeStringFormat ("0<(SELECT COUNT(%s) FROM %s)" , (column , table )))
261+ else :
262+ result = inject .checkBooleanExpression (safeStringFormat (BRUTE_COLUMN_EXISTS_TEMPLATE , (column , table )))
266263
267- if conf .verbose in (1 , 2 ) and not conf .api :
268- clearConsoleLine (True )
269- infoMsg = "[%s] [INFO] retrieved: %s\n " % (time .strftime ("%X" ), unsafeSQLIdentificatorNaming (column ))
270- dataToStdout (infoMsg , True )
264+ kb .locks .io .acquire ()
271265
272- if conf .verbose in (1 , 2 ):
273- status = "%d/%d items (%d%%)" % (threadData .shared .count , threadData .shared .limit , round (100.0 * threadData .shared .count / threadData .shared .limit ))
274- dataToStdout ("\r [%s] [INFO] tried %s" % (time .strftime ("%X" ), status ), True )
266+ if result :
267+ threadData .shared .files .append (column )
275268
276- kb .locks .io .release ()
269+ if conf .verbose in (1 , 2 ) and not conf .api :
270+ clearConsoleLine (True )
271+ infoMsg = "[%s] [INFO] retrieved: %s\n " % (time .strftime ("%X" ), unsafeSQLIdentificatorNaming (column ))
272+ dataToStdout (infoMsg , True )
277273
278- try :
279- runThreads (conf .threads , columnExistsThread , threadChoice = True )
280- except KeyboardInterrupt :
281- warnMsg = "user aborted during column existence "
282- warnMsg += "check. sqlmap will display partial output"
283- logger .warning (warnMsg )
284- finally :
285- kb .bruteMode = False
274+ if conf .verbose in (1 , 2 ):
275+ status = "%d/%d items (%d%%)" % (threadData .shared .count , threadData .shared .limit , round (100.0 * threadData .shared .count / threadData .shared .limit ))
276+ dataToStdout ("\r [%s] [INFO] tried %s" % (time .strftime ("%X" ), status ), True )
286277
287- clearConsoleLine (True )
288- dataToStdout ("\n " )
278+ kb .locks .io .release ()
289279
290- if not threadData .shared .files :
291- warnMsg = "no column(s) found"
292- logger .warning (warnMsg )
293- else :
294- columns = {}
295-
296- for column in threadData .shared .files :
297- if Backend .getIdentifiedDbms () in (DBMS .MYSQL ,):
298- result = not inject .checkBooleanExpression ("%s" % safeStringFormat ("EXISTS(SELECT %s FROM %s WHERE %s REGEXP '[^0-9]')" , (column , table , column )))
299- elif Backend .getIdentifiedDbms () in (DBMS .SQLITE ,):
300- result = inject .checkBooleanExpression ("%s" % safeStringFormat ("EXISTS(SELECT %s FROM %s WHERE %s NOT GLOB '*[^0-9]*')" , (column , table , column )))
301- elif Backend .getIdentifiedDbms () in (DBMS .MCKOI ,):
302- result = inject .checkBooleanExpression ("%s" % safeStringFormat ("0=(SELECT MAX(%s)-MAX(%s) FROM %s)" , (column , column , table )))
303- else :
304- result = inject .checkBooleanExpression ("%s" % safeStringFormat ("EXISTS(SELECT %s FROM %s WHERE ROUND(%s)=ROUND(%s))" , (column , table , column , column )))
280+ try :
281+ runThreads (conf .threads , columnExistsThread , threadChoice = True )
282+ except KeyboardInterrupt :
283+ warnMsg = "user aborted during column existence "
284+ warnMsg += "check. sqlmap will display partial output"
285+ logger .warning (warnMsg )
286+ finally :
287+ kb .bruteMode = False
305288
306- if result :
307- columns [column ] = "numeric"
308- else :
309- columns [column ] = "non-numeric"
289+ clearConsoleLine (True )
290+ dataToStdout ("\n " )
291+
292+ if not threadData .shared .files :
293+ warnMsg = "no column(s) found"
294+ logger .warning (warnMsg )
295+ else :
296+ columns = {}
297+
298+ for column in threadData .shared .files :
299+ if Backend .getIdentifiedDbms () in (DBMS .MYSQL ,):
300+ result = not inject .checkBooleanExpression ("%s" % safeStringFormat ("EXISTS(SELECT %s FROM %s WHERE %s REGEXP '[^0-9]')" , (column , table , column )))
301+ elif Backend .getIdentifiedDbms () in (DBMS .SQLITE ,):
302+ result = inject .checkBooleanExpression ("%s" % safeStringFormat ("EXISTS(SELECT %s FROM %s WHERE %s NOT GLOB '*[^0-9]*')" , (column , table , column )))
303+ elif Backend .getIdentifiedDbms () in (DBMS .MCKOI ,):
304+ result = inject .checkBooleanExpression ("%s" % safeStringFormat ("0=(SELECT MAX(%s)-MAX(%s) FROM %s)" , (column , column , table )))
305+ else :
306+ result = inject .checkBooleanExpression ("%s" % safeStringFormat ("EXISTS(SELECT %s FROM %s WHERE ROUND(%s)=ROUND(%s))" , (column , table , column , column )))
307+
308+ if result :
309+ columns [column ] = "numeric"
310+ else :
311+ columns [column ] = "non-numeric"
310312
311- kb .data .cachedColumns [conf .db ] = {conf . tbl : columns }
313+ kb .data .cachedColumns [conf .db ] = {table : columns }
312314
313- for _ in ((conf .db , conf . tbl , item [0 ], item [1 ]) for item in columns .items ()):
314- if _ not in kb .brute .columns :
315- kb .brute .columns .append (_ )
315+ for _ in ((conf .db , table , item [0 ], item [1 ]) for item in columns .items ()):
316+ if _ not in kb .brute .columns :
317+ kb .brute .columns .append (_ )
316318
317- hashDBWrite (HASHDB_KEYS .KB_BRUTE_COLUMNS , kb .brute .columns , True )
319+ hashDBWrite (HASHDB_KEYS .KB_BRUTE_COLUMNS , kb .brute .columns , True )
318320
319321 return kb .data .cachedColumns
320322
0 commit comments