diff --git a/plugins/generic/enumeration.py b/plugins/generic/enumeration.py index bd98b3c3f..038facc70 100644 --- a/plugins/generic/enumeration.py +++ b/plugins/generic/enumeration.py @@ -1012,7 +1012,7 @@ class Enumeration: tblList = list(tblList) else: errMsg = "unable to retrieve the tables " - errMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) + errMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) raise sqlmapNoneDataException, errMsg for tbl in tblList: @@ -1100,7 +1100,7 @@ class Enumeration: condQuery = "" infoMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl) - infoMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) + infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) logger.info(infoMsg) if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): @@ -1169,7 +1169,7 @@ class Enumeration: condQuery = "" infoMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl) - infoMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) + infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) logger.info(infoMsg) if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL): @@ -1200,7 +1200,7 @@ class Enumeration: if not isNumPosStrValue(count): errMsg = "unable to retrieve the number of columns " errMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl) - errMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) + errMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) logger.error(errMsg) continue @@ -1264,7 +1264,7 @@ class Enumeration: if not kb.data.cachedColumns: errMsg = "unable to retrieve the columns for any " - errMsg += "table on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) + errMsg += "table in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) logger.error(errMsg) if bruteForce is None: @@ -1523,7 +1523,7 @@ class Enumeration: tblList = tblList[0] else: errMsg = "unable to retrieve the tables " - errMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) + errMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) raise sqlmapNoneDataException, errMsg for tbl in tblList: @@ -1548,7 +1548,7 @@ class Enumeration: kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)] \ or not kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)]: warnMsg = "unable to enumerate the columns for table " - warnMsg += "'%s' on database" % unsafeSQLIdentificatorNaming(tbl) + warnMsg += "'%s' in database" % unsafeSQLIdentificatorNaming(tbl) warnMsg += " '%s'" % unsafeSQLIdentificatorNaming(conf.db) warnMsg += ", skipping" if len(tblList) > 1 else "" logger.warn(warnMsg) @@ -1563,7 +1563,7 @@ class Enumeration: if conf.col: infoMsg += " of column(s) '%s'" % colString infoMsg += " for table '%s'" % unsafeSQLIdentificatorNaming(tbl) - infoMsg += " on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) + infoMsg += " in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) logger.info(infoMsg) entriesCount = 0 @@ -1650,7 +1650,7 @@ class Enumeration: if conf.col: infoMsg += "column(s) '%s' " % colString infoMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl) - infoMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) + infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) logger.info(infoMsg) if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): @@ -1670,7 +1670,7 @@ class Enumeration: if count == 0: warnMsg = "table '%s' " % unsafeSQLIdentificatorNaming(tbl) - warnMsg += "on database '%s' " % unsafeSQLIdentificatorNaming(conf.db) + warnMsg += "in database '%s' " % unsafeSQLIdentificatorNaming(conf.db) warnMsg += "appears to be empty" logger.warn(warnMsg) @@ -1683,7 +1683,7 @@ class Enumeration: if conf.col: warnMsg += "column(s) '%s' " % colString warnMsg += "entries for table '%s' " % unsafeSQLIdentificatorNaming(tbl) - warnMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db) + warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db) logger.warn(warnMsg) continue @@ -1747,7 +1747,7 @@ class Enumeration: if conf.col: warnMsg += "columns '%s' " % colString warnMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl) - warnMsg += "on database '%s'%s" % (unsafeSQLIdentificatorNaming(conf.db), " (permission denied)" if kb.permissionFlag else "") + warnMsg += "in database '%s'%s" % (unsafeSQLIdentificatorNaming(conf.db), " (permission denied)" if kb.permissionFlag else "") logger.warn(warnMsg) else: kb.data.dumpedTable["__infos__"] = {"count": entriesCount, @@ -1990,6 +1990,7 @@ class Enumeration: tblList = conf.tbl.split(",") tblCond = rootQuery.inband.condition dbCond = rootQuery.inband.condition2 + whereDbsQuery = "" tblConsider, tblCondParam = self.likeOrExact("table") @@ -2012,8 +2013,6 @@ class Enumeration: 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) - else: - whereDbsQuery = "" logger.info(infoMsg) @@ -2148,9 +2147,11 @@ class Enumeration: rootQuery = queries[Backend.getIdentifiedDbms()].search_column foundCols = {} dbs = {} + whereDbsQuery = "" colList = conf.col.split(",") colCond = rootQuery.inband.condition dbCond = rootQuery.inband.condition2 + tblCond = rootQuery.inband.condition3 colConsider, colCondParam = self.likeOrExact("column") @@ -2167,16 +2168,19 @@ class Enumeration: foundCols[column] = {} + if conf.tbl: + _ = conf.tbl.split(",") + whereTblsQuery = " AND (" + " OR ".join("%s = '%s'" % (tblCond, unsafeSQLIdentificatorNaming(tbl)) for tbl in _) + ")" + infoMsg += " for table%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(tbl for tbl in _)) + if conf.db and conf.db != CURRENT_DB: _ = conf.db.split(",") - whereDbsQuery = "".join(" AND '%s' = %s" % (unsafeSQLIdentificatorNaming(db), dbCond) for db in _) - infoMsg += " for database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _)) + whereDbsQuery = " AND (" + " OR ".join("%s = '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) for db in _) + ")" + infoMsg += " in 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) + whereDbsQuery = "".join(" AND %s != '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) 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) - else: - whereDbsQuery = "" logger.info(infoMsg) @@ -2185,41 +2189,53 @@ class Enumeration: if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: 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 query += colQuery query += whereDbsQuery + query += whereTblsQuery values = inject.getValue(query, blind=False) else: - values = ((conf.db, conf.tbl),) + # 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 foundDb, foundTbl in filterPairValues(values): foundDb = safeSQLIdentificatorNaming(foundDb) - foundTbl = safeSQLIdentificatorNaming(foundTbl, True) + foundTbls = foundTbl.split(",") - if foundDb is None or foundTbl is None: - continue + for foundTbl in foundTbls: + foundTbl = safeSQLIdentificatorNaming(foundTbl, True) - conf.db = foundDb - conf.tbl = foundTbl - conf.col = column + if foundDb is None or foundTbl is None: + continue - self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False) + conf.db = foundDb + conf.tbl = foundTbl + conf.col = column - if foundDb in kb.data.cachedColumns and foundTbl in kb.data.cachedColumns[foundDb]: - if foundDb not in dbs: - dbs[foundDb] = {} + self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False) - if foundTbl not in dbs[foundDb]: - dbs[foundDb][foundTbl] = {} + if foundDb in kb.data.cachedColumns and foundTbl in kb.data.cachedColumns[foundDb]: + if foundDb not in dbs: + dbs[foundDb] = {} - dbs[foundDb][foundTbl].update(kb.data.cachedColumns[foundDb][foundTbl]) + if foundTbl not in dbs[foundDb]: + dbs[foundDb][foundTbl] = {} - kb.data.cachedColumns = {} + dbs[foundDb][foundTbl].update(kb.data.cachedColumns[foundDb][foundTbl]) - if foundDb in foundCols[column]: - foundCols[column][foundDb].append(foundTbl) - else: - foundCols[column][foundDb] = [foundTbl] + if foundDb in foundCols[column]: + foundCols[column][foundDb].append(foundTbl) + else: + foundCols[column][foundDb] = [foundTbl] + + kb.data.cachedColumns = {} else: if not conf.db: infoMsg = "fetching number of databases with tables containing column" @@ -2231,6 +2247,7 @@ class Enumeration: query = rootQuery.blind.count query += colQuery query += whereDbsQuery + query += whereTblsQuery count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if not isNumPosStrValue(count): @@ -2248,6 +2265,7 @@ class Enumeration: query = rootQuery.blind.query query += colQuery query += whereDbsQuery + query += whereTblsQuery if Backend.isDbms(DBMS.DB2): query += ") AS foobar" query = agent.limitQuery(index, query) @@ -2280,6 +2298,7 @@ class Enumeration: query = rootQuery.blind.count2 query = query % db query += " AND %s" % colQuery + query += whereTblsQuery count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if not isNumPosStrValue(count): @@ -2298,6 +2317,7 @@ class Enumeration: query = rootQuery.blind.query2 query = query % db query += " AND %s" % colQuery + query += whereTblsQuery query = agent.limitQuery(index, query) tbl = inject.getValue(query, inband=False, error=False) kb.hintValue = tbl diff --git a/xml/queries.xml b/xml/queries.xml index 79d0d486f..6dcb78175 100644 --- a/xml/queries.xml +++ b/xml/queries.xml @@ -69,8 +69,8 @@ - - + + @@ -142,8 +142,8 @@ - - + + @@ -207,8 +207,8 @@ - - + + @@ -294,8 +294,8 @@ - - + + @@ -548,7 +548,7 @@ - + @@ -617,8 +617,8 @@ - - + +