2013-02-14 15:32:17 +04:00
#!/usr/bin/env python
2012-07-20 22:17:35 +04:00
"""
2013-01-18 18:07:51 +04:00
Copyright ( c ) 2006 - 2013 sqlmap developers ( http : / / sqlmap . org / )
2012-07-20 22:17:35 +04:00
See the file ' doc/COPYING ' for copying permission
"""
from lib . core . agent import agent
2012-10-25 11:56:36 +04:00
from lib . core . common import arrayizeValue
2012-07-20 22:17:35 +04:00
from lib . core . common import Backend
from lib . core . common import filterPairValues
from lib . core . common import getLimitRange
2013-01-22 14:16:18 +04:00
from lib . core . common import isInferenceAvailable
2012-07-20 22:17:35 +04:00
from lib . core . common import isNoneValue
from lib . core . common import isNumPosStrValue
from lib . core . common import isTechniqueAvailable
from lib . core . common import readInput
from lib . core . common import safeSQLIdentificatorNaming
2013-01-30 21:08:34 +04:00
from lib . core . common import safeStringFormat
2012-12-21 13:15:42 +04:00
from lib . core . common import unArrayizeValue
2012-07-20 22:17:35 +04:00
from lib . core . common import unsafeSQLIdentificatorNaming
from lib . core . data import conf
from lib . core . data import kb
from lib . core . data import logger
from lib . core . data import paths
from lib . core . data import queries
from lib . core . enums import CHARSET_TYPE
from lib . core . enums import DBMS
from lib . core . enums import EXPECTED
from lib . core . enums import PAYLOAD
2012-12-06 17:14:19 +04:00
from lib . core . exception import SqlmapMissingMandatoryOptionException
from lib . core . exception import SqlmapUserQuitException
2012-07-20 22:17:35 +04:00
from lib . core . settings import CURRENT_DB
2013-01-19 03:04:01 +04:00
from lib . core . settings import METADB_SUFFIX
2012-07-20 22:17:35 +04:00
from lib . request import inject
from lib . techniques . brute . use import columnExists
from lib . techniques . brute . use import tableExists
class Search :
"""
This class defines search functionalities for plugins .
"""
def __init__ ( self ) :
pass
def searchDb ( self ) :
foundDbs = [ ]
rootQuery = queries [ Backend . getIdentifiedDbms ( ) ] . search_db
dbList = conf . db . split ( " , " )
if Backend . isDbms ( DBMS . MYSQL ) and not kb . data . has_information_schema :
dbCond = rootQuery . inband . condition2
else :
dbCond = rootQuery . inband . condition
dbConsider , dbCondParam = self . likeOrExact ( " database " )
for db in dbList :
2013-01-23 17:00:58 +04:00
values = [ ]
2012-07-20 22:17:35 +04:00
db = safeSQLIdentificatorNaming ( db )
if Backend . getIdentifiedDbms ( ) in ( DBMS . ORACLE , DBMS . DB2 ) :
db = db . upper ( )
infoMsg = " searching database "
if dbConsider == " 1 " :
infoMsg + = " s like "
infoMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( db )
logger . info ( infoMsg )
if conf . excludeSysDbs :
exclDbsQuery = " " . join ( " AND ' %s ' != %s " % ( unsafeSQLIdentificatorNaming ( db ) , dbCond ) for db in self . excludeDbsList )
infoMsg = " skipping system database %s ' %s ' " % ( " s " if len ( self . excludeDbsList ) > 1 else " " , " , " . join ( db for db in self . excludeDbsList ) )
logger . info ( infoMsg )
else :
exclDbsQuery = " "
dbQuery = " %s %s " % ( dbCond , dbCondParam )
dbQuery = dbQuery % unsafeSQLIdentificatorNaming ( db )
2012-12-05 13:45:17 +04:00
if any ( isTechniqueAvailable ( _ ) for _ in ( PAYLOAD . TECHNIQUE . UNION , PAYLOAD . TECHNIQUE . ERROR , PAYLOAD . TECHNIQUE . QUERY ) ) or conf . direct :
2012-07-20 22:17:35 +04:00
if Backend . isDbms ( DBMS . MYSQL ) and not kb . data . has_information_schema :
query = rootQuery . inband . query2
else :
query = rootQuery . inband . query
2013-01-23 17:22:35 +04:00
query = query % ( dbQuery + exclDbsQuery )
2012-10-28 01:16:25 +04:00
values = inject . getValue ( query , blind = False , time = False )
2012-07-20 22:17:35 +04:00
if not isNoneValue ( values ) :
2012-10-25 11:56:36 +04:00
values = arrayizeValue ( values )
2012-07-20 22:17:35 +04:00
for value in values :
value = safeSQLIdentificatorNaming ( value )
foundDbs . append ( value )
2013-01-22 14:14:35 +04:00
2013-01-23 17:00:58 +04:00
if not values and isInferenceAvailable ( ) and not conf . direct :
2013-01-15 21:14:58 +04:00
infoMsg = " fetching number of database "
2012-07-20 22:17:35 +04:00
if dbConsider == " 1 " :
infoMsg + = " s like "
infoMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( db )
logger . info ( infoMsg )
if Backend . isDbms ( DBMS . MYSQL ) and not kb . data . has_information_schema :
query = rootQuery . blind . count2
else :
query = rootQuery . blind . count
2012-10-25 11:56:36 +04:00
2013-01-23 17:22:35 +04:00
query = query % ( dbQuery + exclDbsQuery )
2012-10-28 02:36:09 +04:00
count = inject . getValue ( query , union = False , error = False , expected = EXPECTED . INT , charsetType = CHARSET_TYPE . DIGITS )
2012-07-20 22:17:35 +04:00
if not isNumPosStrValue ( count ) :
warnMsg = " no database "
if dbConsider == " 1 " :
warnMsg + = " s like "
warnMsg + = " ' %s ' found " % unsafeSQLIdentificatorNaming ( db )
logger . warn ( warnMsg )
continue
indexRange = getLimitRange ( count )
for index in indexRange :
if Backend . isDbms ( DBMS . MYSQL ) and not kb . data . has_information_schema :
query = rootQuery . blind . query2
else :
query = rootQuery . blind . query
2013-01-23 17:22:35 +04:00
query = query % ( dbQuery + exclDbsQuery )
2012-07-20 22:17:35 +04:00
query = agent . limitQuery ( index , query , dbCond )
2012-12-21 13:15:42 +04:00
value = unArrayizeValue ( inject . getValue ( query , union = False , error = False ) )
2012-07-20 22:17:35 +04:00
value = safeSQLIdentificatorNaming ( value )
foundDbs . append ( value )
2012-07-21 01:29:30 +04:00
conf . dumper . lister ( " found databases " , foundDbs )
2012-07-20 22:17:35 +04:00
def searchTable ( self ) :
bruteForce = False
if Backend . isDbms ( DBMS . MYSQL ) and not kb . data . has_information_schema :
errMsg = " information_schema not available, "
errMsg + = " back-end DBMS is MySQL < 5.0 "
bruteForce = True
if bruteForce :
message = " do you want to use common table existence check? %s " % ( " [Y/n/q] " if Backend . getIdentifiedDbms ( ) in ( DBMS . ACCESS , ) else " [y/N/q] " )
test = readInput ( message , default = " Y " if " Y " in message else " N " )
if test [ 0 ] in ( " n " , " N " ) :
return
elif test [ 0 ] in ( " q " , " Q " ) :
2012-12-06 17:14:19 +04:00
raise SqlmapUserQuitException
2012-07-20 22:17:35 +04:00
else :
regex = " | " . join ( conf . tbl . split ( " , " ) )
return tableExists ( paths . COMMON_TABLES , regex )
foundTbls = { }
tblList = conf . tbl . split ( " , " )
rootQuery = queries [ Backend . getIdentifiedDbms ( ) ] . search_table
tblCond = rootQuery . inband . condition
dbCond = rootQuery . inband . condition2
tblConsider , tblCondParam = self . likeOrExact ( " table " )
for tbl in tblList :
2013-01-23 17:00:58 +04:00
values = [ ]
2012-07-20 22:17:35 +04:00
tbl = safeSQLIdentificatorNaming ( tbl , True )
2013-01-22 14:14:35 +04:00
if Backend . getIdentifiedDbms ( ) in ( DBMS . ORACLE , DBMS . DB2 , DBMS . FIREBIRD ) :
2012-07-20 22:17:35 +04:00
tbl = tbl . upper ( )
infoMsg = " searching table "
if tblConsider == " 1 " :
infoMsg + = " s like "
infoMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( tbl )
2013-01-23 18:34:20 +04:00
if dbCond and conf . db and conf . db != CURRENT_DB :
2012-07-20 22:17:35 +04:00
_ = conf . db . split ( " , " )
whereDbsQuery = " AND ( " + " OR " . join ( " %s = ' %s ' " % ( dbCond , unsafeSQLIdentificatorNaming ( db ) ) for db in _ ) + " ) "
infoMsg + = " for database %s ' %s ' " % ( " s " if len ( _ ) > 1 else " " , " , " . join ( db for db in _ ) )
elif conf . excludeSysDbs :
whereDbsQuery = " " . join ( " AND ' %s ' != %s " % ( unsafeSQLIdentificatorNaming ( db ) , dbCond ) for db in self . excludeDbsList )
infoMsg2 = " skipping system database %s ' %s ' " % ( " s " if len ( self . excludeDbsList ) > 1 else " " , " , " . join ( db for db in self . excludeDbsList ) )
logger . info ( infoMsg2 )
2013-01-23 18:34:20 +04:00
else :
whereDbsQuery = " "
2012-07-20 22:17:35 +04:00
logger . info ( infoMsg )
tblQuery = " %s %s " % ( tblCond , tblCondParam )
2013-02-15 16:54:42 +04:00
tblQuery = tblQuery % unsafeSQLIdentificatorNaming ( tbl )
2012-07-20 22:17:35 +04:00
2012-12-05 13:45:17 +04:00
if any ( isTechniqueAvailable ( _ ) for _ in ( PAYLOAD . TECHNIQUE . UNION , PAYLOAD . TECHNIQUE . ERROR , PAYLOAD . TECHNIQUE . QUERY ) ) or conf . direct :
2012-07-20 22:17:35 +04:00
query = rootQuery . inband . query
2013-01-23 18:34:20 +04:00
2013-01-23 17:22:35 +04:00
query = query % ( tblQuery + whereDbsQuery )
2012-10-28 01:16:25 +04:00
values = inject . getValue ( query , blind = False , time = False )
2012-07-20 22:17:35 +04:00
2013-01-22 14:14:35 +04:00
if values and Backend . getIdentifiedDbms ( ) in ( DBMS . SQLITE , DBMS . FIREBIRD ) :
2013-01-14 20:26:11 +04:00
newValues = [ ]
if isinstance ( values , basestring ) :
values = [ values ]
for value in values :
2013-01-22 13:53:05 +04:00
dbName = " SQLite " if Backend . isDbms ( DBMS . SQLITE ) else " Firebird "
newValues . append ( [ " %s %s " % ( dbName , METADB_SUFFIX ) , value ] )
2013-01-14 20:26:11 +04:00
values = newValues
2012-07-20 22:17:35 +04:00
for foundDb , foundTbl in filterPairValues ( values ) :
foundDb = safeSQLIdentificatorNaming ( foundDb )
foundTbl = safeSQLIdentificatorNaming ( foundTbl , True )
if foundDb is None or foundTbl is None :
continue
if foundDb in foundTbls :
foundTbls [ foundDb ] . append ( foundTbl )
else :
foundTbls [ foundDb ] = [ foundTbl ]
2013-01-22 14:14:35 +04:00
2013-01-23 17:00:58 +04:00
if not values and isInferenceAvailable ( ) and not conf . direct :
2013-01-22 13:53:05 +04:00
if Backend . getIdentifiedDbms ( ) not in ( DBMS . SQLITE , DBMS . FIREBIRD ) :
2013-01-23 17:00:58 +04:00
if len ( whereDbsQuery ) == 0 :
infoMsg = " fetching number of databases with table "
if tblConsider == " 1 " :
infoMsg + = " s like "
infoMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( tbl )
logger . info ( infoMsg )
2012-07-20 22:17:35 +04:00
2013-01-23 17:00:58 +04:00
query = rootQuery . blind . count
2013-01-23 17:22:35 +04:00
query = query % ( tblQuery + whereDbsQuery )
2013-01-23 17:00:58 +04:00
count = inject . getValue ( query , union = False , error = False , expected = EXPECTED . INT , charsetType = CHARSET_TYPE . DIGITS )
2012-07-20 22:17:35 +04:00
2013-01-23 17:00:58 +04:00
if not isNumPosStrValue ( count ) :
warnMsg = " no databases have table "
if tblConsider == " 1 " :
warnMsg + = " s like "
warnMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( tbl )
logger . warn ( warnMsg )
2012-07-20 22:17:35 +04:00
2013-01-23 17:00:58 +04:00
continue
2012-07-20 22:17:35 +04:00
2013-01-23 17:00:58 +04:00
indexRange = getLimitRange ( count )
2012-07-20 22:17:35 +04:00
2013-01-23 17:00:58 +04:00
for index in indexRange :
query = rootQuery . blind . query
2013-01-23 17:22:35 +04:00
query = query % ( tblQuery + whereDbsQuery )
2013-01-23 17:00:58 +04:00
query = agent . limitQuery ( index , query )
2012-10-25 11:56:36 +04:00
2013-01-23 17:00:58 +04:00
foundDb = unArrayizeValue ( inject . getValue ( query , union = False , error = False ) )
foundDb = safeSQLIdentificatorNaming ( foundDb )
2012-07-20 22:17:35 +04:00
2013-01-23 17:00:58 +04:00
if foundDb not in foundTbls :
foundTbls [ foundDb ] = [ ]
2012-07-20 22:17:35 +04:00
2013-01-23 17:00:58 +04:00
if tblConsider == " 2 " :
foundTbls [ foundDb ] . append ( tbl )
2012-07-20 22:17:35 +04:00
2013-01-23 17:00:58 +04:00
if tblConsider == " 2 " :
continue
else :
for db in conf . db . split ( " , " ) :
2013-01-23 17:02:02 +04:00
if db not in foundTbls :
2013-02-15 17:21:51 +04:00
foundTbls [ safeSQLIdentificatorNaming ( db ) ] = [ ]
2013-01-14 20:26:11 +04:00
else :
2013-01-22 13:53:05 +04:00
dbName = " SQLite " if Backend . isDbms ( DBMS . SQLITE ) else " Firebird "
foundTbls [ " %s %s " % ( dbName , METADB_SUFFIX ) ] = [ ]
2012-07-20 22:17:35 +04:00
for db in foundTbls . keys ( ) :
db = safeSQLIdentificatorNaming ( db )
infoMsg = " fetching number of table "
if tblConsider == " 1 " :
infoMsg + = " s like "
2013-02-15 17:26:50 +04:00
infoMsg + = " ' %s ' in database ' %s ' " % ( unsafeSQLIdentificatorNaming ( tbl ) , unsafeSQLIdentificatorNaming ( db ) )
2012-07-20 22:17:35 +04:00
logger . info ( infoMsg )
query = rootQuery . blind . count2
2013-01-22 13:53:05 +04:00
if Backend . getIdentifiedDbms ( ) not in ( DBMS . SQLITE , DBMS . FIREBIRD ) :
2013-01-14 20:26:11 +04:00
query = query % unsafeSQLIdentificatorNaming ( db )
2012-07-20 22:17:35 +04:00
query + = " AND %s " % tblQuery
2013-01-23 17:22:35 +04:00
2012-10-28 02:36:09 +04:00
count = inject . getValue ( query , union = False , error = False , expected = EXPECTED . INT , charsetType = CHARSET_TYPE . DIGITS )
2012-07-20 22:17:35 +04:00
if not isNumPosStrValue ( count ) :
warnMsg = " no table "
if tblConsider == " 1 " :
warnMsg + = " s like "
warnMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( tbl )
2013-02-15 17:21:51 +04:00
warnMsg + = " in database ' %s ' " % unsafeSQLIdentificatorNaming ( db )
2012-07-20 22:17:35 +04:00
logger . warn ( warnMsg )
continue
indexRange = getLimitRange ( count )
for index in indexRange :
query = rootQuery . blind . query2
2013-01-22 13:53:05 +04:00
2013-01-30 21:08:34 +04:00
if query . endswith ( " ' %s ' ) " ) :
query = query [ : - 1 ] + " AND %s ) " % tblQuery
else :
query + = " AND %s " % tblQuery
2013-01-22 13:53:05 +04:00
if Backend . isDbms ( DBMS . FIREBIRD ) :
2013-01-30 21:08:34 +04:00
query = safeStringFormat ( query , index )
2013-01-22 13:53:05 +04:00
if Backend . getIdentifiedDbms ( ) not in ( DBMS . SQLITE , DBMS . FIREBIRD ) :
2013-01-30 21:08:34 +04:00
query = safeStringFormat ( query , unsafeSQLIdentificatorNaming ( db ) )
2013-01-22 13:53:05 +04:00
if not Backend . isDbms ( DBMS . FIREBIRD ) :
query = agent . limitQuery ( index , query )
2012-10-25 11:56:36 +04:00
2012-12-21 13:15:42 +04:00
foundTbl = unArrayizeValue ( inject . getValue ( query , union = False , error = False ) )
2013-02-05 14:37:49 +04:00
if not isNoneValue ( foundTbl ) :
2013-02-05 14:23:22 +04:00
kb . hintValue = foundTbl
foundTbl = safeSQLIdentificatorNaming ( foundTbl , True )
foundTbls [ db ] . append ( foundTbl )
2012-07-20 22:17:35 +04:00
2013-02-05 14:18:46 +04:00
for db in foundTbls . keys ( ) :
2013-02-05 14:23:22 +04:00
if isNoneValue ( foundTbls [ db ] ) :
2013-02-05 14:18:46 +04:00
del foundTbls [ db ]
2012-07-21 00:46:36 +04:00
if not foundTbls :
warnMsg = " no databases contain any of the provided tables "
logger . warn ( warnMsg )
return
conf . dumper . dbTables ( foundTbls )
self . dumpFoundTables ( foundTbls )
2012-07-20 22:17:35 +04:00
def searchColumn ( self ) :
bruteForce = False
if Backend . isDbms ( DBMS . MYSQL ) and not kb . data . has_information_schema :
errMsg = " information_schema not available, "
errMsg + = " back-end DBMS is MySQL < 5.0 "
bruteForce = True
if bruteForce :
message = " do you want to use common column existence check? %s " % ( " [Y/n/q] " if Backend . getIdentifiedDbms ( ) in ( DBMS . ACCESS , ) else " [y/N/q] " )
test = readInput ( message , default = " Y " if " Y " in message else " N " )
if test [ 0 ] in ( " n " , " N " ) :
return
elif test [ 0 ] in ( " q " , " Q " ) :
2012-12-06 17:14:19 +04:00
raise SqlmapUserQuitException
2012-07-20 22:17:35 +04:00
else :
regex = " | " . join ( conf . col . split ( " , " ) )
conf . dumper . dbTableColumns ( columnExists ( paths . COMMON_COLUMNS , regex ) )
message = " do you want to dump entries? [Y/n] "
output = readInput ( message , default = " Y " )
if output and output [ 0 ] not in ( " n " , " N " ) :
self . dumpAll ( )
return
rootQuery = queries [ Backend . getIdentifiedDbms ( ) ] . search_column
foundCols = { }
dbs = { }
whereDbsQuery = " "
whereTblsQuery = " "
infoMsgTbl = " "
infoMsgDb = " "
colList = conf . col . split ( " , " )
2012-07-21 01:29:48 +04:00
origTbl = conf . tbl
origDb = conf . db
2012-07-20 22:17:35 +04:00
colCond = rootQuery . inband . condition
dbCond = rootQuery . inband . condition2
tblCond = rootQuery . inband . condition3
colConsider , colCondParam = self . likeOrExact ( " column " )
for column in colList :
2013-01-23 17:00:58 +04:00
values = [ ]
2012-07-20 22:17:35 +04:00
column = safeSQLIdentificatorNaming ( column )
2012-07-21 01:29:48 +04:00
conf . db = origDb
conf . tbl = origTbl
2012-07-20 22:17:35 +04:00
if Backend . getIdentifiedDbms ( ) in ( DBMS . ORACLE , DBMS . DB2 ) :
column = column . upper ( )
infoMsg = " searching column "
if colConsider == " 1 " :
infoMsg + = " s like "
infoMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( column )
foundCols [ column ] = { }
if conf . tbl :
_ = conf . tbl . split ( " , " )
whereTblsQuery = " AND ( " + " OR " . join ( " %s = ' %s ' " % ( tblCond , unsafeSQLIdentificatorNaming ( tbl ) ) for tbl in _ ) + " ) "
2013-02-15 17:26:50 +04:00
infoMsgTbl = " for table %s ' %s ' " % ( " s " if len ( _ ) > 1 else " " , " , " . join ( unsafeSQLIdentificatorNaming ( tbl ) for tbl in _ ) )
2012-07-20 22:17:35 +04:00
if conf . db and conf . db != CURRENT_DB :
_ = conf . db . split ( " , " )
whereDbsQuery = " AND ( " + " OR " . join ( " %s = ' %s ' " % ( dbCond , unsafeSQLIdentificatorNaming ( db ) ) for db in _ ) + " ) "
2013-02-15 17:26:50 +04:00
infoMsgDb = " in database %s ' %s ' " % ( " s " if len ( _ ) > 1 else " " , " , " . join ( unsafeSQLIdentificatorNaming ( db ) for db in _ ) )
2012-07-20 22:17:35 +04:00
elif conf . excludeSysDbs :
whereDbsQuery = " " . join ( " AND %s != ' %s ' " % ( dbCond , unsafeSQLIdentificatorNaming ( db ) ) for db in self . excludeDbsList )
2013-02-15 17:26:50 +04:00
infoMsg2 = " skipping system database %s ' %s ' " % ( " s " if len ( self . excludeDbsList ) > 1 else " " , " , " . join ( unsafeSQLIdentificatorNaming ( db ) for db in self . excludeDbsList ) )
2012-07-20 22:17:35 +04:00
logger . info ( infoMsg2 )
else :
infoMsgDb = " across all databases "
logger . info ( " %s %s %s " % ( infoMsg , infoMsgTbl , infoMsgDb ) )
colQuery = " %s %s " % ( colCond , colCondParam )
colQuery = colQuery % unsafeSQLIdentificatorNaming ( column )
2012-12-05 13:45:17 +04:00
if any ( isTechniqueAvailable ( _ ) for _ in ( PAYLOAD . TECHNIQUE . UNION , PAYLOAD . TECHNIQUE . ERROR , PAYLOAD . TECHNIQUE . QUERY ) ) or conf . direct :
2012-07-20 22:17:35 +04:00
if not all ( ( conf . db , conf . tbl ) ) :
# Enumerate tables containing the column provided if
# either of database(s) or table(s) is not provided
query = rootQuery . inband . query
2013-01-23 17:22:35 +04:00
query = query % ( colQuery + whereDbsQuery + whereTblsQuery )
2012-10-28 01:16:25 +04:00
values = inject . getValue ( query , blind = False , time = False )
2012-07-20 22:17:35 +04:00
else :
# Assume provided databases' tables contain the
# column(s) provided
values = [ ]
for db in conf . db . split ( " , " ) :
for tbl in conf . tbl . split ( " , " ) :
values . append ( [ db , tbl ] )
for db , tbl in filterPairValues ( values ) :
db = safeSQLIdentificatorNaming ( db )
tbls = tbl . split ( " , " )
for tbl in tbls :
tbl = safeSQLIdentificatorNaming ( tbl , True )
if db is None or tbl is None :
continue
conf . db = db
conf . tbl = tbl
conf . col = column
self . getColumns ( onlyColNames = True , colTuple = ( colConsider , colCondParam ) , bruteForce = False )
if db in kb . data . cachedColumns and tbl in kb . data . cachedColumns [ db ] :
if db not in dbs :
dbs [ db ] = { }
if tbl not in dbs [ db ] :
dbs [ db ] [ tbl ] = { }
dbs [ db ] [ tbl ] . update ( kb . data . cachedColumns [ db ] [ tbl ] )
if db in foundCols [ column ] :
foundCols [ column ] [ db ] . append ( tbl )
else :
foundCols [ column ] [ db ] = [ tbl ]
kb . data . cachedColumns = { }
2013-01-22 14:14:35 +04:00
2013-01-23 17:00:58 +04:00
if not values and isInferenceAvailable ( ) and not conf . direct :
2012-07-20 22:17:35 +04:00
if not conf . db :
infoMsg = " fetching number of databases with tables containing column "
if colConsider == " 1 " :
infoMsg + = " s like "
2013-02-15 17:26:50 +04:00
infoMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( column )
2012-07-20 22:17:35 +04:00
logger . info ( " %s %s %s " % ( infoMsg , infoMsgTbl , infoMsgDb ) )
query = rootQuery . blind . count
2013-01-23 17:22:35 +04:00
query = query % ( colQuery + whereDbsQuery + whereTblsQuery )
2012-10-28 02:36:09 +04:00
count = inject . getValue ( query , union = False , error = False , expected = EXPECTED . INT , charsetType = CHARSET_TYPE . DIGITS )
2012-07-20 22:17:35 +04:00
if not isNumPosStrValue ( count ) :
warnMsg = " no databases have tables containing column "
if colConsider == " 1 " :
warnMsg + = " s like "
2013-02-15 17:26:50 +04:00
warnMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( column )
2012-07-20 22:17:35 +04:00
logger . warn ( " %s %s " % ( warnMsg , infoMsgTbl ) )
continue
indexRange = getLimitRange ( count )
for index in indexRange :
query = rootQuery . blind . query
2013-01-23 17:22:35 +04:00
query = query % ( colQuery + whereDbsQuery + whereTblsQuery )
2012-07-20 22:17:35 +04:00
query = agent . limitQuery ( index , query )
2013-01-23 17:22:35 +04:00
2012-12-21 13:15:42 +04:00
db = unArrayizeValue ( inject . getValue ( query , union = False , error = False ) )
2012-07-20 22:17:35 +04:00
db = safeSQLIdentificatorNaming ( db )
if db not in dbs :
dbs [ db ] = { }
if db not in foundCols [ column ] :
foundCols [ column ] [ db ] = [ ]
else :
for db in conf . db . split ( " , " ) :
if db not in foundCols [ column ] :
foundCols [ column ] [ db ] = [ ]
2012-07-21 01:35:20 +04:00
origDb = conf . db
origTbl = conf . tbl
2012-07-20 22:17:35 +04:00
for column , dbData in foundCols . items ( ) :
colQuery = " %s %s " % ( colCond , colCondParam )
2013-02-15 16:54:42 +04:00
colQuery = colQuery % unsafeSQLIdentificatorNaming ( column )
2012-07-20 22:17:35 +04:00
for db in dbData :
db = safeSQLIdentificatorNaming ( db )
2012-07-21 01:35:20 +04:00
conf . db = origDb
conf . tbl = origTbl
2012-07-20 22:17:35 +04:00
infoMsg = " fetching number of tables containing column "
if colConsider == " 1 " :
infoMsg + = " s like "
2013-02-15 17:26:50 +04:00
infoMsg + = " ' %s ' in database ' %s ' " % ( unsafeSQLIdentificatorNaming ( column ) , unsafeSQLIdentificatorNaming ( db ) )
2012-07-20 22:17:35 +04:00
logger . info ( infoMsg )
query = rootQuery . blind . count2
2013-02-15 19:48:58 +04:00
query = query % unsafeSQLIdentificatorNaming ( db )
2012-07-20 22:17:35 +04:00
query + = " AND %s " % colQuery
query + = whereTblsQuery
2013-01-23 17:22:35 +04:00
2012-10-28 02:36:09 +04:00
count = inject . getValue ( query , union = False , error = False , expected = EXPECTED . INT , charsetType = CHARSET_TYPE . DIGITS )
2012-07-20 22:17:35 +04:00
if not isNumPosStrValue ( count ) :
warnMsg = " no tables contain column "
if colConsider == " 1 " :
warnMsg + = " s like "
2013-02-15 17:26:50 +04:00
warnMsg + = " ' %s ' " % unsafeSQLIdentificatorNaming ( column )
warnMsg + = " in database ' %s ' " % unsafeSQLIdentificatorNaming ( db )
2012-07-20 22:17:35 +04:00
logger . warn ( warnMsg )
continue
indexRange = getLimitRange ( count )
for index in indexRange :
query = rootQuery . blind . query2
2013-01-31 19:41:23 +04:00
if query . endswith ( " ' %s ' ) " ) :
2013-02-05 15:24:57 +04:00
query = query [ : - 1 ] + " AND %s ) " % ( colQuery + whereTblsQuery )
2013-01-31 19:41:23 +04:00
else :
2013-02-05 15:24:57 +04:00
query + = " AND %s " % ( colQuery + whereTblsQuery )
2013-01-31 19:41:23 +04:00
query = safeStringFormat ( query , db )
2012-07-20 22:17:35 +04:00
query = agent . limitQuery ( index , query )
2013-01-23 17:22:35 +04:00
2012-12-21 13:15:42 +04:00
tbl = unArrayizeValue ( inject . getValue ( query , union = False , error = False ) )
2012-07-20 22:17:35 +04:00
kb . hintValue = tbl
tbl = safeSQLIdentificatorNaming ( tbl , True )
conf . db = db
conf . tbl = tbl
conf . col = column
self . getColumns ( onlyColNames = True , colTuple = ( colConsider , colCondParam ) , bruteForce = False )
if db in kb . data . cachedColumns and tbl in kb . data . cachedColumns [ db ] :
if db not in dbs :
dbs [ db ] = { }
if tbl not in dbs [ db ] :
dbs [ db ] [ tbl ] = { }
dbs [ db ] [ tbl ] . update ( kb . data . cachedColumns [ db ] [ tbl ] )
kb . data . cachedColumns = { }
if db in foundCols [ column ] :
foundCols [ column ] [ db ] . append ( tbl )
else :
foundCols [ column ] [ db ] = [ tbl ]
2012-12-18 22:07:34 +04:00
if dbs :
conf . dumper . dbColumns ( foundCols , colConsider , dbs )
self . dumpFoundColumn ( dbs , foundCols , colConsider )
else :
2012-07-21 00:46:36 +04:00
warnMsg = " no databases have tables containing any of the "
warnMsg + = " provided columns "
logger . warn ( warnMsg )
2012-07-20 22:17:35 +04:00
def search ( self ) :
2012-07-21 01:29:30 +04:00
if Backend . getIdentifiedDbms ( ) in ( DBMS . ORACLE , DBMS . DB2 ) :
2012-07-20 22:17:35 +04:00
for item in ( ' db ' , ' tbl ' , ' col ' ) :
if getattr ( conf , item , None ) :
setattr ( conf , item , getattr ( conf , item ) . upper ( ) )
if conf . col :
self . searchColumn ( )
elif conf . tbl :
2012-07-21 00:46:36 +04:00
self . searchTable ( )
2012-07-20 22:17:35 +04:00
elif conf . db :
2012-07-21 01:29:30 +04:00
self . searchDb ( )
2012-07-20 22:17:35 +04:00
else :
2012-07-21 00:46:36 +04:00
errMsg = " missing parameter, provide -D, -T or -C along "
2012-07-20 22:17:35 +04:00
errMsg + = " with --search "
2013-01-04 02:20:55 +04:00
raise SqlmapMissingMandatoryOptionException ( errMsg )