def sqlShell(self): infoMsg = "calling %s shell. To quit type " % kb.dbms infoMsg += "'x' or 'q' and press ENTER" logger.info(infoMsg) autoCompletion(sqlShell=True) while True: query = None try: query = raw_input("sql> ") except KeyboardInterrupt: print errMsg = "user aborted" logger.error(errMsg) except EOFError: print errMsg = "exit" logger.error(errMsg) break if not query: continue if query.lower() in ( "x", "q", "exit", "quit" ): break output = self.sqlQuery(query) if output and output != "Quit": dumper.string(query, output) elif output != "Quit": print "No output"
def runCmd(self, cmd): getOutput = None if not self.alwaysRetrieveCmdOutput: message = "do you want to retrieve the command standard " message += "output? [Y/n/a] " getOutput = readInput(message, default="Y") if getOutput in ("a", "A"): self.alwaysRetrieveCmdOutput = True if not getOutput or getOutput in ("y", "Y") or self.alwaysRetrieveCmdOutput: output = self.evalCmd(cmd) if output: dumper.string("command standard output", output) else: print "No output" else: self.execCmd(cmd, forgeCmd=True)
def udfInjectCustom(self): if kb.dbms not in ( "MySQL", "PostgreSQL" ): errMsg = "UDF injection feature is not yet implemented on %s" % kb.dbms raise sqlmapUnsupportedFeatureException(errMsg) stackedTest() if not kb.stackedTest: return self.checkDbmsOs() if self.isDba() == False: warnMsg = "the functionality requested might not work because " warnMsg += "the session user is not a database administrator" logger.warn(warnMsg) if not conf.shLib: msg = "which is the local path of the shared library? " while True: self.udfLocalFile = readInput(msg) if self.udfLocalFile: break else: logger.warn("you need to specify the local path of the shared library") else: self.udfLocalFile = conf.shLib if not os.path.exists(self.udfLocalFile): errMsg = "the specified shared library file does not exist" raise sqlmapFilePathException(errMsg) if not self.udfLocalFile.endswith(".dll") and not self.udfLocalFile.endswith(".so"): errMsg = "shared library file must end with '.dll' or '.so'" raise sqlmapMissingMandatoryOptionException(errMsg) elif self.udfLocalFile.endswith(".so") and kb.os == "Windows": errMsg = "you provided a shared object as shared library, but " errMsg += "the database underlying operating system is Windows" raise sqlmapMissingMandatoryOptionException(errMsg) elif self.udfLocalFile.endswith(".dll") and kb.os == "Linux": errMsg = "you provided a dynamic-link library as shared library, " errMsg += "but the database underlying operating system is Linux" raise sqlmapMissingMandatoryOptionException(errMsg) self.udfSharedLibName = os.path.basename(self.udfLocalFile).split(".")[0] self.udfSharedLibExt = os.path.basename(self.udfLocalFile).split(".")[1] msg = "how many user-defined functions do you want to create " msg += "from the shared library? " while True: udfCount = readInput(msg, default=1) if isinstance(udfCount, str) and udfCount.isdigit(): udfCount = int(udfCount) if udfCount <= 0: logger.info("nothing to inject then") return else: break elif isinstance(udfCount, int): break else: logger.warn("invalid value, only digits are allowed") for x in range(0, udfCount): while True: msg = "what is the name of the UDF number %d? " % (x + 1) udfName = readInput(msg) if udfName: self.udfs[udfName] = {} break else: logger.warn("you need to specify the name of the UDF") if kb.dbms == "MySQL": defaultType = "string" elif kb.dbms == "PostgreSQL": defaultType = "text" self.udfs[udfName]["input"] = [] default = 1 msg = "how many input parameters takes UDF " msg += "'%s'? (default: %d) " % (udfName, default) while True: parCount = readInput(msg, default=default) if isinstance(parCount, str) and parCount.isdigit() and int(parCount) >= 0: parCount = int(parCount) break elif isinstance(parCount, int): break else: logger.warn("invalid value, only digits >= 0 are allowed") for y in range(0, parCount): msg = "what is the data-type of input parameter " msg += "number %d? (default: %s) " % ((y + 1), defaultType) while True: parType = readInput(msg, default=defaultType) if isinstance(parType, str) and parType.isdigit(): logger.warn("you need to specify the data-type of the parameter") else: self.udfs[udfName]["input"].append(parType) break msg = "what is the data-type of the return " msg += "value? (default: %s) " % defaultType while True: retType = readInput(msg, default=defaultType) if isinstance(retType, str) and retType.isdigit(): logger.warn("you need to specify the data-type of the return value") else: self.udfs[udfName]["return"] = retType break self.udfInjectCore(self.udfs) msg = "do you want to call your injected user-defined " msg += "functions now? [Y/n/q] " choice = readInput(msg, default="Y") if choice[0] not in ( "y", "Y" ): self.cleanup(udfDict=self.udfs) return while True: udfList = [] msg = "which UDF do you want to call?" for udf, inpRet in self.udfs.items(): udfList.append(udf) msg += "\n[%d] %s" % (len(udfList), udf) msg += "\n[q] Quit" while True: choice = readInput(msg) if choice and choice[0] in ( "q", "Q" ): break elif isinstance(choice, str) and choice.isdigit() and int(choice) > 0 and int(choice) <= len(udfList): choice = int(choice) break elif isinstance(choice, int) and choice > 0 and choice <= len(udfList): break else: warnMsg = "invalid value, only digits >= 1 and " warnMsg += "<= %d are allowed" % len(udfList) logger.warn(warnMsg) cmd = "" count = 1 udfToCall = udfList[choice - 1] for inp in self.udfs[udfToCall]["input"]: msg = "what is the value of the parameter number " msg += "%d (data-type: %s)? " % (count, inp) while True: parValue = readInput(msg) if parValue: if "int" not in inp and "bool" not in inp: parValue = "'%s'" % parValue cmd += "%s," % parValue break else: logger.warn("you need to specify the value of the parameter") count += 1 cmd = cmd[:-1] msg = "do you want to retrieve the return value of the " msg += "UDF? [Y/n] " choice = readInput(msg, default="Y") if choice[0] in ("y", "Y"): output = self.udfEvalCmd(cmd, udfName=udfToCall) if output: dumper.string("return value", output) else: print "No return value" else: self.udfExecCmd(cmd, udfName=udfToCall, silent=True) msg = "do you want to call this or another injected UDF? [Y/n] " choice = readInput(msg, default="Y") if choice[0] not in ("y", "Y"): break self.cleanup(udfDict=self.udfs)
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 conf.dbmsHandler = setHandler() if not conf.dbmsHandler: htmlParsed = getHtmlErrorFp() 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" else: errMsg += ". Support for this DBMS will be implemented if " errMsg += "you ask, just drop us an email" raise sqlmapUnsupportedDBMSException, errMsg print "%s\n" % conf.dbmsHandler.getFingerprint() # Techniques options if conf.stackedTest: dumper.string("stacked queries support", stackedTest()) if conf.timeTest: dumper.string("time based blind sql injection payload", timeTest()) if (conf.unionUse or conf.unionTest) and not kb.unionPosition: dumper.string("valid union", unionTest()) # Enumeration options if conf.getBanner: dumper.string("banner", conf.dbmsHandler.getBanner()) if conf.getCurrentUser: dumper.string("current user", conf.dbmsHandler.getCurrentUser()) if conf.getCurrentDb: dumper.string("current database", conf.dbmsHandler.getCurrentDb()) if conf.isDba: dumper.string("current user is DBA", conf.dbmsHandler.isDba()) if conf.getUsers: dumper.lister("database management system users", conf.dbmsHandler.getUsers()) if conf.getPasswordHashes: dumper.userSettings( "database management system users password hashes", conf.dbmsHandler.getPasswordHashes(), "password hash" ) if conf.getPrivileges: dumper.userSettings( "database management system users privileges", conf.dbmsHandler.getPrivileges(), "privilege" ) if conf.getDbs: dumper.lister("available databases", conf.dbmsHandler.getDbs()) if conf.getTables: dumper.dbTables(conf.dbmsHandler.getTables()) if conf.getColumns: dumper.dbTableColumns(conf.dbmsHandler.getColumns()) if conf.dumpTable: dumper.dbTableValues(conf.dbmsHandler.dumpTable()) if conf.dumpAll: conf.dbmsHandler.dumpAll() if conf.query: dumper.string(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: dumper.string("%s file saved to" % conf.rFile, conf.dbmsHandler.readFile(conf.rFile), sort=False) 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: dumper.string("Registry key value data", conf.dbmsHandler.regRead()) if conf.regAdd: conf.dbmsHandler.regAdd() if conf.regDel: conf.dbmsHandler.regDel() # Miscellaneous options if conf.cleanup: conf.dbmsHandler.cleanup()
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 conf.dbmsHandler = setHandler() if not conf.dbmsHandler: htmlParsed = getHtmlErrorFp() 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" else: errMsg += ". Support for this DBMS will be implemented if " errMsg += "you ask, just drop us an email" raise sqlmapUnsupportedDBMSException, errMsg print "%s\n" % conf.dbmsHandler.getFingerprint() # Techniques options if conf.stackedTest: dumper.string("stacked queries support", stackedTest()) if conf.timeTest: dumper.string("time based blind sql injection payload", timeTest()) if conf.unionTest: dumper.string("valid union", unionTest()) # Enumeration options if conf.getBanner: dumper.string("banner", conf.dbmsHandler.getBanner()) if conf.getCurrentUser: dumper.string("current user", conf.dbmsHandler.getCurrentUser()) if conf.getCurrentDb: dumper.string("current database", conf.dbmsHandler.getCurrentDb()) if conf.getUsers: dumper.lister("database management system users", conf.dbmsHandler.getUsers()) if conf.getPasswordHashes: dumper.userSettings("database management system users password hashes", conf.dbmsHandler.getPasswordHashes(), "password hash") if conf.getPrivileges: dumper.userSettings("database management system users privileges", conf.dbmsHandler.getPrivileges(), "privilege") if conf.getDbs: dumper.lister("available databases", conf.dbmsHandler.getDbs()) if conf.getTables: dumper.dbTables(conf.dbmsHandler.getTables()) if conf.getColumns: dumper.dbTableColumns(conf.dbmsHandler.getColumns()) if conf.dumpTable: dumper.dbTableValues(conf.dbmsHandler.dumpTable()) if conf.dumpAll: conf.dbmsHandler.dumpAll() if conf.query: dumper.string(conf.query, conf.dbmsHandler.sqlQuery(conf.query)) if conf.sqlShell: conf.dbmsHandler.sqlShell() # File system options if conf.rFile: dumper.string(conf.rFile, conf.dbmsHandler.readFile(conf.rFile)) if conf.wFile: dumper.string(conf.wFile, conf.dbmsHandler.writeFile(conf.wFile)) # Takeover options if conf.osShell: conf.dbmsHandler.osShell()