Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 012fc21

Browse files
committed
Improvements to column(s) search: now it's possible to search column(s) in provided table(s) across all databases, search column(s) across all tables in provided database(s) or let sqlmap alone identify the databases' tables - this is now implemented for error-based, union query and direct connection. Work is still required for boolean-based and time-based.
Adapted the queries.xml file accordingly
1 parent c878dd3 commit 012fc21

2 files changed

Lines changed: 69 additions & 49 deletions

File tree

plugins/generic/enumeration.py

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@ def getColumns(self, onlyColNames=False, colTuple=None, bruteForce=None):
10121012
tblList = list(tblList)
10131013
else:
10141014
errMsg = "unable to retrieve the tables "
1015-
errMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
1015+
errMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
10161016
raise sqlmapNoneDataException, errMsg
10171017

10181018
for tbl in tblList:
@@ -1100,7 +1100,7 @@ def getColumns(self, onlyColNames=False, colTuple=None, bruteForce=None):
11001100
condQuery = ""
11011101

11021102
infoMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
1103-
infoMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
1103+
infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
11041104
logger.info(infoMsg)
11051105

11061106
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
@@ -1169,7 +1169,7 @@ def getColumns(self, onlyColNames=False, colTuple=None, bruteForce=None):
11691169
condQuery = ""
11701170

11711171
infoMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
1172-
infoMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
1172+
infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
11731173
logger.info(infoMsg)
11741174

11751175
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL):
@@ -1200,7 +1200,7 @@ def getColumns(self, onlyColNames=False, colTuple=None, bruteForce=None):
12001200
if not isNumPosStrValue(count):
12011201
errMsg = "unable to retrieve the number of columns "
12021202
errMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
1203-
errMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
1203+
errMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
12041204
logger.error(errMsg)
12051205

12061206
continue
@@ -1264,7 +1264,7 @@ def getColumns(self, onlyColNames=False, colTuple=None, bruteForce=None):
12641264

12651265
if not kb.data.cachedColumns:
12661266
errMsg = "unable to retrieve the columns for any "
1267-
errMsg += "table on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
1267+
errMsg += "table in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
12681268
logger.error(errMsg)
12691269

12701270
if bruteForce is None:
@@ -1523,7 +1523,7 @@ def dumpTable(self, foundData=None):
15231523
tblList = tblList[0]
15241524
else:
15251525
errMsg = "unable to retrieve the tables "
1526-
errMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
1526+
errMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
15271527
raise sqlmapNoneDataException, errMsg
15281528

15291529
for tbl in tblList:
@@ -1548,7 +1548,7 @@ def dumpTable(self, foundData=None):
15481548
kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)] \
15491549
or not kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)]:
15501550
warnMsg = "unable to enumerate the columns for table "
1551-
warnMsg += "'%s' on database" % unsafeSQLIdentificatorNaming(tbl)
1551+
warnMsg += "'%s' in database" % unsafeSQLIdentificatorNaming(tbl)
15521552
warnMsg += " '%s'" % unsafeSQLIdentificatorNaming(conf.db)
15531553
warnMsg += ", skipping" if len(tblList) > 1 else ""
15541554
logger.warn(warnMsg)
@@ -1563,7 +1563,7 @@ def dumpTable(self, foundData=None):
15631563
if conf.col:
15641564
infoMsg += " of column(s) '%s'" % colString
15651565
infoMsg += " for table '%s'" % unsafeSQLIdentificatorNaming(tbl)
1566-
infoMsg += " on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
1566+
infoMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
15671567
logger.info(infoMsg)
15681568

15691569
entriesCount = 0
@@ -1650,7 +1650,7 @@ def dumpTable(self, foundData=None):
16501650
if conf.col:
16511651
infoMsg += "column(s) '%s' " % colString
16521652
infoMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
1653-
infoMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
1653+
infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
16541654
logger.info(infoMsg)
16551655

16561656
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
@@ -1670,7 +1670,7 @@ def dumpTable(self, foundData=None):
16701670

16711671
if count == 0:
16721672
warnMsg = "table '%s' " % unsafeSQLIdentificatorNaming(tbl)
1673-
warnMsg += "on database '%s' " % unsafeSQLIdentificatorNaming(conf.db)
1673+
warnMsg += "in database '%s' " % unsafeSQLIdentificatorNaming(conf.db)
16741674
warnMsg += "appears to be empty"
16751675
logger.warn(warnMsg)
16761676

