def getTables(self, bruteForce=None): if len(kb.data.cachedTables) > 0: return kb.data.cachedTables self.forceDbmsEnum() if bruteForce is None: 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" logger.error(errMsg) bruteForce = True elif Backend.isDbms(DBMS.ACCESS): try: tables = self.getTables(False) except sqlmapNoneDataException: tables = None if not tables: errMsg = "cannot retrieve table names, " errMsg += "back-end DBMS is Access" logger.error(errMsg) bruteForce = True else: return tables if conf.db == CURRENT_DB: conf.db = self.getCurrentDb() if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): conf.db = conf.db.upper() if conf.db: dbs = conf.db.split(",") else: dbs = self.getDbs() for db in dbs: dbs[dbs.index(db)] = safeSQLIdentificatorNaming(db) dbs = filter(None, dbs) if bruteForce: resumeAvailable = False for db, table in kb.brute.tables: if db == conf.db: resumeAvailable = True break if resumeAvailable: for db, table in kb.brute.tables: if db == conf.db: if conf.db not in kb.data.cachedTables: kb.data.cachedTables[conf.db] = [table] else: kb.data.cachedTables[conf.db].append(table) return kb.data.cachedTables 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"): raise sqlmapUserQuitException else: return tableExists(paths.COMMON_TABLES) infoMsg = "fetching tables for database" infoMsg += "%s: '%s'" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, basestring) else db[0] for db in sorted(dbs))) logger.info(infoMsg) rootQuery = queries[Backend.getIdentifiedDbms()].tables if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: query = rootQuery.inband.query condition = rootQuery.inband.condition if 'condition' in rootQuery.inband else None if condition: if conf.excludeSysDbs: query += " WHERE " query += " AND ".join("%s != '%s'" % (condition, unsafeSQLIdentificatorNaming(db)) 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) elif not Backend.isDbms(DBMS.SQLITE): query += " WHERE %s" % condition query += " IN (%s)" % ",".join("'%s'" % unsafeSQLIdentificatorNaming(db) for db in sorted(dbs)) if len(dbs) < 2 and ("%s," % condition) in query: query = query.replace("%s," % condition, "", 1) value = inject.getValue(query, blind=False, time=False) if not isNoneValue(value): value = filter(None, arrayizeValue(value)) if len(value) > 0 and not isListLike(value[0]): value = map(lambda x: (dbs[0], x), value) for db, table in filterPairValues(value): db = safeSQLIdentificatorNaming(db) table = safeSQLIdentificatorNaming(table, True) if db not in kb.data.cachedTables: kb.data.cachedTables[db] = [table] else: kb.data.cachedTables[db].append(table) if not kb.data.cachedTables and isInferenceAvailable() and not conf.direct: for db in dbs: if conf.excludeSysDbs and db in self.excludeDbsList: infoMsg = "skipping system database '%s'" % db logger.info(infoMsg) continue infoMsg = "fetching number of tables for " infoMsg += "database '%s'" % unsafeSQLIdentificatorNaming(db) logger.info(infoMsg) if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.ACCESS): query = rootQuery.blind.count else: query = rootQuery.blind.count % unsafeSQLIdentificatorNaming(db) count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if count == 0: warnMsg = "database '%s' " % unsafeSQLIdentificatorNaming(db) warnMsg += "appears to be empty" logger.warn(warnMsg) continue elif not isNumPosStrValue(count): warnMsg = "unable to retrieve the number of " warnMsg += "tables for database '%s'" % unsafeSQLIdentificatorNaming(db) logger.warn(warnMsg) continue tables = [] plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2) indexRange = getLimitRange(count, plusOne=plusOne) for index in indexRange: if Backend.isDbms(DBMS.SYBASE): query = rootQuery.blind.query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")) elif Backend.getIdentifiedDbms() in (DBMS.MAXDB, DBMS.ACCESS): query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ") elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD): query = rootQuery.blind.query % index else: query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(db), index) table = inject.getValue(query, union=False, error=False) if not isNoneValue(table): kb.hintValue = table table = safeSQLIdentificatorNaming(table, True) tables.append(table) if tables: kb.data.cachedTables[db] = tables else: warnMsg = "unable to retrieve the table names " warnMsg += "for database '%s'" % unsafeSQLIdentificatorNaming(db) logger.warn(warnMsg) if isNoneValue(kb.data.cachedTables): kb.data.cachedTables.clear() if not kb.data.cachedTables: errMsg = "unable to retrieve the table names for any database" if bruteForce is None: logger.error(errMsg) return self.getTables(bruteForce=True) else: raise sqlmapNoneDataException, errMsg else: for db, tables in kb.data.cachedTables.items(): kb.data.cachedTables[db] = sorted(tables) if tables else tables return kb.data.cachedTables
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"): raise SqlmapUserQuitException 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: values = [] tbl = safeSQLIdentificatorNaming(tbl, True) if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD): tbl = tbl.upper() infoMsg = "searching table" if tblConsider == "1": infoMsg += "s like" infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) if dbCond and conf.db and conf.db != CURRENT_DB: _ = 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) else: whereDbsQuery = "" logger.info(infoMsg) tblQuery = "%s%s" % (tblCond, tblCondParam) tblQuery = tblQuery % unsafeSQLIdentificatorNaming(tbl) if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: query = rootQuery.inband.query query = query % (tblQuery + whereDbsQuery) values = inject.getValue(query, blind=False, time=False) if values and Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD): newValues = [] if isinstance(values, basestring): values = [values] for value in values: dbName = "SQLite" if Backend.isDbms(DBMS.SQLITE) else "Firebird" newValues.append(["%s%s" % (dbName, METADB_SUFFIX), value]) values = newValues 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] if not values and isInferenceAvailable() and not conf.direct: if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD): if len(whereDbsQuery) == 0: infoMsg = "fetching number of databases with table" if tblConsider == "1": infoMsg += "s like" infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) logger.info(infoMsg) query = rootQuery.blind.count query = query % (tblQuery + whereDbsQuery) count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if not isNumPosStrValue(count): warnMsg = "no databases have table" if tblConsider == "1": warnMsg += "s like" warnMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) logger.warn(warnMsg) continue indexRange = getLimitRange(count) for index in indexRange: query = rootQuery.blind.query query = query % (tblQuery + whereDbsQuery) query = agent.limitQuery(index, query) foundDb = unArrayizeValue(inject.getValue(query, union=False, error=False)) foundDb = safeSQLIdentificatorNaming(foundDb) if foundDb not in foundTbls: foundTbls[foundDb] = [] if tblConsider == "2": foundTbls[foundDb].append(tbl) if tblConsider == "2": continue else: for db in conf.db.split(","): db = safeSQLIdentificatorNaming(db) if db not in foundTbls: foundTbls[db] = [] else: dbName = "SQLite" if Backend.isDbms(DBMS.SQLITE) else "Firebird" foundTbls["%s%s" % (dbName, METADB_SUFFIX)] = [] for db in foundTbls.keys(): db = safeSQLIdentificatorNaming(db) infoMsg = "fetching number of table" if tblConsider == "1": infoMsg += "s like" infoMsg += " '%s' in database '%s'" % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(db)) logger.info(infoMsg) query = rootQuery.blind.count2 if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD): query = query % unsafeSQLIdentificatorNaming(db) query += " AND %s" % tblQuery count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if not isNumPosStrValue(count): warnMsg = "no table" if tblConsider == "1": warnMsg += "s like" warnMsg += " '%s' " % unsafeSQLIdentificatorNaming(tbl) warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(db) logger.warn(warnMsg) continue indexRange = getLimitRange(count) for index in indexRange: query = rootQuery.blind.query2 if query.endswith("'%s')"): query = query[:-1] + " AND %s)" % tblQuery else: query += " AND %s" % tblQuery if Backend.isDbms(DBMS.FIREBIRD): query = safeStringFormat(query, index) if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD): query = safeStringFormat(query, unsafeSQLIdentificatorNaming(db)) if not Backend.isDbms(DBMS.FIREBIRD): query = agent.limitQuery(index, query) foundTbl = unArrayizeValue(inject.getValue(query, union=False, error=False)) if not isNoneValue(foundTbl): kb.hintValue = foundTbl foundTbl = safeSQLIdentificatorNaming(foundTbl, True) foundTbls[db].append(foundTbl) for db in foundTbls.keys(): if isNoneValue(foundTbls[db]): del foundTbls[db] if not foundTbls: warnMsg = "no databases contain any of the provided tables" logger.warn(warnMsg) return conf.dumper.dbTables(foundTbls) self.dumpFoundTables(foundTbls)
def getTables(self, bruteForce=None): if len(kb.data.cachedTables) > 0: return kb.data.cachedTables self.forceDbmsEnum() if bruteForce is None: 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" logger.error(errMsg) bruteForce = True elif Backend.isDbms(DBMS.ACCESS): try: tables = self.getTables(False) except SqlmapNoneDataException: tables = None if not tables: errMsg = "cannot retrieve table names, " errMsg += "back-end DBMS is Access" logger.error(errMsg) bruteForce = True else: return tables if conf.db == CURRENT_DB: conf.db = self.getCurrentDb() if conf.db and Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB): conf.db = conf.db.upper() if conf.db: dbs = conf.db.split(",") else: dbs = self.getDbs() dbs = [_ for _ in dbs if _ and _.strip()] for db in dbs: dbs[dbs.index(db)] = safeSQLIdentificatorNaming(db) if bruteForce: resumeAvailable = False for db, table in kb.brute.tables: if db == conf.db: resumeAvailable = True break if resumeAvailable and not conf.freshQueries: for db, table in kb.brute.tables: if db == conf.db: if conf.db not in kb.data.cachedTables: kb.data.cachedTables[conf.db] = [table] else: kb.data.cachedTables[conf.db].append(table) return kb.data.cachedTables 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"): raise SqlmapUserQuitException else: return tableExists(paths.COMMON_TABLES) infoMsg = "fetching tables for database" infoMsg += "%s: '%s'" % ("s" if len(dbs) > 1 else "", ", ".join(unsafeSQLIdentificatorNaming(unArrayizeValue(db)) for db in sorted(dbs))) logger.info(infoMsg) rootQuery = queries[Backend.getIdentifiedDbms()].tables if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: query = rootQuery.inband.query condition = rootQuery.inband.condition if 'condition' in rootQuery.inband else None if condition: if not Backend.isDbms(DBMS.SQLITE): query += " WHERE %s" % condition if conf.excludeSysDbs: infoMsg = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(unsafeSQLIdentificatorNaming(db) for db in self.excludeDbsList)) logger.info(infoMsg) query += " IN (%s)" % ",".join("'%s'" % unsafeSQLIdentificatorNaming(db) for db in sorted(dbs) if db not in self.excludeDbsList) else: query += " IN (%s)" % ",".join("'%s'" % unsafeSQLIdentificatorNaming(db) for db in sorted(dbs)) if len(dbs) < 2 and ("%s," % condition) in query: query = query.replace("%s," % condition, "", 1) values = inject.getValue(query, blind=False, time=False) if not isNoneValue(values): values = filter(None, arrayizeValue(values)) if len(values) > 0 and not isListLike(values[0]): values = [(dbs[0], _) for _ in values] for db, table in filterPairValues(values): db = safeSQLIdentificatorNaming(db) table = safeSQLIdentificatorNaming(unArrayizeValue(table), True) if db not in kb.data.cachedTables: kb.data.cachedTables[db] = [table] else: kb.data.cachedTables[db].append(table) if not kb.data.cachedTables and isInferenceAvailable() and not conf.direct: for db in dbs: if conf.excludeSysDbs and db in self.excludeDbsList: infoMsg = "skipping system database '%s'" % unsafeSQLIdentificatorNaming(db) logger.info(infoMsg) continue infoMsg = "fetching number of tables for " infoMsg += "database '%s'" % unsafeSQLIdentificatorNaming(db) logger.info(infoMsg) if Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.ACCESS): query = rootQuery.blind.count else: query = rootQuery.blind.count % unsafeSQLIdentificatorNaming(db) count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if count == 0: warnMsg = "database '%s' " % unsafeSQLIdentificatorNaming(db) warnMsg += "appears to be empty" logger.warn(warnMsg) continue elif not isNumPosStrValue(count): warnMsg = "unable to retrieve the number of " warnMsg += "tables for database '%s'" % unsafeSQLIdentificatorNaming(db) logger.warn(warnMsg) continue tables = [] plusOne = Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2) indexRange = getLimitRange(count, plusOne=plusOne) for index in indexRange: if Backend.isDbms(DBMS.SYBASE): query = rootQuery.blind.query % (db, (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")) elif Backend.getIdentifiedDbms() in (DBMS.MAXDB, DBMS.ACCESS): query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ") elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD): query = rootQuery.blind.query % index elif Backend.isDbms(DBMS.HSQLDB): query = rootQuery.blind.query % (index, unsafeSQLIdentificatorNaming(db)) else: query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(db), index) table = unArrayizeValue(inject.getValue(query, union=False, error=False)) if not isNoneValue(table): kb.hintValue = table table = safeSQLIdentificatorNaming(table, True) tables.append(table) if tables: kb.data.cachedTables[db] = tables else: warnMsg = "unable to retrieve the table names " warnMsg += "for database '%s'" % unsafeSQLIdentificatorNaming(db) logger.warn(warnMsg) if isNoneValue(kb.data.cachedTables): kb.data.cachedTables.clear() if not kb.data.cachedTables: errMsg = "unable to retrieve the table names for any database" if bruteForce is None: logger.error(errMsg) return self.getTables(bruteForce=True) elif not conf.search: raise SqlmapNoneDataException(errMsg) else: for db, tables in kb.data.cachedTables.items(): kb.data.cachedTables[db] = sorted(tables) if tables else tables if kb.data.cachedTables: for db in kb.data.cachedTables.keys(): kb.data.cachedTables[db] = list(set(kb.data.cachedTables[db])) return kb.data.cachedTables
try: conf.dumper.userSettings("database management system users roles", conf.dbmsHandler.getRoles(), "role") except SqlmapNoneDataException, ex: logger.critical(ex) except: raise if conf.getDbs: conf.dumper.dbs(conf.dbmsHandler.getDbs()) if conf.getTables: conf.dumper.dbTables(conf.dbmsHandler.getTables()) if conf.commonTables: conf.dumper.dbTables(tableExists(paths.COMMON_TABLES)) if conf.getSchema: conf.dumper.dbTableColumns(conf.dbmsHandler.getSchema()) if conf.getColumns: conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns()) if conf.getCount: conf.dumper.dbTablesCount(conf.dbmsHandler.getCount()) if conf.commonColumns: conf.dumper.dbTableColumns(columnExists(paths.COMMON_COLUMNS)) if conf.dumpTable: conf.dbmsHandler.dumpTable()
def action(): """ This function exploit the SQL injection on the affected url parameter and extract requested data from the back-end database management system or operating system if possible """ # First of all we have to identify the back-end database management # system to be able to go ahead with the injection setHandler() if not Backend.getDbms() or not conf.dbmsHandler: htmlParsed = Format.getErrorParsedDBMSes() errMsg = "sqlmap was not able to fingerprint the " errMsg += "back-end database management system" if htmlParsed: errMsg += ", but from the HTML error page it was " errMsg += "possible to determinate that the " errMsg += "back-end DBMS is %s" % htmlParsed if htmlParsed and htmlParsed.lower() in SUPPORTED_DBMS: errMsg += ". Do not specify the back-end DBMS manually, " errMsg += "sqlmap will fingerprint the DBMS for you" elif kb.nullConnection: errMsg += ". You can try to rerun without using optimization " errMsg += "switch '%s'" % ("-o" if conf.optimize else "--null-connection") else: errMsg += ". Support for this DBMS will be implemented at " errMsg += "some point" raise sqlmapUnsupportedDBMSException, errMsg dataToStdout("%s\n" % conf.dbmsHandler.getFingerprint()) # Enumeration options if conf.getBanner: conf.dumper.banner(conf.dbmsHandler.getBanner()) if conf.getCurrentUser: conf.dumper.currentUser(conf.dbmsHandler.getCurrentUser()) if conf.getCurrentDb: conf.dumper.currentDb(conf.dbmsHandler.getCurrentDb()) if conf.isDba: conf.dumper.dba(conf.dbmsHandler.isDba()) if conf.getUsers: conf.dumper.users(conf.dbmsHandler.getUsers()) if conf.getPasswordHashes: conf.dumper.userSettings("database management system users password hashes", conf.dbmsHandler.getPasswordHashes(), "password hash") if conf.getPrivileges: conf.dumper.userSettings("database management system users privileges", conf.dbmsHandler.getPrivileges(), "privilege") if conf.getRoles: conf.dumper.userSettings("database management system users roles", conf.dbmsHandler.getRoles(), "role") if conf.getDbs: conf.dumper.dbs(conf.dbmsHandler.getDbs()) if conf.getTables: conf.dumper.dbTables(conf.dbmsHandler.getTables()) if conf.commonTables: conf.dumper.dbTables(tableExists(paths.COMMON_TABLES)) if conf.getSchema: conf.dumper.dbTableColumns(conf.dbmsHandler.getSchema()) if conf.getColumns: conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns()) if conf.getCount: conf.dumper.dbTablesCount(conf.dbmsHandler.getCount()) if conf.commonColumns: conf.dumper.dbTableColumns(columnExists(paths.COMMON_COLUMNS)) if conf.dumpTable: conf.dbmsHandler.dumpTable() if conf.dumpAll: conf.dbmsHandler.dumpAll() if conf.search: conf.dbmsHandler.search() if conf.query: conf.dumper.query(conf.query, conf.dbmsHandler.sqlQuery(conf.query)) if conf.sqlShell: conf.dbmsHandler.sqlShell() # User-defined function options if conf.udfInject: conf.dbmsHandler.udfInjectCustom() # File system options if conf.rFile: conf.dumper.rFile(conf.rFile, conf.dbmsHandler.readFile(conf.rFile)) if conf.wFile: conf.dbmsHandler.writeFile(conf.wFile, conf.dFile, conf.wFileType) # Operating system options if conf.osCmd: conf.dbmsHandler.osCmd() if conf.osShell: conf.dbmsHandler.osShell() if conf.osPwn: conf.dbmsHandler.osPwn() if conf.osSmb: conf.dbmsHandler.osSmb() if conf.osBof: conf.dbmsHandler.osBof() # Windows registry options if conf.regRead: conf.dumper.registerValue(conf.dbmsHandler.regRead()) if conf.regAdd: conf.dbmsHandler.regAdd() if conf.regDel: conf.dbmsHandler.regDel() # Miscellaneous options if conf.cleanup: conf.dbmsHandler.cleanup() if conf.direct: conf.dbmsConnector.close()
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"): raise SqlmapUserQuitException 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: values = [] tbl = safeSQLIdentificatorNaming(tbl, True) if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD): tbl = tbl.upper() infoMsg = "searching table" if tblConsider == "1": infoMsg += "s like" infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) if dbCond and conf.db and conf.db != CURRENT_DB: _ = 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) else: whereDbsQuery = "" logger.info(infoMsg) tblQuery = "%s%s" % (tblCond, tblCondParam) tblQuery = tblQuery % unsafeSQLIdentificatorNaming(tbl) if any( isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: query = rootQuery.inband.query query = query % (tblQuery + whereDbsQuery) values = inject.getValue(query, blind=False, time=False) if values and Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD): newValues = [] if isinstance(values, basestring): values = [values] for value in values: dbName = "SQLite" if Backend.isDbms( DBMS.SQLITE) else "Firebird" newValues.append( ["%s%s" % (dbName, METADB_SUFFIX), value]) values = newValues 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] if not values and isInferenceAvailable() and not conf.direct: if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD): if len(whereDbsQuery) == 0: infoMsg = "fetching number of databases with table" if tblConsider == "1": infoMsg += "s like" infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) logger.info(infoMsg) query = rootQuery.blind.count query = query % (tblQuery + whereDbsQuery) count = inject.getValue( query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if not isNumPosStrValue(count): warnMsg = "no databases have table" if tblConsider == "1": warnMsg += "s like" warnMsg += " '%s'" % unsafeSQLIdentificatorNaming( tbl) logger.warn(warnMsg) continue indexRange = getLimitRange(count) for index in indexRange: query = rootQuery.blind.query query = query % (tblQuery + whereDbsQuery) query = agent.limitQuery(index, query) foundDb = unArrayizeValue( inject.getValue(query, union=False, error=False)) foundDb = safeSQLIdentificatorNaming(foundDb) if foundDb not in foundTbls: foundTbls[foundDb] = [] if tblConsider == "2": foundTbls[foundDb].append(tbl) if tblConsider == "2": continue else: for db in conf.db.split(",") if conf.db else ( self.getCurrentDb(), ): db = safeSQLIdentificatorNaming(db) if db not in foundTbls: foundTbls[db] = [] else: dbName = "SQLite" if Backend.isDbms( DBMS.SQLITE) else "Firebird" foundTbls["%s%s" % (dbName, METADB_SUFFIX)] = [] for db in foundTbls.keys(): db = safeSQLIdentificatorNaming(db) infoMsg = "fetching number of table" if tblConsider == "1": infoMsg += "s like" infoMsg += " '%s' in database '%s'" % ( unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(db)) logger.info(infoMsg) query = rootQuery.blind.count2 if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD): query = query % unsafeSQLIdentificatorNaming(db) query += " AND %s" % tblQuery count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if not isNumPosStrValue(count): warnMsg = "no table" if tblConsider == "1": warnMsg += "s like" warnMsg += " '%s' " % unsafeSQLIdentificatorNaming(tbl) warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming( db) logger.warn(warnMsg) continue indexRange = getLimitRange(count) for index in indexRange: query = rootQuery.blind.query2 if query.endswith("'%s')"): query = query[:-1] + " AND %s)" % tblQuery else: query += " AND %s" % tblQuery if Backend.isDbms(DBMS.FIREBIRD): query = safeStringFormat(query, index) if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD): query = safeStringFormat( query, unsafeSQLIdentificatorNaming(db)) if not Backend.isDbms(DBMS.FIREBIRD): query = agent.limitQuery(index, query) foundTbl = unArrayizeValue( inject.getValue(query, union=False, error=False)) if not isNoneValue(foundTbl): kb.hintValue = foundTbl foundTbl = safeSQLIdentificatorNaming( foundTbl, True) foundTbls[db].append(foundTbl) for db in foundTbls.keys(): if isNoneValue(foundTbls[db]): del foundTbls[db] if not foundTbls: warnMsg = "no databases contain any of the provided tables" logger.warn(warnMsg) return conf.dumper.dbTables(foundTbls) self.dumpFoundTables(foundTbls)
def action(): """ This function exploit the SQL injection on the affected url parameter and extract requested data from the back-end database management system or operating system if possible """ # First of all we have to identify the back-end database management # system to be able to go ahead with the injection setHandler() if not Backend.getDbms() or not conf.dbmsHandler: htmlParsed = Format.getErrorParsedDBMSes() errMsg = "sqlmap was not able to fingerprint the " errMsg += "back-end database management system" if htmlParsed: errMsg += ", but from the HTML error page it was " errMsg += "possible to determinate that the " errMsg += "back-end DBMS is %s" % htmlParsed if htmlParsed and htmlParsed.lower() in SUPPORTED_DBMS: errMsg += ". Do not specify the back-end DBMS manually, " errMsg += "sqlmap will fingerprint the DBMS for you" elif kb.nullConnection: errMsg += ". You can try to rerun without using optimization " errMsg += "switch '%s'" % ("-o" if conf.optimize else "--null-connection") else: errMsg += ". Support for this DBMS will be implemented at " errMsg += "some point" raise sqlmapUnsupportedDBMSException, errMsg dataToStdout("%s\n" % conf.dbmsHandler.getFingerprint()) # Enumeration options if conf.getBanner: conf.dumper.banner(conf.dbmsHandler.getBanner()) if conf.getCurrentUser: conf.dumper.currentUser(conf.dbmsHandler.getCurrentUser()) if conf.getCurrentDb: conf.dumper.currentDb(conf.dbmsHandler.getCurrentDb()) if conf.isDba: conf.dumper.dba(conf.dbmsHandler.isDba()) if conf.getUsers: conf.dumper.users(conf.dbmsHandler.getUsers()) if conf.getPasswordHashes: conf.dumper.userSettings( "database management system users password hashes", conf.dbmsHandler.getPasswordHashes(), "password hash") if conf.getPrivileges: conf.dumper.userSettings("database management system users privileges", conf.dbmsHandler.getPrivileges(), "privilege") if conf.getRoles: conf.dumper.userSettings("database management system users roles", conf.dbmsHandler.getRoles(), "role") if conf.getDbs: conf.dumper.dbs(conf.dbmsHandler.getDbs()) if conf.getTables: conf.dumper.dbTables(conf.dbmsHandler.getTables()) if conf.commonTables: conf.dumper.dbTables(tableExists(paths.COMMON_TABLES)) if conf.getColumns: conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns()) if conf.commonColumns: conf.dumper.dbTableColumns(columnExists(paths.COMMON_COLUMNS)) if conf.dumpTable: conf.dumper.dbTableValues(conf.dbmsHandler.dumpTable()) if conf.dumpAll: conf.dbmsHandler.dumpAll() if conf.search: conf.dbmsHandler.search() if conf.query: conf.dumper.query(conf.query, conf.dbmsHandler.sqlQuery(conf.query)) if conf.sqlShell: conf.dbmsHandler.sqlShell() # User-defined function options if conf.udfInject: conf.dbmsHandler.udfInjectCustom() # File system options if conf.rFile: conf.dumper.rFile(conf.rFile, conf.dbmsHandler.readFile(conf.rFile)) if conf.wFile: conf.dbmsHandler.writeFile(conf.wFile, conf.dFile, conf.wFileType) # Operating system options if conf.osCmd: conf.dbmsHandler.osCmd() if conf.osShell: conf.dbmsHandler.osShell() if conf.osPwn: conf.dbmsHandler.osPwn() if conf.osSmb: conf.dbmsHandler.osSmb() if conf.osBof: conf.dbmsHandler.osBof() # Windows registry options if conf.regRead: conf.dumper.registerValue(conf.dbmsHandler.regRead()) if conf.regAdd: conf.dbmsHandler.regAdd() if conf.regDel: conf.dbmsHandler.regDel() # Miscellaneous options if conf.cleanup: conf.dbmsHandler.cleanup() if conf.direct: conf.dbmsConnector.close()
try: conf.dumper.userSettings("database management system users roles", conf.dbmsHandler.getRoles(), "role") except sqlmapNoneDataException, ex: logger.critical(ex) except: raise if conf.getDbs: conf.dumper.dbs(conf.dbmsHandler.getDbs()) if conf.getTables: conf.dumper.dbTables(conf.dbmsHandler.getTables()) if conf.commonTables: conf.dumper.dbTables(tableExists(paths.COMMON_TABLES)) if conf.getSchema: conf.dumper.dbTableColumns(conf.dbmsHandler.getSchema()) if conf.getColumns: conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns()) if conf.getCount: conf.dumper.dbTablesCount(conf.dbmsHandler.getCount()) if conf.commonColumns: conf.dumper.dbTableColumns(columnExists(paths.COMMON_COLUMNS)) if conf.dumpTable: conf.dbmsHandler.dumpTable()
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"): raise sqlmapUserQuitException 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 whereDbsQuery = "" tblConsider, tblCondParam = self.likeOrExact("table") for tbl in tblList: tbl = safeSQLIdentificatorNaming(tbl, True) if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): tbl = tbl.upper() infoMsg = "searching table" if tblConsider == "1": infoMsg += "s like" infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) if conf.db and conf.db != CURRENT_DB: _ = 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) logger.info(infoMsg) tblQuery = "%s%s" % (tblCond, tblCondParam) tblQuery = tblQuery % tbl if any( isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: query = rootQuery.inband.query query += tblQuery query += whereDbsQuery values = inject.getValue(query, blind=False) 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] else: infoMsg = "fetching number of databases with table" if tblConsider == "1": infoMsg += "s like" infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) logger.info(infoMsg) query = rootQuery.blind.count query += tblQuery query += whereDbsQuery count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if not isNumPosStrValue(count): warnMsg = "no databases have table" if tblConsider == "1": warnMsg += "s like" warnMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) logger.warn(warnMsg) continue indexRange = getLimitRange(count) for index in indexRange: query = rootQuery.blind.query query += tblQuery query += whereDbsQuery if Backend.isDbms(DBMS.DB2): query += ") AS foobar" query = agent.limitQuery(index, query) foundDb = inject.getValue(query, inband=False, error=False) foundDb = safeSQLIdentificatorNaming(foundDb) if foundDb not in foundTbls: foundTbls[foundDb] = [] if tblConsider == "2": foundTbls[foundDb].append(tbl) if tblConsider == "2": continue for db in foundTbls.keys(): db = safeSQLIdentificatorNaming(db) infoMsg = "fetching number of table" if tblConsider == "1": infoMsg += "s like" infoMsg += " '%s' in database '%s'" % ( unsafeSQLIdentificatorNaming(tbl), db) logger.info(infoMsg) query = rootQuery.blind.count2 query = query % unsafeSQLIdentificatorNaming(db) query += " AND %s" % tblQuery count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if not isNumPosStrValue(count): warnMsg = "no table" if tblConsider == "1": warnMsg += "s like" warnMsg += " '%s' " % unsafeSQLIdentificatorNaming(tbl) warnMsg += "in database '%s'" % db logger.warn(warnMsg) continue indexRange = getLimitRange(count) for index in indexRange: query = rootQuery.blind.query2 query = query % unsafeSQLIdentificatorNaming(db) query += " AND %s" % tblQuery query = agent.limitQuery(index, query) foundTbl = inject.getValue(query, inband=False, error=False) kb.hintValue = foundTbl foundTbl = safeSQLIdentificatorNaming(foundTbl, True) foundTbls[db].append(foundTbl) if not foundTbls: warnMsg = "no databases contain any of the provided tables" logger.warn(warnMsg) return conf.dumper.dbTables(foundTbls) self.dumpFoundTables(foundTbls)