@@ -1683,7 +1683,7 @@ def dumpTable(self, foundData=None):
16831683
if conf.col:
16841684
warnMsg += "column(s) '%s' " % colString
16851685
warnMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
1686-
warnMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
1686+
warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
16871687
logger.warn(warnMsg)
16881688

16891689
continue
@@ -1747,7 +1747,7 @@ def dumpTable(self, foundData=None):
17471747
if conf.col:
17481748
warnMsg += "columns '%s' " % colString
17491749
warnMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
1750-
warnMsg += "on database '%s'%s" % (unsafeSQLIdentificatorNaming(conf.db), " (permission denied)" if kb.permissionFlag else "")
1750+
warnMsg += "in database '%s'%s" % (unsafeSQLIdentificatorNaming(conf.db), " (permission denied)" if kb.permissionFlag else "")
17511751
logger.warn(warnMsg)
17521752
else:
17531753
kb.data.dumpedTable["__infos__"] = {"count": entriesCount,
@@ -1990,6 +1990,7 @@ def searchTable(self):
19901990
tblList = conf.tbl.split(",")
19911991
tblCond = rootQuery.inband.condition
19921992
dbCond = rootQuery.inband.condition2
1993+
whereDbsQuery = ""
19931994

19941995
tblConsider, tblCondParam = self.likeOrExact("table")
19951996

@@ -2012,8 +2013,6 @@ def searchTable(self):
20122013
whereDbsQuery = "".join(" AND '%s' != %s" % (unsafeSQLIdentificatorNaming(db), dbCond) for db in self.excludeDbsList)
20132014
infoMsg2 = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(db for db in self.excludeDbsList))
20142015
logger.info(infoMsg2)
2015-
else:
2016-
whereDbsQuery = ""
20172016

20182017
logger.info(infoMsg)
20192018

@@ -2148,9 +2147,11 @@ def searchColumn(self):
21482147
rootQuery = queries[Backend.getIdentifiedDbms()].search_column
21492148
foundCols = {}
21502149
dbs = {}
2150+
whereDbsQuery = ""
21512151
colList = conf.col.split(",")
21522152
colCond = rootQuery.inband.condition
21532153
dbCond = rootQuery.inband.condition2
2154+
tblCond = rootQuery.inband.condition3
21542155

21552156
colConsider, colCondParam = self.likeOrExact("column")
21562157

@@ -2167,16 +2168,19 @@ def searchColumn(self):
21672168

21682169
foundCols[column] = {}
21692170

2171+
if conf.tbl:
2172+
_ = conf.tbl.split(",")
2173+
whereTblsQuery = " AND (" + " OR ".join("%s = '%s'" % (tblCond, unsafeSQLIdentificatorNaming(tbl)) for tbl in _) + ")"
2174+
infoMsg += " for table%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(tbl for tbl in _))
2175+
21702176
if conf.db and conf.db != CURRENT_DB:
21712177
_ = conf.db.split(",")
2172-
whereDbsQuery = "".join(" AND '%s' = %s" % (unsafeSQLIdentificatorNaming(db), dbCond) for db in _)
2173-
infoMsg += " for database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _))
2178+
whereDbsQuery = " AND (" + " OR ".join("%s = '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) for db in _) + ")"
2179+
infoMsg += " in database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _))
21742180
elif conf.excludeSysDbs:
2175-
whereDbsQuery = "".join(" AND '%s' != %s" % (unsafeSQLIdentificatorNaming(db), dbCond) for db in self.excludeDbsList)
2181+
whereDbsQuery = "".join(" AND %s != '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) for db in self.excludeDbsList)
21762182
infoMsg2 = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(db for db in self.excludeDbsList))
21772183
logger.info(infoMsg2)
2178-
else:
2179-
whereDbsQuery = ""
21802184

21812185
logger.info(infoMsg)
21822186

@@ -2185,41 +2189,53 @@ def searchColumn(self):
21852189

21862190
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct:
21872191
if not all((conf.db, conf.tbl)):
2192+
# Enumerate tables containing the column provided if
2193+
# either of database(s) or table(s) is not provided
21882194
query = rootQuery.inband.query
21892195
query += colQuery
21902196
query += whereDbsQuery
2197+
query += whereTblsQuery
21912198
values = inject.getValue(query, blind=False)
21922199
else:
2193-
values = ((conf.db, conf.tbl),)
2200+
# Assume provided databases' tables contain the
2201+
# column(s) provided
2202+
values = []
2203+
2204+
for db in conf.db.split(","):
2205+
for tbl in conf.tbl.split(","):
2206+
values.append([db, tbl])
21942207

21952208
for foundDb, foundTbl in filterPairValues(values):
21962209
foundDb = safeSQLIdentificatorNaming(foundDb)
2197-
foundTbl = safeSQLIdentificatorNaming(foundTbl, True)
2210+
foundTbls = foundTbl.split(",")
21982211

2199-
if foundDb is None or foundTbl is None:
2200-
continue
2212+
for foundTbl in foundTbls:
2213+
foundTbl = safeSQLIdentificatorNaming(foundTbl, True)
2214+
2215+
if foundDb is None or foundTbl is None:
2216+
continue
22012217

2202-
conf.db = foundDb
2203-
conf.tbl = foundTbl
2204-
conf.col = column
2218+
conf.db = foundDb
2219+
conf.tbl = foundTbl
2220+
conf.col = column
22052221

2206-
self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False)
2222+
self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False)
22072223

2208-
if foundDb in kb.data.cachedColumns and foundTbl in kb.data.cachedColumns[foundDb]:
2209-
if foundDb not in dbs:
2210-
dbs[foundDb] = {}
2224+
if foundDb in kb.data.cachedColumns and foundTbl in kb.data.cachedColumns[foundDb]:
2225+
if foundDb not in dbs:
2226+
dbs[foundDb] = {}
22112227

2212-
if foundTbl not in dbs[foundDb]:
2213-
dbs[foundDb][foundTbl] = {}
2228+
if foundTbl not in dbs[foundDb]:
2229+
dbs[foundDb][foundTbl] = {}
22142230

2215-
dbs[foundDb][foundTbl].update(kb.data.cachedColumns[foundDb][foundTbl])
2231+
dbs[foundDb][foundTbl].update(kb.data.cachedColumns[foundDb][foundTbl])
22162232

2217-
kb.data.cachedColumns = {}
2233+
if foundDb in foundCols[column]:
2234+
foundCols[column][foundDb].append(foundTbl)
2235+
else:
2236+
foundCols[column][foundDb] = [foundTbl]
22182237

2219-
if foundDb in foundCols[column]:
2220-
foundCols[column][foundDb].append(foundTbl)
2221-
else:
2222-
foundCols[column][foundDb] = [foundTbl]
2238+
kb.data.cachedColumns = {}
22232239
else:
22242240
if not conf.db:
22252241
infoMsg = "fetching number of databases with tables containing column"
@@ -2231,6 +2247,7 @@ def searchColumn(self):
22312247
query = rootQuery.blind.count
22322248
query += colQuery
22332249
query += whereDbsQuery
2250+
query += whereTblsQuery
22342251
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
22352252

22362253
if not isNumPosStrValue(count):
@@ -2248,6 +2265,7 @@ def searchColumn(self):
22482265
query = rootQuery.blind.query
22492266
query += colQuery
22502267
query += whereDbsQuery
2268+
query += whereTblsQuery
22512269
if Backend.isDbms(DBMS.DB2):
22522270
query += ") AS foobar"
22532271
query = agent.limitQuery(index, query)
@@ -2280,6 +2298,7 @@ def searchColumn(self):
22802298
query = rootQuery.blind.count2
22812299
query = query % db
22822300
query += " AND %s" % colQuery
2301+
query += whereTblsQuery
22832302
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
22842303

22852304
if not isNumPosStrValue(count):
@@ -2298,6 +2317,7 @@ def searchColumn(self):
22982317
query = rootQuery.blind.query2
22992318
query = query % db
23002319
query += " AND %s" % colQuery
2320+
query += whereTblsQuery
23012321
query = agent.limitQuery(index, query)
23022322
tbl = inject.getValue(query, inband=False, error=False)
23032323
kb.hintValue = tbl

0 commit comments

Comments
 (0)