def getUnicode(value, encoding=None, noneToNull=False): """ Returns the unicode representation of the supplied value >>> getUnicode('test') == u'test' True >>> getUnicode(1) == u'1' True >>> getUnicode(None) == 'None' True """ if noneToNull and value is None: return NULL if isinstance(value, six.text_type): return value elif isinstance(value, six.binary_type): # Heuristics (if encoding not explicitly specified) candidates = filterNone( (encoding, kb.get("pageEncoding") if kb.get("originalPage") else None, conf.get("encoding"), UNICODE_ENCODING, sys.getfilesystemencoding())) if all(_ in value for _ in (b'<', b'>')): pass elif any(_ in value for _ in (b":\\", b'/', b'.')) and b'\n' not in value: candidates = filterNone( (encoding, sys.getfilesystemencoding(), kb.get("pageEncoding") if kb.get("originalPage") else None, UNICODE_ENCODING, conf.get("encoding"))) elif conf.get("encoding") and b'\n' not in value: candidates = filterNone( (encoding, conf.get("encoding"), kb.get("pageEncoding") if kb.get("originalPage") else None, sys.getfilesystemencoding(), UNICODE_ENCODING)) for candidate in candidates: try: return six.text_type(value, candidate) except (UnicodeDecodeError, LookupError): pass try: return six.text_type( value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING) except UnicodeDecodeError: return six.text_type(value, UNICODE_ENCODING, errors="reversible") elif isListLike(value): value = list(getUnicode(_, encoding, noneToNull) for _ in value) return value else: try: return six.text_type(value) except UnicodeDecodeError: return six.text_type( str(value), errors="ignore" ) # encoding ignored for non-basestring instances
def getBytes(value, encoding=None, errors="strict", unsafe=True): """ Returns byte representation of provided Unicode value >>> getBytes(u"foo\\\\x01\\\\x83\\\\xffbar") == b"foo\\x01\\x83\\xffbar" True """ retVal = value if encoding is None: encoding = conf.get("encoding") or UNICODE_ENCODING try: codecs.lookup(encoding) except (LookupError, TypeError): encoding = UNICODE_ENCODING if isinstance(value, six.text_type): if INVALID_UNICODE_PRIVATE_AREA: if unsafe: for char in xrange(0xF0000, 0xF00FF + 1): value = value.replace(_unichr(char), "%s%02x" % (SAFE_HEX_MARKER, char - 0xF0000)) retVal = value.encode(encoding, errors) if unsafe: retVal = re.sub(r"%s([0-9a-f]{2})" % SAFE_HEX_MARKER, lambda _: decodeHex(_.group(1)), retVal) else: retVal = value.encode(encoding, errors) if unsafe: retVal = re.sub(b"\\\\x([0-9a-f]{2})", lambda _: decodeHex(_.group(1)), retVal) return retVal
def exceptionHandledFunction(threadFunction, silent=False): try: threadFunction() except KeyboardInterrupt: kb.threadContinue = False kb.threadException = True raise except Exception, ex: if not silent and kb.get("threadContinue"): logger.error("thread %s: %s" % (threading.currentThread().getName(), ex.message)) if conf.get("verbose") > 1: traceback.print_exc()
def exceptionHandledFunction(threadFunction, silent=False): try: threadFunction() except KeyboardInterrupt: kb.threadContinue = False kb.threadException = True raise except Exception as ex: if not silent and kb.get("threadContinue"): errMsg = ex.message if isinstance(ex, SqlmapBaseException) else "%s: %s" % (type(ex).__name__, ex.message) logger.error("thread %s: '%s'" % (threading.currentThread().getName(), errMsg)) if conf.get("verbose") > 1: traceback.print_exc()
def exceptionHandledFunction(threadFunction, silent=False): try: threadFunction() except KeyboardInterrupt: kb.threadContinue = False kb.threadException = True raise except Exception as ex: from lib.core.common import getSafeExString if not silent and kb.get("threadContinue") and not kb.get("multipleCtrlC") and not isinstance(ex, SqlmapUserQuitException): errMsg = getSafeExString(ex) if isinstance(ex, SqlmapBaseException) else "%s: %s" % (type(ex).__name__, getSafeExString(ex)) logger.error("thread %s: '%s'" % (threading.currentThread().getName(), errMsg)) if conf.get("verbose") > 1 and not isinstance(ex, SqlmapConnectionException): traceback.print_exc()
def setHandler(): """ Detect which is the target web application back-end database management system. """ items = [ (DBMS.MYSQL, MYSQL_ALIASES, MySQLMap, MySQLConn), (DBMS.ORACLE, ORACLE_ALIASES, OracleMap, OracleConn), (DBMS.PGSQL, PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn), (DBMS.MSSQL, MSSQL_ALIASES, MSSQLServerMap, MSSQLServerConn), (DBMS.SQLITE, SQLITE_ALIASES, SQLiteMap, SQLiteConn), (DBMS.ACCESS, ACCESS_ALIASES, AccessMap, AccessConn), (DBMS.FIREBIRD, FIREBIRD_ALIASES, FirebirdMap, FirebirdConn), (DBMS.MAXDB, MAXDB_ALIASES, MaxDBMap, MaxDBConn), (DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn), (DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn), (DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn), (DBMS.H2, H2_ALIASES, H2Map, H2Conn), (DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn), ] _ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else () for _ in items) if _: items.remove(_) items.insert(0, _) for dbms, aliases, Handler, Connector in items: if conf.forceDbms: if conf.forceDbms.lower() not in aliases: continue else: kb.dbms = conf.dbms = conf.forceDbms = dbms if kb.dbmsFilter: if dbms not in kb.dbmsFilter: continue handler = Handler() conf.dbmsConnector = Connector() if conf.direct: exception = None dialect = DBMS_DICT[dbms][3] if dialect: try: sqlalchemy = SQLAlchemy(dialect=dialect) sqlalchemy.connect() if sqlalchemy.connector: conf.dbmsConnector = sqlalchemy except Exception as ex: exception = ex if not dialect or exception: try: conf.dbmsConnector.connect() except Exception as ex: if exception: raise exception else: if not isinstance(ex, NameError): raise else: msg = "support for direct connection to '%s' is not available. " % dbms msg += "Please rerun with '--dependencies'" raise SqlmapConnectionException(msg) if conf.forceDbms == dbms or handler.checkDbms(): if kb.resolutionDbms: conf.dbmsHandler = max(_ for _ in items if _[0] == kb.resolutionDbms)[2]() conf.dbmsHandler._dbms = kb.resolutionDbms else: conf.dbmsHandler = handler conf.dbmsHandler._dbms = dbms break else: conf.dbmsConnector = None # At this point back-end DBMS is correctly fingerprinted, no need # to enforce it anymore Backend.flushForcedDbms()
except (sqlmapConnectionException, sqlmapValueException), errMsg: print kb.threadException = True logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) except: from lib.core.common import unhandledExceptionMessage print kb.threadException = True errMsg = unhandledExceptionMessage() logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) traceback.print_exc() finally: kb.multiThreadMode = False kb.bruteMode = False kb.threadContinue = True kb.threadException = False for lock in kb.locks.values(): if lock.locked_lock(): lock.release() if conf.get("hashDB", None): conf.hashDB.flush(True) if cleanupFunction: cleanupFunction()
def main(): """ Main function of sqlmap when running from command line. """ try: dirtyPatches() checkEnvironment() setPaths(modulePath()) banner() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if checkPipedInput(): conf.batch = True if conf.get("api"): # heavy imports from lib.utils.api import StdDbOut from lib.utils.api import setRestAPILog # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True) init() if not conf.updateAll: # Postponed imports (faster start) if conf.smokeTest: from lib.core.testing import smokeTest os._exitcode = 1 - (smokeTest() or 0) elif conf.vulnTest: from lib.core.testing import vulnTest os._exitcode = 1 - (vulnTest() or 0) elif conf.liveTest: from lib.core.testing import liveTest os._exitcode = 1 - (liveTest() or 0) else: from lib.controller.controller import start if conf.profile and PY2: from lib.core.profiling import profile globals()["start"] = start profile() else: try: start() except Exception as ex: os._exitcode = 1 if "can't start new thread" in getSafeExString(ex): errMsg = "unable to start new threads. Please check OS (u)limits" logger.critical(errMsg) raise SystemExit else: raise except SqlmapUserQuitException: if not conf.batch: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) logger.critical(errMsg) raise SystemExit except KeyboardInterrupt: print() except EOFError: print() errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print() errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() valid = checkIntegrity() if valid is False: errMsg = "code integrity check failed (turning off automatic issue creation). " errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.critical(errMsg) print() dataToStdout(excMsg) raise SystemExit elif any(_ in excMsg for _ in ("tamper/", "waf/")): logger.critical(errMsg) print() dataToStdout(excMsg) raise SystemExit elif any(_ in excMsg for _ in ("ImportError", "Can't find file for module")): errMsg = "invalid runtime environment ('%s')" % excMsg.split("Error: ")[-1].strip() logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("MemoryError", "Cannot allocate memory")): errMsg = "memory exhaustion detected" logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("No space left", "Disk quota exceeded", "Disk full while accessing")): errMsg = "no space left on output device" logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("The paging file is too small",)): errMsg = "no space left for paging file" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("No such file", "_'", "self.get_prog_name()")): errMsg = "corrupted installation detected ('%s'). " % excMsg.strip().split('\n')[-1] errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.critical(errMsg) raise SystemExit elif "Read-only file system" in excMsg: errMsg = "output device is mounted as read-only" logger.critical(errMsg) raise SystemExit elif "OperationalError: disk I/O error" in excMsg: errMsg = "I/O error on output device" logger.critical(errMsg) raise SystemExit elif "Violation of BIDI" in excMsg: errMsg = "invalid URL (violation of Bidi IDNA rule - RFC 5893)" logger.critical(errMsg) raise SystemExit elif "_mkstemp_inner" in excMsg: errMsg = "there has been a problem while accessing temporary files" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("twophase", "sqlalchemy")): errMsg = "please update the 'sqlalchemy' package (>= 1.1.11) " errMsg += "(Reference: https://qiita.com/tkprof/items/7d7b2d00df9c5f16fffe)" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("scramble_caching_sha2", "TypeError")): errMsg = "please downgrade the 'PyMySQL' package (=< 0.8.1) " errMsg += "(Reference: https://github.com/PyMySQL/PyMySQL/issues/700)" logger.critical(errMsg) raise SystemExit elif "must be pinned buffer, not bytearray" in excMsg: errMsg = "error occurred at Python interpreter which " errMsg += "is fixed in 2.7.x. Please update accordingly " errMsg += "(Reference: https://bugs.python.org/issue8104)" logger.critical(errMsg) raise SystemExit elif "can't start new thread" in excMsg: errMsg = "there has been a problem while creating new thread instance. " errMsg += "Please make sure that you are not running too many processes" if not IS_WIN: errMsg += " (or increase the 'ulimit -u' value)" logger.critical(errMsg) raise SystemExit elif "'DictObject' object has no attribute '" in excMsg and all(_ in errMsg for _ in ("(fingerprinted)", "(identified)")): errMsg = "there has been a problem in enumeration. " errMsg += "Because of a considerable chance of false-positive case " errMsg += "you are advised to rerun with switch '--flush-session'" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("pymysql", "configparser")): errMsg = "wrong initialization of pymsql detected (using Python3 dependencies)" logger.critical(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "one of your .pyc files are corrupted%s" % (" ('%s')" % match.group(1) if match else "") errMsg += ". Please delete .pyc files on your system to fix the problem" logger.critical(errMsg) raise SystemExit elif kb.get("dumpKeyboardInterrupt"): raise SystemExit elif any(_ in excMsg for _ in ("Broken pipe",)): raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') if "../" in file_: file_ = re.sub(r"(\.\./)+", '/', file_) else: file_ = file_.lstrip('/') file_ = re.sub(r"/{2,}", '/', file_) excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) if conf.get("api") or not valid: logger.critical("%s\n%s" % (errMsg, excMsg)) else: logger.critical(errMsg) dataToStdout("%s\n" % setColor(excMsg.strip(), level=logging.CRITICAL)) createGithubIssue(errMsg, excMsg) finally: kb.threadContinue = False _ = getDaysFromLastUpdate() if _ > LAST_UPDATE_NAGGING_DAYS: warnMsg = "you haven't updated sqlmap for more than %d days!!!" % _ logger.warn(warnMsg) if conf.get("showTime"): dataToStdout("\n[*] ending @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True) kb.threadException = True if kb.get("tempDir"): for prefix in (MKSTEMP_PREFIX.IPC, MKSTEMP_PREFIX.TESTING, MKSTEMP_PREFIX.COOKIE_JAR, MKSTEMP_PREFIX.BIG_ARRAY): for filepath in glob.glob(os.path.join(kb.tempDir, "%s*" % prefix)): try: os.remove(filepath) except OSError: pass if not filterNone(filepath for filepath in glob.glob(os.path.join(kb.tempDir, '*')) if not any(filepath.endswith(_) for _ in ('.lock', '.exe', '_'))): shutil.rmtree(kb.tempDir, ignore_errors=True) if conf.get("hashDB"): conf.hashDB.flush(True) if conf.get("harFile"): with openFile(conf.harFile, "w+b") as f: json.dump(conf.httpCollector.obtain(), fp=f, indent=4, separators=(',', ': ')) if conf.get("api"): conf.databaseCursor.disconnect() if conf.get("dumper"): conf.dumper.flush() # short delay for thread finalization _ = time.time() while threading.activeCount() > 1 and (time.time() - _) > THREAD_FINALIZATION_TIMEOUT: time.sleep(0.01) if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() conf.disableBanner = True main()
def main(): """ Main function of sqlmap when running from command line. """ try: dirtyPatches() checkEnvironment() setPaths(modulePath()) banner() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if checkPipedInput(): conf.batch = True if conf.get("api"): # heavy imports from lib.utils.api import StdDbOut from lib.utils.api import setRestAPILog # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True) init() if not conf.updateAll: # Postponed imports (faster start) if conf.smokeTest: from lib.core.testing import smokeTest smokeTest() elif conf.liveTest: from lib.core.testing import liveTest liveTest() else: from lib.controller.controller import start if conf.profile: from lib.core.profiling import profile globals()["start"] = start profile() else: try: start() except thread.error as ex: if "can't start new thread" in getSafeExString(ex): errMsg = "unable to start new threads. Please check OS (u)limits" logger.critical(errMsg) raise SystemExit else: raise except SqlmapUserQuitException: if not conf.batch: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) logger.critical(errMsg) raise SystemExit except KeyboardInterrupt: print() except EOFError: print() errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print() errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() valid = checkIntegrity() if valid is False: errMsg = "code integrity check failed (turning off automatic issue creation). " errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.critical(errMsg) print() dataToStdout(excMsg) raise SystemExit elif any(_ in excMsg for _ in ("tamper/", "waf/")): logger.critical(errMsg) print() dataToStdout(excMsg) raise SystemExit elif any(_ in excMsg for _ in ("ImportError", "Can't find file for module")): errMsg = "invalid runtime environment ('%s')" % excMsg.split( "Error: ")[-1].strip() logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("MemoryError", "Cannot allocate memory")): errMsg = "memory exhaustion detected" logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("No space left", "Disk quota exceeded", "Disk full while accessing")): errMsg = "no space left on output device" logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("The paging file is too small", )): errMsg = "no space left for paging file" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("No such file", "_'", "self.get_prog_name()")): errMsg = "corrupted installation detected ('%s'). " % excMsg.strip( ).split('\n')[-1] errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.critical(errMsg) raise SystemExit elif "Read-only file system" in excMsg: errMsg = "output device is mounted as read-only" logger.critical(errMsg) raise SystemExit elif "OperationalError: disk I/O error" in excMsg: errMsg = "I/O error on output device" logger.critical(errMsg) raise SystemExit elif "Violation of BIDI" in excMsg: errMsg = "invalid URL (violation of Bidi IDNA rule - RFC 5893)" logger.critical(errMsg) raise SystemExit elif "_mkstemp_inner" in excMsg: errMsg = "there has been a problem while accessing temporary files" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("twophase", "sqlalchemy")): errMsg = "please update the 'sqlalchemy' package (>= 1.1.11) " errMsg += "(Reference: https://qiita.com/tkprof/items/7d7b2d00df9c5f16fffe)" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("scramble_caching_sha2", "TypeError")): errMsg = "please downgrade the 'PyMySQL' package (=< 0.8.1) " errMsg += "(Reference: https://github.com/PyMySQL/PyMySQL/issues/700)" logger.critical(errMsg) raise SystemExit elif "must be pinned buffer, not bytearray" in excMsg: errMsg = "error occurred at Python interpreter which " errMsg += "is fixed in 2.7.x. Please update accordingly " errMsg += "(Reference: https://bugs.python.org/issue8104)" logger.critical(errMsg) raise SystemExit elif "can't start new thread" in excMsg: errMsg = "there has been a problem while creating new thread instance. " errMsg += "Please make sure that you are not running too many processes" if not IS_WIN: errMsg += " (or increase the 'ulimit -u' value)" logger.critical(errMsg) raise SystemExit elif "'DictObject' object has no attribute '" in excMsg and all( _ in errMsg for _ in ("(fingerprinted)", "(identified)")): errMsg = "there has been a problem in enumeration. " errMsg += "Because of a considerable chance of false-positive case " errMsg += "you are advised to rerun with switch '--flush-session'" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("pymysql", "configparser")): errMsg = "wrong initialization of pymsql detected (using Python3 dependencies)" logger.critical(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "one of your .pyc files are corrupted%s" % ( " ('%s')" % match.group(1) if match else "") errMsg += ". Please delete .pyc files on your system to fix the problem" logger.critical(errMsg) raise SystemExit elif kb.get("dumpKeyboardInterrupt"): raise SystemExit elif any(_ in excMsg for _ in ("Broken pipe", )): raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') if "../" in file_: file_ = re.sub(r"(\.\./)+", '/', file_) else: file_ = file_.lstrip('/') file_ = re.sub(r"/{2,}", '/', file_) excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) if conf.get("api") or not valid: logger.critical("%s\n%s" % (errMsg, excMsg)) else: logger.critical(errMsg) dataToStdout("%s\n" % setColor(excMsg.strip(), level=logging.CRITICAL)) createGithubIssue(errMsg, excMsg) finally: kb.threadContinue = False if conf.get("showTime"): dataToStdout("\n[*] ending @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True) kb.threadException = True if kb.get("tempDir"): for prefix in (MKSTEMP_PREFIX.IPC, MKSTEMP_PREFIX.TESTING, MKSTEMP_PREFIX.COOKIE_JAR, MKSTEMP_PREFIX.BIG_ARRAY): for filepath in glob.glob( os.path.join(kb.tempDir, "%s*" % prefix)): try: os.remove(filepath) except OSError: pass if not filter( None, (filepath for filepath in glob.glob(os.path.join(kb.tempDir, '*')) if not any( filepath.endswith(_) for _ in ('.lock', '.exe', '_')))): shutil.rmtree(kb.tempDir, ignore_errors=True) if conf.get("hashDB"): conf.hashDB.flush(True) if conf.get("harFile"): with openFile(conf.harFile, "w+b") as f: json.dump(conf.httpCollector.obtain(), fp=f, indent=4, separators=(',', ': ')) if conf.get("api"): conf.databaseCursor.disconnect() if conf.get("dumper"): conf.dumper.flush() # short delay for thread finalization _ = time.time() while threading.activeCount() > 1 and ( time.time() - _) > THREAD_FINALIZATION_TIMEOUT: time.sleep(0.01) if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() conf.disableBanner = True main()
def main(): """ Main function of sqlmap when running from command line. """ try: checkEnvironment() setPaths(modulePath()) banner() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if hasattr(conf, "api"): # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: try: start() except thread.error as ex: if "can't start new thread" in getSafeExString(ex): errMsg = "unable to start new threads. Please check OS (u)limits" logger.critical(errMsg) raise SystemExit else: raise except SqlmapUserQuitException: errMsg = "user quit" try: logger.error(errMsg) except KeyboardInterrupt: pass except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) try: logger.critical(errMsg) except KeyboardInterrupt: pass raise SystemExit except KeyboardInterrupt: print errMsg = "user aborted" try: logger.error(errMsg) except KeyboardInterrupt: pass except EOFError: print errMsg = "exit" try: logger.error(errMsg) except KeyboardInterrupt: pass except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() try: if not checkIntegrity(): errMsg = "code integrity check failed (turning off automatic issue creation). " errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.critical(errMsg) print dataToStdout(excMsg) raise SystemExit elif "MemoryError" in excMsg: errMsg = "memory exhaustion detected" logger.error(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("No space left", "Disk quota exceeded")): errMsg = "no space left on output device" logger.error(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("No such file", "_'", "self.get_prog_name()")): errMsg = "corrupted installation detected ('%s'). " % excMsg.strip( ).split('\n')[-1] errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.error(errMsg) raise SystemExit elif "Read-only file system" in excMsg: errMsg = "output device is mounted as read-only" logger.error(errMsg) raise SystemExit elif "OperationalError: disk I/O error" in excMsg: errMsg = "I/O error on output device" logger.error(errMsg) raise SystemExit elif "_mkstemp_inner" in excMsg: errMsg = "there has been a problem while accessing temporary files" logger.error(errMsg) raise SystemExit elif "can't start new thread" in excMsg: errMsg = "there has been a problem while creating new thread instance. " errMsg += "Please make sure that you are not running too many processes" if not IS_WIN: errMsg += " (or increase the 'ulimit -u' value)" logger.error(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("pymysql", "configparser")): errMsg = "wrong initialization of pymsql detected (using Python3 dependencies)" logger.error(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "one of your .pyc files are corrupted%s" % ( " ('%s')" % match.group(1) if match else "") errMsg += ". Please delete .pyc files on your system to fix the problem" logger.error(errMsg) raise SystemExit elif "valueStack.pop" in excMsg and kb.get( "dumpKeyboardInterrupt"): raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) if hasattr(conf, "api"): logger.critical("%s\n%s" % (errMsg, excMsg)) else: logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) except KeyboardInterrupt: pass finally: kb.threadContinue = False if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) kb.threadException = True if kb.get("tempDir"): for prefix in (MKSTEMP_PREFIX.IPC, MKSTEMP_PREFIX.TESTING, MKSTEMP_PREFIX.COOKIE_JAR, MKSTEMP_PREFIX.BIG_ARRAY): for filepath in glob.glob( os.path.join(kb.tempDir, "%s*" % prefix)): try: os.remove(filepath) except OSError: pass if not filter( None, (filepath for filepath in glob.glob(os.path.join(kb.tempDir, '*')) if not any( filepath.endswith(_) for _ in ('.lock', '.exe', '_')))): shutil.rmtree(kb.tempDir, ignore_errors=True) if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if hasattr(conf, "api"): try: conf.databaseCursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() # short delay for thread finalization try: _ = time.time() while threading.activeCount() > 1 and ( time.time() - _) > THREAD_FINALIZATION_TIMEOUT: time.sleep(0.01) except KeyboardInterrupt: pass finally: # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if threading.activeCount() > 1: os._exit(0)
except EOFError: print errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print errMsg = unhandledExceptionMessage() logger.critical(errMsg) traceback.print_exc() finally: dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) kb.threadContinue = False kb.threadException = True if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
print kb.threadException = True logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) except: from lib.core.common import unhandledExceptionMessage print kb.threadException = True errMsg = unhandledExceptionMessage() logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) traceback.print_exc() finally: kb.multiThreadMode = False kb.bruteMode = False kb.threadContinue = True kb.threadException = False for lock in kb.locks.values(): if lock.locked_lock(): lock.release() if conf.get("hashDB", None): conf.hashDB.flush(True) if cleanupFunction: cleanupFunction()
except EOFError: print errMsg = "exit" logger.log(CUSTOM_LOGGING.ERROR, errMsg) except SystemExit: pass except Exception, ex: print print ex #errMsg = unhandledExceptionMessage() #logger.log(CUSTOM_LOGGING.WARNING, errMsg) excMsg = traceback.format_exc() dataToStdout(excMsg) finally: if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X")) kb.threadContinue = False kb.threadException = True if conf.get("threads", 0) > 1: os._exit(0) if __name__ == "__main__": main()
def main(): """ Main function of injection when running from command line. """ try: # paths.SQLMAP_ROOT_PATH = modulePath()#Get current path of sqlmap.py paths.INJECTION_ROOT_PATH= modulePath()#Get current path of sqlmap.py setPaths() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) """ ###Get the options from cmdline command print "-----------------------------------------------------------------" print "--------------------- cmdLineOptions ---------------------------" print cmdLineOptions print "----------------------------------------------------------------" for i in cmdLineOptions.keys() : print i,"---------",cmdLineOptions[i] print "-----------------------------------------------------------------" """ initOptions(cmdLineOptions) # print "----------------------------------" # print kb.chars banner() #Show the banner of the software conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() #According to the input parameters, set the configure of the software start() except SqlmapUserQuitException: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getUnicode(ex.message) logger.critical(errMsg) sys.exit(1) except KeyboardInterrupt: print errMsg = "user aborted" logger.error(errMsg) except EOFError: print errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) finally: if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) kb.threadContinue = False kb.threadException = True # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
def setHandler(): """ Detect which is the target web application back-end database management system. """ items = [ (DBMS.MYSQL, MYSQL_ALIASES, MySQLMap, MySQLConn), (DBMS.ORACLE, ORACLE_ALIASES, OracleMap, OracleConn), (DBMS.PGSQL, PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn), (DBMS.MSSQL, MSSQL_ALIASES, MSSQLServerMap, MSSQLServerConn), (DBMS.SQLITE, SQLITE_ALIASES, SQLiteMap, SQLiteConn), (DBMS.ACCESS, ACCESS_ALIASES, AccessMap, AccessConn), (DBMS.FIREBIRD, FIREBIRD_ALIASES, FirebirdMap, FirebirdConn), (DBMS.MAXDB, MAXDB_ALIASES, MaxDBMap, MaxDBConn), (DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn), (DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn), (DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn), (DBMS.H2, H2_ALIASES, H2Map, H2Conn), (DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn), ] _ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else None for _ in items) if _: items.remove(_) items.insert(0, _) for dbms, aliases, Handler, Connector in items: if conf.forceDbms: if conf.forceDbms.lower() not in aliases: continue else: kb.dbms = conf.dbms = conf.forceDbms = dbms if kb.dbmsFilter: if dbms not in kb.dbmsFilter: continue handler = Handler() conf.dbmsConnector = Connector() if conf.direct: exception = None dialect = DBMS_DICT[dbms][3] if dialect: try: sqlalchemy = SQLAlchemy(dialect=dialect) sqlalchemy.connect() if sqlalchemy.connector: conf.dbmsConnector = sqlalchemy except Exception as ex: exception = ex if not dialect or exception: try: conf.dbmsConnector.connect() except Exception as ex: if exception: raise exception else: if not isinstance(ex, NameError): raise else: msg = "support for direct connection to '%s' is not available. " % dbms msg += "Please rerun with '--dependencies'" raise SqlmapConnectionException(msg) if conf.forceDbms == dbms or handler.checkDbms(): if kb.resolutionDbms: conf.dbmsHandler = max(_ for _ in items if _[0] == kb.resolutionDbms)[2]() conf.dbmsHandler._dbms = kb.resolutionDbms else: conf.dbmsHandler = handler conf.dbmsHandler._dbms = dbms break else: conf.dbmsConnector = None # At this point back-end DBMS is correctly fingerprinted, no need # to enforce it anymore Backend.flushForcedDbms()
def main(): """ Main function of sqlmap when running from command line. """ try: checkEnvironment() setPaths(modulePath()) banner() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if conf.get("api"): # heavy imports from lib.utils.api import StdDbOut from lib.utils.api import setRestAPILog # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: try: start() except thread.error as ex: if "can't start new thread" in getSafeExString(ex): errMsg = "unable to start new threads. Please check OS (u)limits" logger.critical(errMsg) raise SystemExit else: raise except SqlmapUserQuitException: errMsg = "user quit" try: logger.error(errMsg) except KeyboardInterrupt: pass except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) try: logger.critical(errMsg) except KeyboardInterrupt: pass raise SystemExit except KeyboardInterrupt: print errMsg = "user aborted" try: logger.error(errMsg) except KeyboardInterrupt: pass except EOFError: print errMsg = "exit" try: logger.error(errMsg) except KeyboardInterrupt: pass except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() valid = checkIntegrity() try: if valid is False: errMsg = "code integrity check failed (turning off automatic issue creation). " errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.critical(errMsg) print dataToStdout(excMsg) raise SystemExit elif any(_ in excMsg for _ in ("tamper/", "waf/")): logger.critical(errMsg) print dataToStdout(excMsg) raise SystemExit elif "MemoryError" in excMsg: errMsg = "memory exhaustion detected" logger.error(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("No space left", "Disk quota exceeded")): errMsg = "no space left on output device" logger.error(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("No such file", "_'", "self.get_prog_name()")): errMsg = "corrupted installation detected ('%s'). " % excMsg.strip().split('\n')[-1] errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.error(errMsg) raise SystemExit elif "Read-only file system" in excMsg: errMsg = "output device is mounted as read-only" logger.error(errMsg) raise SystemExit elif "OperationalError: disk I/O error" in excMsg: errMsg = "I/O error on output device" logger.error(errMsg) raise SystemExit elif "_mkstemp_inner" in excMsg: errMsg = "there has been a problem while accessing temporary files" logger.error(errMsg) raise SystemExit elif "can't start new thread" in excMsg: errMsg = "there has been a problem while creating new thread instance. " errMsg += "Please make sure that you are not running too many processes" if not IS_WIN: errMsg += " (or increase the 'ulimit -u' value)" logger.error(errMsg) raise SystemExit elif "'DictObject' object has no attribute '" in excMsg and all(_ in errMsg for _ in ("(fingerprinted)", "(identified)")): errMsg = "there has been a problem in enumeration. " errMsg += "Because of a considerable chance of false-positive case " errMsg += "you are advised to rerun with switch '--flush-session'" logger.error(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("pymysql", "configparser")): errMsg = "wrong initialization of pymsql detected (using Python3 dependencies)" logger.error(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "one of your .pyc files are corrupted%s" % (" ('%s')" % match.group(1) if match else "") errMsg += ". Please delete .pyc files on your system to fix the problem" logger.error(errMsg) raise SystemExit elif "valueStack.pop" in excMsg and kb.get("dumpKeyboardInterrupt"): raise SystemExit elif any(_ in excMsg for _ in ("Broken pipe",)): raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) if conf.get("api") or not valid: logger.critical("%s\n%s" % (errMsg, excMsg)) else: logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) except KeyboardInterrupt: pass finally: kb.threadContinue = False if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) kb.threadException = True if kb.get("tempDir"): for prefix in (MKSTEMP_PREFIX.IPC, MKSTEMP_PREFIX.TESTING, MKSTEMP_PREFIX.COOKIE_JAR, MKSTEMP_PREFIX.BIG_ARRAY): for filepath in glob.glob(os.path.join(kb.tempDir, "%s*" % prefix)): try: os.remove(filepath) except OSError: pass if not filter(None, (filepath for filepath in glob.glob(os.path.join(kb.tempDir, '*')) if not any(filepath.endswith(_) for _ in ('.lock', '.exe', '_')))): shutil.rmtree(kb.tempDir, ignore_errors=True) if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if conf.get("harFile"): with openFile(conf.harFile, "w+b") as f: json.dump(conf.httpCollector.obtain(), fp=f, indent=4, separators=(',', ': ')) if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if conf.get("api"): try: conf.databaseCursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() # short delay for thread finalization try: _ = time.time() while threading.activeCount() > 1 and (time.time() - _) > THREAD_FINALIZATION_TIMEOUT: time.sleep(0.01) except KeyboardInterrupt: pass finally: # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if threading.activeCount() > 1: os._exit(0)
def main(): """ Main function of sqlmap when running from command line. http://python.usyiyi.cn/ http://blog.csdn.net/pipisorry/article/details/39909057/ python异常类型:http://www.cnblogs.com/zhangpengshou/p/3565087.html """ try: checkEnvironment() # 检查系统环境 setPaths() # 设置路径 banner() # 打印sqlmap标识信息 ''' cmdLineParser()解析命令行参数 ''' # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if hasattr(conf, "api"): # hasattr用于确定一个对象是否具有某一个属性 ''' 语法: hasattr(object,name)->bool 判断object中是否有name属性,返回一个布尔值,如果有name属性,则返回为True,否则返回为False ''' # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() # 初始化环境信息 if conf.profile: profile() # sqlmap程序运行时的环境信息 elif conf.smokeTest: smokeTest() # 冒烟测试 elif conf.liveTest: liveTest() # 存活测试 else: try: start() # 检测开始的地方,start()函数位于controller.py中 except thread.error as ex: if "can't start new thread" in getSafeExString(ex): errMsg = "unable to start new threads. Please check OS (u)limits" logger.critical(errMsg) raise SystemExit else: raise except SqlmapUserQuitException: errMsg = "user quit" try: logger.error(errMsg) ''' os._exit() 直接退出 Python 解释器,其后的代码都不执行。 sys.exit() 引发一个 SystemExit 异常,没有捕获这个异常,会直接退出;捕获这个异常可以做一些额外的清理工作。 exit() 跟 C 语言等其他语言的 exit() 应该是一样的。 Python退出程序的方式有两种:os._exit(), sys.exit() 1)os._exit() 直接退出 Python程序,其后的代码也不会继续执行。 2)sys.exit() 引发一个 SystemExit异常,若没有捕获这个异常,Python解释器会直接退出;捕获这个异常可以做一些额外的清理工作。0为正常退出,其他数值(1-127)为不正常,可抛异常事件供捕获。 3) exit() 跟 C 语言等其他语言的 exit() 应该是一样的。 os._exit() 调用 C 语言的 _exit() 函数。 __builtin__.exit 是一个 Quitter 对象,这个对象的 __call__ 方法会抛出一个 SystemExit 异常。 一般来说 os._exit() 用于在线程中退出 sys.exit() 用于在主线程中退出。 ''' except KeyboardInterrupt: # Ctrl+C被按下 pass except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) try: logger.critical(errMsg) except KeyboardInterrupt: # Ctrl+C被按下 pass raise SystemExit except KeyboardInterrupt: # Ctrl+C被按下 print errMsg = "user aborted" try: logger.error(errMsg) except KeyboardInterrupt: # Ctrl+C被按下 pass except EOFError: # 遇到文件末尾引发的异常 print errMsg = "exit" try: logger.error(errMsg) except KeyboardInterrupt: # Ctrl+C被按下 pass except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() try: if any(_ in excMsg for _ in ("No space left", "Disk quota exceeded")): errMsg = "no space left on output device" logger.error(errMsg) raise SystemExit elif "_mkstemp_inner" in excMsg: errMsg = "there has been a problem while accessing temporary files" logger.error(errMsg) raise SystemExit elif "can't start new thread" in excMsg: errMsg = "there has been a problem while creating new thread instance. " errMsg += "Please make sure that you are not running too many processes" if not IS_WIN: errMsg += " (or increase the 'ulimit -u' value)" logger.error(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("pymysql", "configparser")): errMsg = "wrong initialization of pymsql detected (using Python3 dependencies)" logger.error(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "one of your .pyc files are corrupted%s" % (" ('%s')" % match.group(1) if match else "") errMsg += ". Please delete .pyc files on your system to fix the problem" logger.error(errMsg) raise SystemExit elif "valueStack.pop" in excMsg and kb.get("dumpKeyboardInterrupt"): raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) if hasattr(conf, "api"): logger.critical("%s\n%s" % (errMsg, excMsg)) else: logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) except KeyboardInterrupt: # Ctrl+C被按下 pass finally: kb.threadContinue = False kb.threadException = True if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) ''' 返回所有匹配的文件路径列表。例如, >>> import glob >>> print glob.glob(r'*.py') ['sqlmap.py', 'sqlmapapi.py'] >>> print glob.glob(r'*.py'); ['sqlmap.py', 'sqlmapapi.py'] >>> print glob.glob(r'E:\SQLMap\*.py') ['E:\\SQLMap\\sqlmap.py', 'E:\\SQLMap\\sqlmapapi.py'] >>> ''' if kb.get("tempDir"): #kb是一个字典 for prefix in (MKSTEMP_PREFIX.IPC, MKSTEMP_PREFIX.TESTING, MKSTEMP_PREFIX.COOKIE_JAR, MKSTEMP_PREFIX.BIG_ARRAY): for filepath in glob.glob(os.path.join(kb.tempDir, "%s*" % prefix)): try: os.remove(filepath) except OSError: pass if not filter(None, (filepath for filepath in glob.glob(os.path.join(kb.tempDir, '*')) if not any(filepath.endswith(_) for _ in ('.lock', '.exe', '_')))): shutil.rmtree(kb.tempDir, ignore_errors=True) if conf.get("hashDB"): #conf是一个字典 try: conf.hashDB.flush(True) except KeyboardInterrupt: # Ctrl+C被按下 pass if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if hasattr(conf, "api"): try: conf.database_cursor.disconnect() except KeyboardInterrupt: # Ctrl+C被按下 pass if conf.get("dumper"): conf.dumper.flush() # short delay for thread finalization try: _ = time.time() while threading.activeCount() > 1 and (time.time() - _) > THREAD_FINALIZATION_TIMEOUT: time.sleep(0.01) except KeyboardInterrupt: # Ctrl+C被按下 pass # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if threading.activeCount() > 1: os._exit(0)
def main(): """ Main function of sqlmap when running from command line. """ try: paths.SQLMAP_ROOT_PATH = modulePath() setPaths() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if hasattr(conf, "api"): # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() banner() dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: start() except SqlmapUserQuitException: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapBaseException as e: e = getUnicode(e) logger.critical(e) sys.exit(1) except KeyboardInterrupt: print errMsg = "user aborted" logger.error(errMsg) except EOFError: print errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print errMsg = unhandledExceptionMessage() logger.critical(errMsg) traceback.print_exc() finally: dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) kb.threadContinue = False kb.threadException = True if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if hasattr(conf, "api"): try: conf.database_cursor.disconnect() except KeyboardInterrupt: pass # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
def setHandler(): """ Detect which is the target web application back-end database management system. """ items = [ (DBMS.MYSQL, MYSQL_ALIASES, MySQLMap, MySQLConn), (DBMS.ORACLE, ORACLE_ALIASES, OracleMap, OracleConn), (DBMS.PGSQL, PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn), (DBMS.MSSQL, MSSQL_ALIASES, MSSQLServerMap, MSSQLServerConn), (DBMS.SQLITE, SQLITE_ALIASES, SQLiteMap, SQLiteConn), (DBMS.ACCESS, ACCESS_ALIASES, AccessMap, AccessConn), (DBMS.FIREBIRD, FIREBIRD_ALIASES, FirebirdMap, FirebirdConn), (DBMS.MAXDB, MAXDB_ALIASES, MaxDBMap, MaxDBConn), (DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn), (DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn), (DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn), (DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn), ] _ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else None for _ in items) if _: items.remove(_) items.insert(0, _) for dbms, aliases, Handler, Connector in items: handler = Handler() conf.dbmsConnector = Connector() if conf.direct: dialect = DBMS_DICT[dbms][3] if dialect: sqlalchemy = SQLAlchemy(dialect=dialect) sqlalchemy.connect() if sqlalchemy.connector: conf.dbmsConnector = sqlalchemy else: try: conf.dbmsConnector.connect() except NameError: pass else: conf.dbmsConnector.connect() if handler.checkDbms(): if kb.resolutionDbms: conf.dbmsHandler = max(_ for _ in items if _[0] == kb.resolutionDbms)[2]() else: conf.dbmsHandler = handler conf.dbmsHandler._dbms = dbms break else: conf.dbmsConnector = None # At this point back-end DBMS is correctly fingerprinted, no need # to enforce it anymore Backend.flushForcedDbms()
def main(): """ Main function of sqlmap when running from command line. """ try: paths.SQLMAP_ROOT_PATH = modulePath() setPaths() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if hasattr(conf, "api"): # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() banner() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: start() except SqlmapUserQuitException: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getUnicode(ex.message) logger.critical(errMsg) sys.exit(1) except KeyboardInterrupt: print errMsg = "user aborted" logger.error(errMsg) except EOFError: print errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() for match in re.finditer(r'File "(.+?)", line', excMsg): file = match.group(1).replace('\\', "/") file = file[file.find("sqlmap"):].replace("sqlmap/", "", 1) excMsg = excMsg.replace(match.group(1), file) logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) finally: if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) kb.threadContinue = False kb.threadException = True if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if hasattr(conf, "api"): try: conf.database_cursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
def main(): """ Main function of sqlmap when running from command line. """ try: paths.SQLMAP_ROOT_PATH = modulePath() try: os.path.isdir(paths.SQLMAP_ROOT_PATH) except UnicodeEncodeError: errMsg = "your system does not properly handle non-ASCII paths. " errMsg += "Please move the sqlmap's directory to the other location" logger.error(errMsg) raise SystemExit setPaths() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if hasattr(conf, "api"): # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() banner() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: start() except SqlmapUserQuitException: errMsg = "user quit" try: logger.error(errMsg) except KeyboardInterrupt: pass except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) try: logger.critical(errMsg) except KeyboardInterrupt: pass raise SystemExit except KeyboardInterrupt: print errMsg = "user aborted" try: logger.error(errMsg) except KeyboardInterrupt: pass except EOFError: print errMsg = "exit" try: logger.error(errMsg) except KeyboardInterrupt: pass except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() try: if any(_ in excMsg for _ in ("No space left", "Disk quota exceeded")): errMsg = "no space left on output device" logger.error(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "one of your .pyc files are corrupted%s" % ( " ('%s')" % match.group(1) if match else "") errMsg += ". Please delete .pyc files on your system to fix the problem" logger.error(errMsg) raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) except KeyboardInterrupt: pass finally: kb.threadContinue = False kb.threadException = True if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) if kb.get("tempDir"): shutil.rmtree(kb.tempDir, ignore_errors=True) if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if hasattr(conf, "api"): try: conf.database_cursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
def main(): """ Main function of sqlmap when running from command line. """ try: # cmdLineOptions = { 'code': None, 'getUsers': None, 'getPasswordHashes': None, 'excludeSysDbs': None, 'uChar': None, 'skip': None, 'db': None, 'cpuThrottle': None, 'prefix': None, 'osShell': None, 'googlePage': None, 'query': None, 'getComments': None, 'randomAgent': True, 'delay': None, 'authType': None, 'isDba': None, 'requestFile': None, 'predictOutput': None, 'wizard': None, 'stopFail': None, 'forms': None, 'pivotColumn': None, 'dropSetCookie': None, 'dbmsCred': None, 'risk': None, 'sqlFile': None, 'rParam': None, 'getCurrentUser': None, 'notString': None, 'getRoles': None, 'getPrivileges': None, 'testParameter': None, 'tbl': None, 'trafficFile': None, 'osSmb': None, 'level': None, 'secondOrder': None, 'timeout': None, 'firstChar': None, 'torPort': None, 'wFile': None, 'binaryFields': None, 'checkTor': None, 'commonTables': None, 'direct': None, 'saFreq': None, 'tmpPath': None, 'titles': None, 'getSchema': None, 'timeSec': None, 'paramDel': None, 'regKey': None, 'getColumns': None, 'headers': None, 'authCred': None, 'loadCookies': None, 'dnsName': None, 'showVersion': None, 'outputDir': None, 'osBof': None, 'invalidLogical': None, 'getCurrentDb': None, 'hexConvert': None, 'proxyFile': None, 'answers': None, 'host': None, 'dependencies': None, 'cookie': None, 'rFile': None, 'regexp': None, 'optimize': None, 'limitStop': None, 'search': None, 'uFrom': None, 'noCast': None, 'testFilter': None, 'eta': None, 'csrfToken': None, 'threads': None, 'logFile': None, 'os': None, 'col': None, 'proxy': None, 'proxyCred': None, 'verbose': None, 'crawlDepth': None, 'updateAll': None, 'privEsc': None, 'forceDns': None, 'getAll': None, 'hpp': None, 'url': u'www.cowinbio.com/about/index.php?id=1*', 'invalidBignum': None, 'regType': None, 'getDbs': True, 'freshQueries': None, 'uCols': None, 'smokeTest': None, 'regData': None, 'udfInject': None, 'invalidString': None, 'tor': None, 'forceSSL': None, 'ignore401': None, 'beep': None, 'noEscape': None, 'configFile': None, 'scope': None, 'dumpAll': None, 'torType': None, 'regVal': None, 'ignoreProxy': None, 'mnemonics': None, 'skipUrlEncode': None, 'referer': None, 'agent': None, 'purgeOutput': None, 'retries': None, 'authPrivate': None, 'extensiveFp': None, 'dumpTable': None, 'advancedHelp': None, 'batch': None, 'limitStart': None, 'flushSession': None, 'osCmd': None, 'suffix': None, 'smart': None, 'regDel': None, 'shLib': None, 'sitemapUrl': None, 'identifyWaf': None, 'msfPath': None, 'getHostname': None, 'sessionFile': None, 'saveCmdline': None, 'getTables': None, 'liveTest': None, 'lastChar': None, 'checkWaf': None, 'string': None, 'dbms': None, 'dumpWhere': None, 'tamper': None, 'charset': None, 'runCase': None, 'sqlShell': None, 'osPwn': None, 'evalCode': None, 'cleanup': None, 'csrfUrl': None, 'getBanner': None, 'profile': None, 'regRead': None, 'bulkFile': None, 'safUrl': None, 'csvDel': None, 'excludeCol': None, 'dumpFormat': None, 'alert': None, 'nullConnection': None, 'user': None, 'parseErrors': None, 'getCount': None, 'dFile': None, 'data': None, 'regAdd': None, 'dummy': None, 'sqlmapShell': None, 'mobile': None, 'googleDork': None, 'pickledOptions': None, 'disableColoring': None, 'pageRank': None, 'tech': None, 'textOnly': None, 'cookieDel': None, 'commonColumns': None, 'keepAlive': None} cmdLineOptions = { 'level':6,'risk':3} initOptions(cmdLineOptions) banner() #Show the banner of the software conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() #According to the input parameters, set the configure of the software if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: """ print "------------------------- kb ------------------------------------" kb_info_file = open("kb_info_file","w+") for key in kb.keys(): print >> kb_info_file, key,"-------",kb[key] print "------------------------------------------------------------------" info_file = open("conf_info_file.txt","w+") print "----------------------- conf ----------------------------------" for key in conf.keys(): print >> info_file, key,"------",conf[key] info_file.close() print "------------------------------------------------------------------" """ start() except SqlmapUserQuitException: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getUnicode(ex.message) logger.critical(errMsg) sys.exit(1) except KeyboardInterrupt: print errMsg = "user aborted" logger.error(errMsg) except EOFError: print errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) finally: if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) kb.threadContinue = False kb.threadException = True if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if hasattr(conf, "api"): try: conf.database_cursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
pass except KeyboardInterrupt: raise SqlmapThreadException( "user aborted (Ctrl+C was pressed multiple times)") if forwardException: raise except (SqlmapConnectionException, SqlmapValueException), ex: print kb.threadException = True logger.error("thread %s: %s" % (threading.currentThread().getName(), ex.message)) if conf.get("verbose") > 1: traceback.print_exc() except: from lib.core.common import unhandledExceptionMessage print kb.threadException = True errMsg = unhandledExceptionMessage() logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) traceback.print_exc() finally: kb.multiThreadMode = False kb.bruteMode = False
def _send_output(self, *args, **kwargs): if conf.get("chunked") and "encode_chunked" in kwargs: kwargs["encode_chunked"] = False self.__send_output(*args, **kwargs)
def main(): """ Main function of sqlmap when running from command line. """ try: checkEnvironment() setPaths() banner() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if hasattr(conf, "api"): # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: try: start() except thread.error as ex: if "can't start new thread" in getSafeExString(ex): errMsg = "unable to start new threads. Please check OS (u)limits" logger.critical(errMsg) raise SystemExit else: raise except SqlmapUserQuitException: errMsg = "user quit" try: logger.error(errMsg) except KeyboardInterrupt: pass except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) try: logger.critical(errMsg) except KeyboardInterrupt: pass raise SystemExit except KeyboardInterrupt: print errMsg = "user aborted" try: logger.error(errMsg) except KeyboardInterrupt: pass except EOFError: print errMsg = "exit" try: logger.error(errMsg) except KeyboardInterrupt: pass except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() try: if any(_ in excMsg for _ in ("No space left", "Disk quota exceeded")): errMsg = "no space left on output device" logger.error(errMsg) raise SystemExit elif "_mkstemp_inner" in excMsg: errMsg = "there has been a problem while accessing temporary files" logger.error(errMsg) raise SystemExit elif "can't start new thread" in excMsg: errMsg = "there has been a problem while creating new thread instance. " errMsg += "Please make sure that you are not running too many processes" if not IS_WIN: errMsg += " (or increase the 'ulimit -u' value)" logger.error(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("pymysql", "configparser")): errMsg = "wrong initialization of pymsql detected (using Python3 dependencies)" logger.error(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "one of your .pyc files are corrupted%s" % (" ('%s')" % match.group(1) if match else "") errMsg += ". Please delete .pyc files on your system to fix the problem" logger.error(errMsg) raise SystemExit elif "valueStack.pop" in excMsg and kb.get("dumpKeyboardInterrupt"): raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) if hasattr(conf, "api"): logger.critical("%s\n%s" % (errMsg, excMsg)) else: logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) except KeyboardInterrupt: pass finally: kb.threadContinue = False kb.threadException = True if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) if kb.get("tempDir"): shutil.rmtree(kb.tempDir, ignore_errors=True) if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if hasattr(conf, "api"): try: conf.database_cursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() if threading.activeCount() > 1: logger.debug("short delay for thread finalization") try: time.sleep(0.5) except KeyboardInterrupt: pass # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
def main(): """ Main function of sqlmap when running from command line. """ try: paths.SQLMAP_ROOT_PATH = modulePath() setPaths() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if hasattr(conf, "api"): # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() banner() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: start() except SqlmapUserQuitException: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getUnicode(ex.message) logger.critical(errMsg) sys.exit(1) except KeyboardInterrupt: print errMsg = "user aborted" logger.error(errMsg) except EOFError: print errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) finally: if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) if kb.get("tempDir"): shutil.rmtree(kb.tempDir, ignore_errors=True) kb.threadContinue = False kb.threadException = True if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if hasattr(conf, "api"): try: conf.database_cursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardException=True, threadChoice=False, startThreadMsg=True): threads = [] kb.multipleCtrlC = False kb.threadContinue = True kb.threadException = False kb.technique = ThreadData.technique kb.multiThreadMode = False try: if threadChoice and conf.threads == numThreads == 1 and not ( kb.injection.data and not any(_ not in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED) for _ in kb.injection.data)): while True: message = "please enter number of threads? [Enter for %d (current)] " % numThreads choice = readInput(message, default=str(numThreads)) if choice: skipThreadCheck = False if choice.endswith('!'): choice = choice[:-1] skipThreadCheck = True if isDigit(choice): if int( choice ) > MAX_NUMBER_OF_THREADS and not skipThreadCheck: errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS logger.critical(errMsg) else: conf.threads = numThreads = int(choice) break if numThreads == 1: warnMsg = "running in a single-thread mode. This could take a while" logger.warn(warnMsg) if numThreads > 1: if startThreadMsg: infoMsg = "starting %d threads" % numThreads logger.info(infoMsg) else: threadFunction() return kb.multiThreadMode = True # Start the threads for numThread in xrange(numThreads): thread = threading.Thread(target=exceptionHandledFunction, name=str(numThread), args=[threadFunction]) setDaemon(thread) try: thread.start() except Exception as ex: errMsg = "error occurred while starting new thread ('%s')" % ex logger.critical(errMsg) break threads.append(thread) # And wait for them to all finish alive = True while alive: alive = False for thread in threads: if thread.is_alive(): alive = True time.sleep(0.1) except (KeyboardInterrupt, SqlmapUserQuitException) as ex: print() kb.prependFlag = False kb.threadContinue = False kb.threadException = True if kb.lastCtrlCTime and (time.time() - kb.lastCtrlCTime < 1): kb.multipleCtrlC = True raise SqlmapUserQuitException( "user aborted (Ctrl+C was pressed multiple times)") kb.lastCtrlCTime = time.time() if numThreads > 1: logger.info("waiting for threads to finish%s" % (" (Ctrl+C was pressed)" if isinstance( ex, KeyboardInterrupt) else "")) try: while (threading.active_count() > 1): pass except KeyboardInterrupt: kb.multipleCtrlC = True raise SqlmapThreadException( "user aborted (Ctrl+C was pressed multiple times)") if forwardException: raise except (SqlmapConnectionException, SqlmapValueException) as ex: print() kb.threadException = True logger.error("thread %s: '%s'" % (threading.currentThread().getName(), ex)) if conf.get("verbose") > 1 and isinstance(ex, SqlmapValueException): traceback.print_exc() except: print() if not kb.multipleCtrlC: from lib.core.common import unhandledExceptionMessage kb.threadException = True errMsg = unhandledExceptionMessage() logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) traceback.print_exc() finally: kb.multiThreadMode = False kb.threadContinue = True kb.threadException = False kb.technique = None for lock in kb.locks.values(): if lock.locked(): try: lock.release() except: pass if conf.get("hashDB"): conf.hashDB.flush(True) if cleanupFunction: cleanupFunction()
def _setRequestParams(): """ Check and set the parameters and perform checks on 'data' option for HTTP method POST. """ if conf.direct: conf.parameters[None] = "direct connection" return testableParameters = False # Perform checks on GET parameters if conf.parameters.get(PLACE.GET): parameters = conf.parameters[PLACE.GET] paramDict = paramToDict(PLACE.GET, parameters) if paramDict: conf.paramDict[PLACE.GET] = paramDict testableParameters = True # Perform checks on POST parameters if conf.method == HTTPMETHOD.POST and conf.data is None: errMsg = "HTTP POST method depends on HTTP data value to be posted" raise SqlmapSyntaxException(errMsg) if conf.data is not None: conf.method = HTTPMETHOD.POST if not conf.method or conf.method == HTTPMETHOD.GET else conf.method def process(match, repl): retVal = match.group(0) if not (conf.testParameter and match.group("name") not in conf.testParameter): retVal = repl while True: _ = re.search(r"\\g<([^>]+)>", retVal) if _: retVal = retVal.replace( _.group(0), match.group( int(_.group(1)) if _.group(1).isdigit() else _. group(1))) else: break return retVal if kb.processUserMarks is None and CUSTOM_INJECTION_MARK_CHAR in conf.data: message = "custom injection marking character ('%s') found in option " % CUSTOM_INJECTION_MARK_CHAR message += "'--data'. Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException else: kb.processUserMarks = not test or test[0] not in ("n", "N") if not (kb.processUserMarks and CUSTOM_INJECTION_MARK_CHAR in conf.data): if re.search(JSON_RECOGNITION_REGEX, conf.data): message = "JSON data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub( r'("(?P<name>[^"]+)"\s*:\s*"[^"]+)"', functools.partial(process, repl=r'\g<1>%s"' % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub( r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*\b)', functools.partial(process, repl=r'\g<0>%s' % CUSTOM_INJECTION_MARK_CHAR), conf.data) kb.postHint = POST_HINT.JSON elif re.search(JSON_LIKE_RECOGNITION_REGEX, conf.data): message = "JSON-like data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub( r"('(?P<name>[^']+)'\s*:\s*'[^']+)'", functools.partial(process, repl=r"\g<1>%s'" % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub( r"('(?P<name>[^']+)'\s*:\s*)(-?\d[\d\.]*\b)", functools.partial(process, repl=r"\g<0>%s" % CUSTOM_INJECTION_MARK_CHAR), conf.data) kb.postHint = POST_HINT.JSON_LIKE elif re.search(SOAP_RECOGNITION_REGEX, conf.data): message = "SOAP/XML data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub( r"(<(?P<name>[^>]+)( [^<]*)?>)([^<]+)(</\2)", functools.partial(process, repl=r"\g<1>\g<4>%s\g<5>" % CUSTOM_INJECTION_MARK_CHAR), conf.data) kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower( ) else POST_HINT.XML elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data): message = "Multipart like data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub( r"(?si)((Content-Disposition[^\n]+?name\s*=\s*[\"'](?P<name>[^\n]+?)[\"']).+?)(((\r)?\n)+--)", functools.partial(process, repl=r"\g<1>%s\g<4>" % CUSTOM_INJECTION_MARK_CHAR), conf.data) kb.postHint = POST_HINT.MULTIPART if not kb.postHint: if CUSTOM_INJECTION_MARK_CHAR in conf.data: # later processed pass else: place = PLACE.POST conf.parameters[place] = conf.data paramDict = paramToDict(place, conf.data) if paramDict: conf.paramDict[place] = paramDict testableParameters = True else: if CUSTOM_INJECTION_MARK_CHAR not in conf.data: # in case that no usable parameter values has been found conf.parameters[PLACE.POST] = conf.data kb.processUserMarks = True if (kb.postHint and CUSTOM_INJECTION_MARK_CHAR in conf.data) else kb.processUserMarks if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any( place in conf.parameters for place in (PLACE.GET, PLACE.POST) ) and not kb.postHint and not CUSTOM_INJECTION_MARK_CHAR in (conf.data or ""): warnMsg = "you've provided target URL without any GET " warnMsg += "parameters (e.g. www.site.com/article.php?id=1) " warnMsg += "and without providing any POST parameters " warnMsg += "through --data option" logger.warn(warnMsg) message = "do you want to try URI injections " message += "in the target URL itself? [Y/n/q] " test = readInput(message, default="Y") if not test or test[0] not in ("n", "N"): conf.url = "%s%s" % (conf.url, CUSTOM_INJECTION_MARK_CHAR) kb.processUserMarks = True elif test[0] in ("q", "Q"): raise SqlmapUserQuitException for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))): _ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or "" if CUSTOM_INJECTION_MARK_CHAR in _: if kb.processUserMarks is None: lut = { PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data', PLACE.CUSTOM_HEADER: '--headers/--user-agent/--referer/--cookie' } message = "custom injection marking character ('%s') found in option " % CUSTOM_INJECTION_MARK_CHAR message += "'%s'. Do you want to process it? [Y/n/q] " % lut[ place] test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException else: kb.processUserMarks = not test or test[0] not in ("n", "N") if not kb.processUserMarks: if place == PLACE.URI: query = urlparse.urlsplit(value).query if query: parameters = conf.parameters[PLACE.GET] = query paramDict = paramToDict(PLACE.GET, parameters) if paramDict: conf.url = conf.url.split('?')[0] conf.paramDict[PLACE.GET] = paramDict testableParameters = True elif place == PLACE.CUSTOM_POST: conf.parameters[PLACE.POST] = conf.data paramDict = paramToDict(PLACE.POST, conf.data) if paramDict: conf.paramDict[PLACE.POST] = paramDict testableParameters = True else: conf.parameters[place] = value conf.paramDict[place] = OrderedDict() if place == PLACE.CUSTOM_HEADER: for index in xrange(len(conf.httpHeaders)): header, value = conf.httpHeaders[index] if CUSTOM_INJECTION_MARK_CHAR in re.sub( PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value): parts = value.split(CUSTOM_INJECTION_MARK_CHAR) for i in xrange(len(parts) - 1): conf.paramDict[place][ "%s #%d%s" % (header, i + 1, CUSTOM_INJECTION_MARK_CHAR )] = "%s,%s" % (header, "".join( "%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts)))) conf.httpHeaders[index] = ( header, value.replace(CUSTOM_INJECTION_MARK_CHAR, "")) else: parts = value.split(CUSTOM_INJECTION_MARK_CHAR) for i in xrange(len(parts) - 1): conf.paramDict[place]["%s#%d%s" % ( ("%s " % kb.postHint) if kb.postHint else "", i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "".join( "%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts))) if place == PLACE.URI and PLACE.GET in conf.paramDict: del conf.paramDict[PLACE.GET] elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict: del conf.paramDict[PLACE.POST] testableParameters = True if kb.processUserMarks: for item in ("url", "data", "agent", "referer", "cookie"): if conf.get(item): conf[item] = conf[item].replace(CUSTOM_INJECTION_MARK_CHAR, "") # Perform checks on Cookie parameters if conf.cookie: conf.parameters[PLACE.COOKIE] = conf.cookie paramDict = paramToDict(PLACE.COOKIE, conf.cookie) if paramDict: conf.paramDict[PLACE.COOKIE] = paramDict testableParameters = True # Perform checks on header values if conf.httpHeaders: for httpHeader, headerValue in conf.httpHeaders: # Url encoding of the header values should be avoided # Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value httpHeader = httpHeader.title() if httpHeader == HTTP_HEADER.USER_AGENT: conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES))) if condition: conf.paramDict[PLACE.USER_AGENT] = { PLACE.USER_AGENT: headerValue } testableParameters = True elif httpHeader == HTTP_HEADER.REFERER: conf.parameters[PLACE.REFERER] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES))) if condition: conf.paramDict[PLACE.REFERER] = { PLACE.REFERER: headerValue } testableParameters = True elif httpHeader == HTTP_HEADER.HOST: conf.parameters[PLACE.HOST] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES))) if condition: conf.paramDict[PLACE.HOST] = {PLACE.HOST: headerValue} testableParameters = True if not conf.parameters: errMsg = "you did not provide any GET, POST and Cookie " errMsg += "parameter, neither an User-Agent, Referer or Host header value" raise SqlmapGenericException(errMsg) elif not testableParameters: errMsg = "all testable parameters you provided are not present " errMsg += "within the given request data" raise SqlmapGenericException(errMsg)
(threading.currentThread().getName(), ex.message)) except: from lib.core.common import unhandledExceptionMessage print kb.threadException = True errMsg = unhandledExceptionMessage() logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) traceback.print_exc() finally: kb.multiThreadMode = False kb.bruteMode = False kb.threadContinue = True kb.threadException = False for lock in kb.locks.values(): if lock.locked(): try: lock.release() except: pass if conf.get("hashDB"): conf.hashDB.flush(True) if cleanupFunction: cleanupFunction()
try: while (threading.activeCount() > 1): pass except KeyboardInterrupt: raise SqlmapThreadException("user aborted (Ctrl+C was pressed multiple times)") if forwardException: raise except (SqlmapConnectionException, SqlmapValueException), ex: print kb.threadException = True logger.error("thread %s: %s" % (threading.currentThread().getName(), ex.message)) if conf.get("verbose") > 1: traceback.print_exc() except: from lib.core.common import unhandledExceptionMessage print kb.threadException = True errMsg = unhandledExceptionMessage() logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) traceback.print_exc() finally: kb.multiThreadMode = False kb.bruteMode = False kb.threadContinue = True
def _setRequestParams(): """ Check and set the parameters and perform checks on 'data' option for HTTP method POST. """ if conf.direct: conf.parameters[None] = "direct connection" return testableParameters = False # Perform checks on GET parameters if conf.parameters.get(PLACE.GET): parameters = conf.parameters[PLACE.GET] paramDict = paramToDict(PLACE.GET, parameters) if paramDict: conf.paramDict[PLACE.GET] = paramDict testableParameters = True # Perform checks on POST parameters if conf.method == HTTPMETHOD.POST and conf.data is None: errMsg = "HTTP POST method depends on HTTP data value to be posted" raise SqlmapSyntaxException(errMsg) if conf.data is not None: conf.method = HTTPMETHOD.POST def process(match, repl): retVal = match.group(0) if not (conf.testParameter and match.group("name") not in conf.testParameter): retVal = repl while True: _ = re.search(r"\\g<([^>]+)>", retVal) if _: retVal = retVal.replace(_.group(0), match.group(int(_.group(1)) if _.group(1).isdigit() else _.group(1))) else: break return retVal if re.search(JSON_RECOGNITION_REGEX, conf.data): message = "JSON like data found in POST data. " message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*"[^"]+)"', functools.partial(process, repl=r'\g<1>%s"' % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*\b)', functools.partial(process, repl=r'\g<0>%s' % CUSTOM_INJECTION_MARK_CHAR), conf.data) kb.postHint = POST_HINT.JSON elif re.search(SOAP_RECOGNITION_REGEX, conf.data): message = "SOAP/XML like data found in POST data. " message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub(r"(<(?P<name>[^>]+)( [^<]*)?>)([^<]+)(</\2)", functools.partial(process, repl=r"\g<1>\g<4>%s\g<5>" % CUSTOM_INJECTION_MARK_CHAR), conf.data) kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data): message = "Multipart like data found in POST data. " message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub(r"(?si)(Content-Disposition.+?)((\r)?\n--)", r"\g<1>%s\g<2>" % CUSTOM_INJECTION_MARK_CHAR, conf.data) kb.postHint = POST_HINT.MULTIPART if not kb.postHint: if CUSTOM_INJECTION_MARK_CHAR in conf.data: # later processed pass else: place = PLACE.POST conf.parameters[place] = conf.data paramDict = paramToDict(place, conf.data) if paramDict: conf.paramDict[place] = paramDict testableParameters = True else: if CUSTOM_INJECTION_MARK_CHAR not in conf.data: # in case that no usable parameter values has been found conf.parameters[PLACE.POST] = conf.data kb.processUserMarks = True if (kb.postHint and CUSTOM_INJECTION_MARK_CHAR in conf.data) else kb.processUserMarks if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any(place in conf.parameters for place in (PLACE.GET, PLACE.POST)) and not kb.postHint: warnMsg = "you've provided target url without any GET " warnMsg += "parameters (e.g. www.site.com/article.php?id=1) " warnMsg += "and without providing any POST parameters " warnMsg += "through --data option" logger.warn(warnMsg) message = "do you want to try URI injections " message += "in the target url itself? [Y/n/q] " test = readInput(message, default="Y") if not test or test[0] not in ("n", "N"): conf.url = "%s%s" % (conf.url, CUSTOM_INJECTION_MARK_CHAR) kb.processUserMarks = True elif test[0] in ("q", "Q"): raise SqlmapUserQuitException for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))): _ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or "" if CUSTOM_INJECTION_MARK_CHAR in _: if kb.processUserMarks is None: lut = {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data', PLACE.CUSTOM_HEADER: '--headers/--user-agent/--referer/--cookie'} message = "custom injection marking character ('%s') found in option " % CUSTOM_INJECTION_MARK_CHAR message += "'%s'. Do you want to process it? [Y/n/q] " % lut[place] test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException else: kb.processUserMarks = not test or test[0] not in ("n", "N") if not kb.processUserMarks: if place == PLACE.URI: query = urlparse.urlsplit(value).query if query: parameters = conf.parameters[PLACE.GET] = query paramDict = paramToDict(PLACE.GET, parameters) if paramDict: conf.url = conf.url.split('?')[0] conf.paramDict[PLACE.GET] = paramDict testableParameters = True elif place == PLACE.CUSTOM_POST: conf.parameters[PLACE.POST] = conf.data paramDict = paramToDict(PLACE.POST, conf.data) if paramDict: conf.paramDict[PLACE.POST] = paramDict testableParameters = True else: conf.parameters[place] = value conf.paramDict[place] = OrderedDict() if place == PLACE.CUSTOM_HEADER: for index in xrange(len(conf.httpHeaders)): header, value = conf.httpHeaders[index] if CUSTOM_INJECTION_MARK_CHAR in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value): parts = value.split(CUSTOM_INJECTION_MARK_CHAR) for i in xrange(len(parts) - 1): conf.paramDict[place]["%s #%d%s" % (header, i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "%s,%s" % (header, "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts)))) conf.httpHeaders[index] = (header, value.replace(CUSTOM_INJECTION_MARK_CHAR, "")) else: parts = value.split(CUSTOM_INJECTION_MARK_CHAR) for i in xrange(len(parts) - 1): conf.paramDict[place]["%s#%d%s" % (("%s " % kb.postHint) if kb.postHint else "", i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts))) if place == PLACE.URI and PLACE.GET in conf.paramDict: del conf.paramDict[PLACE.GET] elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict: del conf.paramDict[PLACE.POST] testableParameters = True if kb.processUserMarks: for item in ("url", "data", "agent", "referer", "cookie"): if conf.get(item): conf[item] = conf[item].replace(CUSTOM_INJECTION_MARK_CHAR, "") # Perform checks on Cookie parameters if conf.cookie: conf.parameters[PLACE.COOKIE] = conf.cookie paramDict = paramToDict(PLACE.COOKIE, conf.cookie) if paramDict: conf.paramDict[PLACE.COOKIE] = paramDict testableParameters = True # Perform checks on header values if conf.httpHeaders: for httpHeader, headerValue in conf.httpHeaders: # Url encoding of the header values should be avoided # Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value httpHeader = httpHeader.title() if httpHeader == HTTP_HEADER.USER_AGENT: conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES))) if condition: conf.paramDict[PLACE.USER_AGENT] = {PLACE.USER_AGENT: headerValue} testableParameters = True elif httpHeader == HTTP_HEADER.REFERER: conf.parameters[PLACE.REFERER] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES))) if condition: conf.paramDict[PLACE.REFERER] = {PLACE.REFERER: headerValue} testableParameters = True elif httpHeader == HTTP_HEADER.HOST: conf.parameters[PLACE.HOST] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES))) if condition: conf.paramDict[PLACE.HOST] = {PLACE.HOST: headerValue} testableParameters = True if not conf.parameters: errMsg = "you did not provide any GET, POST and Cookie " errMsg += "parameter, neither an User-Agent, Referer or Host header value" raise SqlmapGenericException(errMsg) elif not testableParameters: errMsg = "all testable parameters you provided are not present " errMsg += "within the given request data" raise SqlmapGenericException(errMsg)
def main(): """ Main function of sqlmap when running from command line. """ GLOBALSS.init() s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) port = int(sys.argv[1]) s.bind(("localhost", port)) print(port) s.listen(1) while True: conn, addr = s.accept() GLOBALSS.myList.append(conn) while len(GLOBALSS.myList) > 0: try: paths.SQLMAP_ROOT_PATH = modulePath() try: os.path.isdir(paths.SQLMAP_ROOT_PATH) except UnicodeEncodeError: errMsg = "your system does not properly handle non-ASCII paths. " errMsg += "Please move the sqlmap's directory to the other location" logger.error(errMsg) raise SystemExit setPaths() parser_result = cmdLineParser() # Store original command line options for possible later restoration if parser_result == False: break cmdLineOptions.update(parser_result.__dict__) initOptions(cmdLineOptions) if hasattr(conf, "api"): # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() banner() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: start() except SqlmapUserQuitException: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) logger.critical(errMsg) raise SystemExit except KeyboardInterrupt: print errMsg = "user aborted" logger.error(errMsg) except EOFError: print errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() print(errMsg) print(excMsg) if "No space left" in excMsg: errMsg = "no space left on output device" logger.error(errMsg) raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) finally: if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) if kb.get("tempDir"): shutil.rmtree(kb.tempDir, ignore_errors=True) kb.threadContinue = False kb.threadException = True if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if hasattr(conf, "api"): try: conf.database_cursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
def main(): """ Main function of sqlmap when running from command line. """ try: dirtyPatches() resolveCrossReferences() checkEnvironment() setPaths(modulePath()) banner() # Store original command line options for possible later restoration args = cmdLineParser() cmdLineOptions.update(args.__dict__ if hasattr(args, "__dict__") else args) initOptions(cmdLineOptions) if checkPipedInput(): conf.batch = True if conf.get("api"): # heavy imports from lib.utils.api import StdDbOut from lib.utils.api import setRestAPILog # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True) init() if not conf.updateAll: # Postponed imports (faster start) if conf.smokeTest: from lib.core.testing import smokeTest os._exitcode = 1 - (smokeTest() or 0) elif conf.vulnTest: from lib.core.testing import vulnTest os._exitcode = 1 - (vulnTest() or 0) elif conf.bedTest: from lib.core.testing import bedTest os._exitcode = 1 - (bedTest() or 0) elif conf.fuzzTest: from lib.core.testing import fuzzTest fuzzTest() else: from lib.controller.controller import start if conf.profile and six.PY2: from lib.core.profiling import profile globals()["start"] = start profile() else: try: if conf.crawlDepth and conf.bulkFile: targets = getFileItems(conf.bulkFile) for i in xrange(len(targets)): try: kb.targets.clear() target = targets[i] if not re.search(r"(?i)\Ahttp[s]*://", target): target = "http://%s" % target infoMsg = "starting crawler for target URL '%s' (%d/%d)" % (target, i + 1, len(targets)) logger.info(infoMsg) crawl(target) except Exception as ex: if not isinstance(ex, SqlmapUserQuitException): errMsg = "problem occurred while crawling '%s' ('%s')" % (target, getSafeExString(ex)) logger.error(errMsg) else: raise else: if kb.targets: start() else: start() except Exception as ex: os._exitcode = 1 if "can't start new thread" in getSafeExString(ex): errMsg = "unable to start new threads. Please check OS (u)limits" logger.critical(errMsg) raise SystemExit else: raise except SqlmapUserQuitException: if not conf.batch: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) logger.critical(errMsg) os._exitcode = 1 raise SystemExit except KeyboardInterrupt: print() except EOFError: print() errMsg = "exit" logger.error(errMsg) except SystemExit as ex: os._exitcode = ex.code or 0 except: print() errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() valid = checkIntegrity() os._exitcode = 255 if any(_ in excMsg for _ in ("MemoryError", "Cannot allocate memory")): errMsg = "memory exhaustion detected" logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("No space left", "Disk quota exceeded", "Disk full while accessing")): errMsg = "no space left on output device" logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("The paging file is too small",)): errMsg = "no space left for paging file" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("Access is denied", "subprocess", "metasploit")): errMsg = "permission error occurred while running Metasploit" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("Permission denied", "metasploit")): errMsg = "permission error occurred while using Metasploit" logger.critical(errMsg) raise SystemExit elif "Read-only file system" in excMsg: errMsg = "output device is mounted as read-only" logger.critical(errMsg) raise SystemExit elif "Insufficient system resources" in excMsg: errMsg = "resource exhaustion detected" logger.critical(errMsg) raise SystemExit elif "OperationalError: disk I/O error" in excMsg: errMsg = "I/O error on output device" logger.critical(errMsg) raise SystemExit elif "Violation of BIDI" in excMsg: errMsg = "invalid URL (violation of Bidi IDNA rule - RFC 5893)" logger.critical(errMsg) raise SystemExit elif "Invalid IPv6 URL" in excMsg: errMsg = "invalid URL ('%s')" % excMsg.strip().split('\n')[-1] logger.critical(errMsg) raise SystemExit elif "_mkstemp_inner" in excMsg: errMsg = "there has been a problem while accessing temporary files" logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("tempfile.mkdtemp", "tempfile.mkstemp", "tempfile.py")): errMsg = "unable to write to the temporary directory '%s'. " % tempfile.gettempdir() errMsg += "Please make sure that your disk is not full and " errMsg += "that you have sufficient write permissions to " errMsg += "create temporary files and/or directories" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("twophase", "sqlalchemy")): errMsg = "please update the 'sqlalchemy' package (>= 1.1.11) " errMsg += "(Reference: https://qiita.com/tkprof/items/7d7b2d00df9c5f16fffe)" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("scramble_caching_sha2", "TypeError")): errMsg = "please downgrade the 'PyMySQL' package (=< 0.8.1) " errMsg += "(Reference: https://github.com/PyMySQL/PyMySQL/issues/700)" logger.critical(errMsg) raise SystemExit elif "must be pinned buffer, not bytearray" in excMsg: errMsg = "error occurred at Python interpreter which " errMsg += "is fixed in 2.7. Please update accordingly " errMsg += "(Reference: https://bugs.python.org/issue8104)" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("Resource temporarily unavailable", "os.fork()", "dictionaryAttack")): errMsg = "there has been a problem while running the multiprocessing hash cracking. " errMsg += "Please rerun with option '--threads=1'" logger.critical(errMsg) raise SystemExit elif "can't start new thread" in excMsg: errMsg = "there has been a problem while creating new thread instance. " errMsg += "Please make sure that you are not running too many processes" if not IS_WIN: errMsg += " (or increase the 'ulimit -u' value)" logger.critical(errMsg) raise SystemExit elif "can't allocate read lock" in excMsg: errMsg = "there has been a problem in regular socket operation " errMsg += "('%s')" % excMsg.strip().split('\n')[-1] logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("pymysql", "configparser")): errMsg = "wrong initialization of pymsql detected (using Python3 dependencies)" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("ntlm", "socket.error, err", "SyntaxError")): errMsg = "wrong initialization of python-ntlm detected (using Python2 syntax)" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("drda", "to_bytes")): errMsg = "wrong initialization of drda detected (using Python3 syntax)" logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("window = tkinter.Tk()",)): errMsg = "there has been a problem in initialization of GUI interface " errMsg += "('%s')" % excMsg.strip().split('\n')[-1] logger.critical(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("unable to access item 'liveTest'",)): errMsg = "detected usage of files from different versions of sqlmap" logger.critical(errMsg) raise SystemExit elif kb.get("dumpKeyboardInterrupt"): raise SystemExit elif any(_ in excMsg for _ in ("Broken pipe",)): raise SystemExit elif valid is False: errMsg = "code integrity check failed (turning off automatic issue creation). " errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.critical(errMsg) print() dataToStdout(excMsg) raise SystemExit elif any(_ in excMsg for _ in ("tamper/", "waf/")): logger.critical(errMsg) print() dataToStdout(excMsg) raise SystemExit elif any(_ in excMsg for _ in ("ImportError", "ModuleNotFoundError", "Can't find file for module", "SAXReaderNotAvailable", "source code string cannot contain null bytes", "No module named", "tp_name field")): errMsg = "invalid runtime environment ('%s')" % excMsg.split("Error: ")[-1].strip() logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("SyntaxError: Non-ASCII character", ".py on line", "but no encoding declared")): errMsg = "invalid runtime environment ('%s')" % excMsg.split("Error: ")[-1].strip() logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("No such file", "_'")): errMsg = "corrupted installation detected ('%s'). " % excMsg.strip().split('\n')[-1] errMsg += "You should retrieve the latest development version from official GitHub " errMsg += "repository at '%s'" % GIT_PAGE logger.critical(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("HTTPNtlmAuthHandler", "'str' object has no attribute 'decode'")): errMsg = "package 'python-ntlm' has a known compatibility issue with the " errMsg += "Python 3 (Reference: https://github.com/mullender/python-ntlm/pull/61)" logger.critical(errMsg) raise SystemExit elif "'DictObject' object has no attribute '" in excMsg and all(_ in errMsg for _ in ("(fingerprinted)", "(identified)")): errMsg = "there has been a problem in enumeration. " errMsg += "Because of a considerable chance of false-positive case " errMsg += "you are advised to rerun with switch '--flush-session'" logger.critical(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "one of your .pyc files are corrupted%s" % (" ('%s')" % match.group(1) if match else "") errMsg += ". Please delete .pyc files on your system to fix the problem" logger.critical(errMsg) raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) try: file_ = os.path.relpath(file_, os.path.dirname(__file__)) except ValueError: pass file_ = file_.replace("\\", '/') if "../" in file_: file_ = re.sub(r"(\.\./)+", '/', file_) else: file_ = file_.lstrip('/') file_ = re.sub(r"/{2,}", '/', file_) excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) if conf.get("api") or not valid: logger.critical("%s\n%s" % (errMsg, excMsg)) else: logger.critical(errMsg) dataToStdout("%s\n" % setColor(excMsg.strip(), level=logging.CRITICAL)) createGithubIssue(errMsg, excMsg) finally: kb.threadContinue = False if getDaysFromLastUpdate() > LAST_UPDATE_NAGGING_DAYS: warnMsg = "your sqlmap version is outdated" logger.warn(warnMsg) if conf.get("showTime"): dataToStdout("\n[*] ending @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True) kb.threadException = True if kb.get("tempDir"): for prefix in (MKSTEMP_PREFIX.IPC, MKSTEMP_PREFIX.TESTING, MKSTEMP_PREFIX.COOKIE_JAR, MKSTEMP_PREFIX.BIG_ARRAY): for filepath in glob.glob(os.path.join(kb.tempDir, "%s*" % prefix)): try: os.remove(filepath) except OSError: pass if not filterNone(filepath for filepath in glob.glob(os.path.join(kb.tempDir, '*')) if not any(filepath.endswith(_) for _ in (".lock", ".exe", ".so", '_'))): # ignore junk files try: shutil.rmtree(kb.tempDir, ignore_errors=True) except OSError: pass if conf.get("hashDB"): conf.hashDB.flush(True) if conf.get("harFile"): try: with openFile(conf.harFile, "w+b") as f: json.dump(conf.httpCollector.obtain(), fp=f, indent=4, separators=(',', ': ')) except SqlmapBaseException as ex: errMsg = getSafeExString(ex) logger.critical(errMsg) if conf.get("api"): conf.databaseCursor.disconnect() if conf.get("dumper"): conf.dumper.flush() # short delay for thread finalization _ = time.time() while threading.activeCount() > 1 and (time.time() - _) > THREAD_FINALIZATION_TIMEOUT: time.sleep(0.01) if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() conf.disableBanner = True main()
def main(): """ Main function of sqlmap when running from command line. """ try: paths.SQLMAP_ROOT_PATH = modulePath() try: os.path.isdir(paths.SQLMAP_ROOT_PATH) except UnicodeEncodeError: errMsg = "your system does not properly handle non-ASCII paths. " errMsg += "Please move the sqlmap's directory to the other location" logger.error(errMsg) raise SystemExit setPaths() # Store original command line options for possible later restoration cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if hasattr(conf, "api"): # Overwrite system standard output and standard error to write # to an IPC database sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() banner() conf.showTime = True dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout("[*] starting at %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: start() except SqlmapUserQuitException: errMsg = "user quit" logger.error(errMsg) except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) logger.critical(errMsg) raise SystemExit except KeyboardInterrupt: print errMsg = "user aborted" logger.error(errMsg) except EOFError: print errMsg = "exit" logger.error(errMsg) except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() if any(_ in excMsg for _ in ("No space left", "Disk quota exceeded")): errMsg = "no space left on output device" logger.error(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "one of your .pyc files are corrupted%s" % (" ('%s')" % match.group(1) if match else "") errMsg += ". Please delete .pyc files on your system to fix the problem" logger.error(errMsg) raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", "/") file_ = re.sub(r"\.\./", "/", file_).lstrip("/") excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) finally: if conf.get("showTime"): dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True) if kb.get("tempDir"): shutil.rmtree(kb.tempDir, ignore_errors=True) kb.threadContinue = False kb.threadException = True if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if hasattr(conf, "api"): try: conf.database_cursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if conf.get("threads", 0) > 1 or conf.get("dnsServer"): os._exit(0)
def _setRequestParams(): """ Check and set the parameters and perform checks on 'data' option for HTTP method POST. """ if conf.direct: conf.parameters[None] = "direct connection" return testableParameters = False # Perform checks on GET parameters if conf.parameters.get(PLACE.GET): parameters = conf.parameters[PLACE.GET] paramDict = paramToDict(PLACE.GET, parameters) if paramDict: conf.paramDict[PLACE.GET] = paramDict testableParameters = True # Perform checks on POST parameters if conf.method == HTTPMETHOD.POST and conf.data is None: errMsg = "HTTP POST method depends on HTTP data value to be posted" raise SqlmapSyntaxException(errMsg) if conf.data is not None: conf.method = HTTPMETHOD.POST if not conf.method or conf.method == HTTPMETHOD.GET else conf.method hintNames = [] def process(match, repl): retVal = match.group(0) if not (conf.testParameter and match.group("name") not in conf.testParameter): retVal = repl while True: _ = re.search(r"\\g<([^>]+)>", retVal) if _: retVal = retVal.replace(_.group(0), match.group(int(_.group(1)) if _.group(1).isdigit() else _.group(1))) else: break if CUSTOM_INJECTION_MARK_CHAR in retVal: hintNames.append((retVal.split(CUSTOM_INJECTION_MARK_CHAR)[0], match.group("name"))) return retVal if kb.processUserMarks is None and CUSTOM_INJECTION_MARK_CHAR in conf.data: message = "custom injection marking character ('%s') found in option " % CUSTOM_INJECTION_MARK_CHAR message += "'--data'. Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException else: kb.processUserMarks = not test or test[0] not in ("n", "N") if kb.processUserMarks: kb.testOnlyCustom = True if not (kb.processUserMarks and CUSTOM_INJECTION_MARK_CHAR in conf.data): if re.search(JSON_RECOGNITION_REGEX, conf.data): message = "JSON data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*"[^"]+)"', functools.partial(process, repl=r'\g<1>%s"' % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*\b)', functools.partial(process, repl=r'\g<0>%s' % CUSTOM_INJECTION_MARK_CHAR), conf.data) match = re.search(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data) if match and not (conf.testParameter and match.group("name") not in conf.testParameter): _ = match.group(2) _ = re.sub(r'("[^"]+)"', '\g<1>%s"' % CUSTOM_INJECTION_MARK_CHAR, _) _ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', '\g<0>%s' % CUSTOM_INJECTION_MARK_CHAR, _) conf.data = conf.data.replace(match.group(0), match.group(0).replace(match.group(2), _)) kb.postHint = POST_HINT.JSON elif re.search(JSON_LIKE_RECOGNITION_REGEX, conf.data): message = "JSON-like data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub(r"('(?P<name>[^']+)'\s*:\s*'[^']+)'", functools.partial(process, repl=r"\g<1>%s'" % CUSTOM_INJECTION_MARK_CHAR), conf.data) conf.data = re.sub(r"('(?P<name>[^']+)'\s*:\s*)(-?\d[\d\.]*\b)", functools.partial(process, repl=r"\g<0>%s" % CUSTOM_INJECTION_MARK_CHAR), conf.data) kb.postHint = POST_HINT.JSON_LIKE elif re.search(ARRAY_LIKE_RECOGNITION_REGEX, conf.data): message = "Array-like data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub(r"(=[^%s]+)" % DEFAULT_GET_POST_DELIMITER, r"\g<1>%s" % CUSTOM_INJECTION_MARK_CHAR, conf.data) kb.postHint = POST_HINT.ARRAY_LIKE elif re.search(XML_RECOGNITION_REGEX, conf.data): message = "SOAP/XML data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub(r"(<(?P<name>[^>]+)( [^<]*)?>)([^<]+)(</\2)", functools.partial(process, repl=r"\g<1>\g<4>%s\g<5>" % CUSTOM_INJECTION_MARK_CHAR), conf.data) kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower() else POST_HINT.XML elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data): message = "Multipart-like data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException elif test[0] not in ("n", "N"): conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, ASTERISK_MARKER) conf.data = re.sub(r"(?si)((Content-Disposition[^\n]+?name\s*=\s*[\"'](?P<name>[^\n]+?)[\"']).+?)(((\r)?\n)+--)", functools.partial(process, repl=r"\g<1>%s\g<4>" % CUSTOM_INJECTION_MARK_CHAR), conf.data) kb.postHint = POST_HINT.MULTIPART if not kb.postHint: if CUSTOM_INJECTION_MARK_CHAR in conf.data: # later processed pass else: place = PLACE.POST conf.parameters[place] = conf.data paramDict = paramToDict(place, conf.data) if paramDict: conf.paramDict[place] = paramDict testableParameters = True else: if CUSTOM_INJECTION_MARK_CHAR not in conf.data: # in case that no usable parameter values has been found conf.parameters[PLACE.POST] = conf.data kb.processUserMarks = True if (kb.postHint and CUSTOM_INJECTION_MARK_CHAR in conf.data) else kb.processUserMarks if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any(place in conf.parameters for place in (PLACE.GET, PLACE.POST)) and not kb.postHint and not CUSTOM_INJECTION_MARK_CHAR in (conf.data or "") and conf.url.startswith("http"): warnMsg = "you've provided target URL without any GET " warnMsg += "parameters (e.g. www.site.com/article.php?id=1) " warnMsg += "and without providing any POST parameters " warnMsg += "through --data option" logger.warn(warnMsg) message = "do you want to try URI injections " message += "in the target URL itself? [Y/n/q] " test = readInput(message, default="Y") if not test or test[0] not in ("n", "N"): conf.url = "%s%s" % (conf.url, CUSTOM_INJECTION_MARK_CHAR) kb.processUserMarks = True elif test[0] in ("q", "Q"): raise SqlmapUserQuitException for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))): _ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or "" if CUSTOM_INJECTION_MARK_CHAR in _: if kb.processUserMarks is None: lut = {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data', PLACE.CUSTOM_HEADER: '--headers/--user-agent/--referer/--cookie'} message = "custom injection marking character ('%s') found in option " % CUSTOM_INJECTION_MARK_CHAR message += "'%s'. Do you want to process it? [Y/n/q] " % lut[place] test = readInput(message, default="Y") if test and test[0] in ("q", "Q"): raise SqlmapUserQuitException else: kb.processUserMarks = not test or test[0] not in ("n", "N") if kb.processUserMarks: kb.testOnlyCustom = True if "=%s" % CUSTOM_INJECTION_MARK_CHAR in _: warnMsg = "it seems that you've provided empty parameter value(s) " warnMsg += "for testing. Please, always use only valid parameter values " warnMsg += "so sqlmap could be able to run properly" logger.warn(warnMsg) if not kb.processUserMarks: if place == PLACE.URI: query = urlparse.urlsplit(value).query if query: parameters = conf.parameters[PLACE.GET] = query paramDict = paramToDict(PLACE.GET, parameters) if paramDict: conf.url = conf.url.split('?')[0] conf.paramDict[PLACE.GET] = paramDict testableParameters = True elif place == PLACE.CUSTOM_POST: conf.parameters[PLACE.POST] = conf.data paramDict = paramToDict(PLACE.POST, conf.data) if paramDict: conf.paramDict[PLACE.POST] = paramDict testableParameters = True else: conf.parameters[place] = value conf.paramDict[place] = OrderedDict() if place == PLACE.CUSTOM_HEADER: for index in xrange(len(conf.httpHeaders)): header, value = conf.httpHeaders[index] if CUSTOM_INJECTION_MARK_CHAR in re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value): parts = value.split(CUSTOM_INJECTION_MARK_CHAR) for i in xrange(len(parts) - 1): conf.paramDict[place]["%s #%d%s" % (header, i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "%s,%s" % (header, "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts)))) conf.httpHeaders[index] = (header, value.replace(CUSTOM_INJECTION_MARK_CHAR, "")) else: parts = value.split(CUSTOM_INJECTION_MARK_CHAR) for i in xrange(len(parts) - 1): name = None if kb.postHint: for ending, _ in hintNames: if parts[i].endswith(ending): name = "%s %s" % (kb.postHint, _) break if name is None: name = "%s#%s%s" % (("%s " % kb.postHint) if kb.postHint else "", i + 1, CUSTOM_INJECTION_MARK_CHAR) conf.paramDict[place][name] = "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts))) if place == PLACE.URI and PLACE.GET in conf.paramDict: del conf.paramDict[PLACE.GET] elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict: del conf.paramDict[PLACE.POST] testableParameters = True if kb.processUserMarks: for item in ("url", "data", "agent", "referer", "cookie"): if conf.get(item): conf[item] = conf[item].replace(CUSTOM_INJECTION_MARK_CHAR, "") # Perform checks on Cookie parameters if conf.cookie: conf.parameters[PLACE.COOKIE] = conf.cookie paramDict = paramToDict(PLACE.COOKIE, conf.cookie) if paramDict: conf.paramDict[PLACE.COOKIE] = paramDict testableParameters = True # Perform checks on header values if conf.httpHeaders: for httpHeader, headerValue in conf.httpHeaders: # Url encoding of the header values should be avoided # Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value httpHeader = httpHeader.title() if httpHeader == HTTP_HEADER.USER_AGENT: conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES))) if condition: conf.paramDict[PLACE.USER_AGENT] = {PLACE.USER_AGENT: headerValue} testableParameters = True elif httpHeader == HTTP_HEADER.REFERER: conf.parameters[PLACE.REFERER] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES))) if condition: conf.paramDict[PLACE.REFERER] = {PLACE.REFERER: headerValue} testableParameters = True elif httpHeader == HTTP_HEADER.HOST: conf.parameters[PLACE.HOST] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES))) if condition: conf.paramDict[PLACE.HOST] = {PLACE.HOST: headerValue} testableParameters = True if not conf.parameters: errMsg = "you did not provide any GET, POST and Cookie " errMsg += "parameter, neither an User-Agent, Referer or Host header value" raise SqlmapGenericException(errMsg) elif not testableParameters: errMsg = "all testable parameters you provided are not present " errMsg += "within the given request data" raise SqlmapGenericException(errMsg) if conf.csrfToken: if not any(conf.csrfToken in _ for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))) and not conf.csrfToken in set(_[0].lower() for _ in conf.httpHeaders) and not conf.csrfToken in conf.paramDict.get(PLACE.COOKIE, {}): errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken errMsg += "found in provided GET, POST, Cookie or header values" raise SqlmapGenericException(errMsg) else: for place in (PLACE.GET, PLACE.POST, PLACE.COOKIE): for parameter in conf.paramDict.get(place, {}): if any(parameter.lower().count(_) for _ in CSRF_TOKEN_PARAMETER_INFIXES): message = "%s parameter '%s' appears to hold anti-CSRF token. " % (place, parameter) message += "Do you want sqlmap to automatically update it in further requests? [y/N] " test = readInput(message, default="N") if test and test[0] in ("y", "Y"): conf.csrfToken = parameter break
except (SqlmapConnectionException, SqlmapValueException), ex: print kb.threadException = True logger.error("thread %s: %s" % (threading.currentThread().getName(), ex.message)) except: from lib.core.common import unhandledExceptionMessage print kb.threadException = True errMsg = unhandledExceptionMessage() logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) traceback.print_exc() finally: kb.multiThreadMode = False kb.bruteMode = False kb.threadContinue = True kb.threadException = False for lock in kb.locks.values(): if lock.locked_lock(): lock.release() if conf.get("hashDB"): conf.hashDB.flush(True) if cleanupFunction: cleanupFunction()
def _setRequestParams(): """ Check and set the parameters and perform checks on 'data' option for HTTP method POST. """ if conf.direct: conf.parameters[None] = "direct connection" return hintNames = [] testableParameters = False # Perform checks on GET parameters if conf.parameters.get(PLACE.GET): parameters = conf.parameters[PLACE.GET] paramDict = paramToDict(PLACE.GET, parameters) if paramDict: conf.paramDict[PLACE.GET] = paramDict testableParameters = True # Perform checks on POST parameters if conf.method == HTTPMETHOD.POST and conf.data is None: logger.warn("detected empty POST body") conf.data = "" if conf.data is not None: conf.method = HTTPMETHOD.POST if not conf.method or conf.method == HTTPMETHOD.GET else conf.method def process(match, repl): retVal = match.group(0) if not (conf.testParameter and match.group("name") not in conf.testParameter): retVal = repl while True: _ = re.search(r"\\g<([^>]+)>", retVal) if _: retVal = retVal.replace( _.group(0), match.group( int(_.group(1)) if _.group(1).isdigit() else _. group(1))) else: break if kb.customInjectionMark in retVal: hintNames.append((retVal.split(kb.customInjectionMark)[0], match.group("name"))) return retVal if kb.processUserMarks is None and kb.customInjectionMark in conf.data: message = "custom injection marker ('%s') found in option " % kb.customInjectionMark message += "'--data'. Do you want to process it? [Y/n/q] " choice = readInput(message, default='Y').upper() if choice == 'Q': raise SqlmapUserQuitException else: kb.processUserMarks = choice == 'Y' if kb.processUserMarks: kb.testOnlyCustom = True if re.search(JSON_RECOGNITION_REGEX, conf.data): message = "JSON data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " choice = readInput(message, default='Y').upper() if choice == 'Q': raise SqlmapUserQuitException elif choice == 'Y': if not (kb.processUserMarks and kb.customInjectionMark in conf.data): conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER) conf.data = re.sub( r'("(?P<name>[^"]+)"\s*:\s*".+?)"(?<!\\")', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data) conf.data = re.sub( r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*)\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data) conf.data = re.sub( r'("(?P<name>[^"]+)"\s*:\s*)((true|false|null))\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data) match = re.search(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data) if match and not (conf.testParameter and match.group("name") not in conf.testParameter): _ = match.group(2) _ = re.sub(r'("[^"]+)"', r'\g<1>%s"' % kb.customInjectionMark, _) _ = re.sub(r'(\A|,|\s+)(-?\d[\d\.]*\b)', r'\g<0>%s' % kb.customInjectionMark, _) conf.data = conf.data.replace( match.group(0), match.group(0).replace(match.group(2), _)) kb.postHint = POST_HINT.JSON elif re.search(JSON_LIKE_RECOGNITION_REGEX, conf.data): message = "JSON-like data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " choice = readInput(message, default='Y').upper() if choice == 'Q': raise SqlmapUserQuitException elif choice == 'Y': if not (kb.processUserMarks and kb.customInjectionMark in conf.data): conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER) conf.data = re.sub( r"('(?P<name>[^']+)'\s*:\s*'[^']+)'", functools.partial(process, repl=r"\g<1>%s'" % kb.customInjectionMark), conf.data) conf.data = re.sub( r"('(?P<name>[^']+)'\s*:\s*)(-?\d[\d\.]*\b)", functools.partial(process, repl=r"\g<0>%s" % kb.customInjectionMark), conf.data) kb.postHint = POST_HINT.JSON_LIKE elif re.search(ARRAY_LIKE_RECOGNITION_REGEX, conf.data): message = "Array-like data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " choice = readInput(message, default='Y').upper() if choice == 'Q': raise SqlmapUserQuitException elif choice == 'Y': if not (kb.processUserMarks and kb.customInjectionMark in conf.data): conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER) conf.data = re.sub( r"(=[^%s]+)" % DEFAULT_GET_POST_DELIMITER, r"\g<1>%s" % kb.customInjectionMark, conf.data) kb.postHint = POST_HINT.ARRAY_LIKE elif re.search(XML_RECOGNITION_REGEX, conf.data): message = "SOAP/XML data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " choice = readInput(message, default='Y').upper() if choice == 'Q': raise SqlmapUserQuitException elif choice == 'Y': if not (kb.processUserMarks and kb.customInjectionMark in conf.data): conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER) conf.data = re.sub( r"(<(?P<name>[^>]+)( [^<]*)?>)([^<]+)(</\2)", functools.partial(process, repl=r"\g<1>\g<4>%s\g<5>" % kb.customInjectionMark), conf.data) kb.postHint = POST_HINT.SOAP if "soap" in conf.data.lower( ) else POST_HINT.XML elif re.search(MULTIPART_RECOGNITION_REGEX, conf.data): message = "Multipart-like data found in %s data. " % conf.method message += "Do you want to process it? [Y/n/q] " choice = readInput(message, default='Y').upper() if choice == 'Q': raise SqlmapUserQuitException elif choice == 'Y': if not (kb.processUserMarks and kb.customInjectionMark in conf.data): conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER) conf.data = re.sub( r"(?si)((Content-Disposition[^\n]+?name\s*=\s*[\"']?(?P<name>[^\"'\r\n]+)[\"']?).+?)(((\r)?\n)+--)", functools.partial(process, repl=r"\g<1>%s\g<4>" % kb.customInjectionMark), conf.data) kb.postHint = POST_HINT.MULTIPART if not kb.postHint: if kb.customInjectionMark in conf.data: # later processed pass else: place = PLACE.POST conf.parameters[place] = conf.data paramDict = paramToDict(place, conf.data) if paramDict: conf.paramDict[place] = paramDict testableParameters = True else: if kb.customInjectionMark not in conf.data: # in case that no usable parameter values has been found conf.parameters[PLACE.POST] = conf.data kb.processUserMarks = True if (kb.postHint and kb.customInjectionMark in ( conf.data or "")) else kb.processUserMarks if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any( place in conf.parameters for place in (PLACE.GET, PLACE.POST)) and not kb.postHint and kb.customInjectionMark not in ( conf.data or "") and conf.url.startswith("http"): warnMsg = "you've provided target URL without any GET " warnMsg += "parameters (e.g. 'http://www.site.com/article.php?id=1') " warnMsg += "and without providing any POST parameters " warnMsg += "through option '--data'" logger.warn(warnMsg) message = "do you want to try URI injections " message += "in the target URL itself? [Y/n/q] " choice = readInput(message, default='Y').upper() if choice == 'Q': raise SqlmapUserQuitException elif choice == 'Y': conf.url = "%s%s" % (conf.url, kb.customInjectionMark) kb.processUserMarks = True for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data), (PLACE.CUSTOM_HEADER, str(conf.httpHeaders))): _ = re.sub(PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value or "") if place == PLACE.CUSTOM_HEADER else value or "" if kb.customInjectionMark in _: if kb.processUserMarks is None: lut = { PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data', PLACE.CUSTOM_HEADER: '--headers/--user-agent/--referer/--cookie' } message = "custom injection marker ('%s') found in option " % kb.customInjectionMark message += "'%s'. Do you want to process it? [Y/n/q] " % lut[ place] choice = readInput(message, default='Y').upper() if choice == 'Q': raise SqlmapUserQuitException else: kb.processUserMarks = choice == 'Y' if kb.processUserMarks: kb.testOnlyCustom = True if "=%s" % kb.customInjectionMark in _: warnMsg = "it seems that you've provided empty parameter value(s) " warnMsg += "for testing. Please, always use only valid parameter values " warnMsg += "so sqlmap could be able to run properly" logger.warn(warnMsg) if not kb.processUserMarks: if place == PLACE.URI: query = urlparse.urlsplit(value).query if query: parameters = conf.parameters[PLACE.GET] = query paramDict = paramToDict(PLACE.GET, parameters) if paramDict: conf.url = conf.url.split('?')[0] conf.paramDict[PLACE.GET] = paramDict testableParameters = True elif place == PLACE.CUSTOM_POST: conf.parameters[PLACE.POST] = conf.data paramDict = paramToDict(PLACE.POST, conf.data) if paramDict: conf.paramDict[PLACE.POST] = paramDict testableParameters = True else: conf.parameters[place] = value conf.paramDict[place] = OrderedDict() if place == PLACE.CUSTOM_HEADER: for index in xrange(len(conf.httpHeaders)): header, value = conf.httpHeaders[index] if kb.customInjectionMark in re.sub( PROBLEMATIC_CUSTOM_INJECTION_PATTERNS, "", value): parts = value.split(kb.customInjectionMark) for i in xrange(len(parts) - 1): conf.paramDict[place]["%s #%d%s" % ( header, i + 1, kb.customInjectionMark )] = "%s,%s" % (header, "".join( "%s%s" % (parts[j], kb.customInjectionMark if i == j else "") for j in xrange(len(parts)))) conf.httpHeaders[index] = ( header, value.replace(kb.customInjectionMark, "")) else: parts = value.split(kb.customInjectionMark) for i in xrange(len(parts) - 1): name = None if kb.postHint: for ending, _ in hintNames: if parts[i].endswith(ending): name = "%s %s" % (kb.postHint, _) break if name is None: name = "%s#%s%s" % ( ("%s " % kb.postHint) if kb.postHint else "", i + 1, kb.customInjectionMark) conf.paramDict[place][name] = "".join( "%s%s" % (parts[j], kb.customInjectionMark if i == j else "") for j in xrange(len(parts))) if place == PLACE.URI and PLACE.GET in conf.paramDict: del conf.paramDict[PLACE.GET] elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict: del conf.paramDict[PLACE.POST] testableParameters = True if kb.processUserMarks: for item in ("url", "data", "agent", "referer", "cookie"): if conf.get(item): conf[item] = conf[item].replace(kb.customInjectionMark, "") # Perform checks on Cookie parameters if conf.cookie: conf.parameters[PLACE.COOKIE] = conf.cookie paramDict = paramToDict(PLACE.COOKIE, conf.cookie) if paramDict: conf.paramDict[PLACE.COOKIE] = paramDict testableParameters = True # Perform checks on header values if conf.httpHeaders: for httpHeader, headerValue in list(conf.httpHeaders): # Url encoding of the header values should be avoided # Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value if httpHeader.upper() == HTTP_HEADER.USER_AGENT.upper(): conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES, True))) if condition: conf.paramDict[PLACE.USER_AGENT] = { PLACE.USER_AGENT: headerValue } testableParameters = True elif httpHeader.upper() == HTTP_HEADER.REFERER.upper(): conf.parameters[PLACE.REFERER] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES, True))) if condition: conf.paramDict[PLACE.REFERER] = { PLACE.REFERER: headerValue } testableParameters = True elif httpHeader.upper() == HTTP_HEADER.HOST.upper(): conf.parameters[PLACE.HOST] = urldecode(headerValue) condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES, True))) if condition: conf.paramDict[PLACE.HOST] = {PLACE.HOST: headerValue} testableParameters = True else: condition = intersect(conf.testParameter, [httpHeader], True) if condition: conf.parameters[PLACE.CUSTOM_HEADER] = str( conf.httpHeaders) conf.paramDict[PLACE.CUSTOM_HEADER] = { httpHeader: "%s,%s%s" % (httpHeader, headerValue, kb.customInjectionMark) } conf.httpHeaders = [ (_[0], _[1].replace(kb.customInjectionMark, "")) for _ in conf.httpHeaders ] testableParameters = True if not conf.parameters: errMsg = "you did not provide any GET, POST and Cookie " errMsg += "parameter, neither an User-Agent, Referer or Host header value" raise SqlmapGenericException(errMsg) elif not testableParameters: errMsg = "all testable parameters you provided are not present " errMsg += "within the given request data" raise SqlmapGenericException(errMsg) if conf.csrfToken: if not any( re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))) and not re.search( r"\b%s\b" % conf.csrfToken, conf.data or "") and conf.csrfToken not in set( _[0].lower() for _ in conf.httpHeaders ) and conf.csrfToken not in conf.paramDict.get( PLACE.COOKIE, {}): errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken._original errMsg += "found in provided GET, POST, Cookie or header values" raise SqlmapGenericException(errMsg) else: for place in (PLACE.GET, PLACE.POST, PLACE.COOKIE): if conf.csrfToken: break for parameter in conf.paramDict.get(place, {}): if any(parameter.lower().count(_) for _ in CSRF_TOKEN_PARAMETER_INFIXES): message = "%s parameter '%s' appears to hold anti-CSRF token. " % ( place, parameter) message += "Do you want sqlmap to automatically update it in further requests? [y/N] " if readInput(message, default='N', boolean=True): class _(unicode): pass conf.csrfToken = _(re.escape(getUnicode(parameter))) conf.csrfToken._original = getUnicode(parameter) break
def main(): """ sqlmap程序入口 """ try: checkEnvironment() setPaths(modulePath()) banner() # 存储原始命令行选项以备以后恢复 cmdLineOptions.update(cmdLineParser().__dict__) initOptions(cmdLineOptions) if conf.get("api"): # heavy imports from lib.utils.api import StdDbOut from lib.utils.api import setRestAPILog # 覆盖系统标准输出和标准错误,以写入IPC数据库 sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() conf.showTime = True dataToStdout(u"[!] 好好学习%s\n\n" % LEGAL_DISCLAIMER, forceOutput=True) dataToStdout(u"[*] 开始时间 %s\n\n" % time.strftime("%X"), forceOutput=True) init() if conf.profile: profile() elif conf.smokeTest: smokeTest() elif conf.liveTest: liveTest() else: try: start() except thread.error as ex: if "can't start new thread" in getSafeExString(ex): errMsg = u"无法启动新线程,请检查操作系统(linux上查看:ulimit -a)限制" logger.critical(errMsg) raise SystemExit else: raise except SqlmapUserQuitException: errMsg = u"用户退出" try: logger.error(errMsg) except KeyboardInterrupt: pass except (SqlmapSilentQuitException, bdb.BdbQuit): pass except SqlmapShellQuitException: cmdLineOptions.sqlmapShell = False except SqlmapBaseException as ex: errMsg = getSafeExString(ex) try: logger.critical(errMsg) except KeyboardInterrupt: pass raise SystemExit except KeyboardInterrupt: print errMsg = u"用户中止" try: logger.error(errMsg) except KeyboardInterrupt: pass except EOFError: print errMsg = u"退出" try: logger.error(errMsg) except KeyboardInterrupt: pass except SystemExit: pass except: print errMsg = unhandledExceptionMessage() excMsg = traceback.format_exc() valid = checkIntegrity() try: if valid is False: errMsg = u"代码完整性检查失败(关闭自动问题创建)" errMsg += u"您应该从官方GitHub存储库中的%s检索最新的开发版本" % GIT_PAGE logger.critical(errMsg) print dataToStdout(excMsg) raise SystemExit elif "tamper/" in excMsg: logger.critical(errMsg) print dataToStdout(excMsg) raise SystemExit elif "MemoryError" in excMsg: errMsg = u"内存耗尽检测" logger.error(errMsg) raise SystemExit elif any(_ in excMsg for _ in ("No space left", "Disk quota exceeded")): errMsg = u"输出设备上没有空间" logger.error(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("No such file", "_'", "self.get_prog_name()")): errMsg = u"检测到损坏的安装('%s'). " % excMsg.strip().split('\n')[-1] errMsg += u"您应该从官方GitHub存储库中的'%s'检索最新的开发版本" % GIT_PAGE logger.error(errMsg) raise SystemExit elif "Read-only file system" in excMsg: errMsg = u"输出设备以只读方式挂载" logger.error(errMsg) raise SystemExit elif "OperationalError: disk I/O error" in excMsg: errMsg = u"输出设备上的I/O错误" logger.error(errMsg) raise SystemExit elif "_mkstemp_inner" in excMsg: errMsg = u"访问临时文件时出现问题" logger.error(errMsg) raise SystemExit elif "can't start new thread" in excMsg: errMsg = u"创建新线程实例时出现问题," errMsg += u"请确保您没有运行太多进程" if not IS_WIN: errMsg += u"(或增加'ulimit -u'值)" logger.error(errMsg) raise SystemExit # False Positive“误报” False Negative“漏报” elif "'DictObject' object has no attribute '" in excMsg and all( _ in errMsg for _ in ("(fingerprinted)", "(identified)")): errMsg = u"在枚举中有一个问题。由于误报的可能性很大," errMsg += u"建议您重新运行'--flush-session'" logger.error(errMsg) raise SystemExit elif all(_ in excMsg for _ in ("pymysql", "configparser")): errMsg = "检测到pymsql初始化错误(依赖Python3)" logger.error(errMsg) raise SystemExit elif "bad marshal data (unknown type code)" in excMsg: match = re.search(r"\s*(.+)\s+ValueError", excMsg) errMsg = "您的一个.pyc文件已损坏%s" % (" ('%s')" % match.group(1) if match else "") errMsg += "请删除系统上的.pyc文件以解决问题" logger.error(errMsg) raise SystemExit elif "valueStack.pop" in excMsg and kb.get( "dumpKeyboardInterrupt"): raise SystemExit elif any(_ in excMsg for _ in ("Broken pipe", )): raise SystemExit for match in re.finditer(r'File "(.+?)", line', excMsg): file_ = match.group(1) file_ = os.path.relpath(file_, os.path.dirname(__file__)) file_ = file_.replace("\\", '/') file_ = re.sub(r"\.\./", '/', file_).lstrip('/') excMsg = excMsg.replace(match.group(1), file_) errMsg = maskSensitiveData(errMsg) excMsg = maskSensitiveData(excMsg) if conf.get("api") or not valid: logger.critical("%s\n%s" % (errMsg, excMsg)) else: logger.critical(errMsg) kb.stickyLevel = logging.CRITICAL dataToStdout(excMsg) createGithubIssue(errMsg, excMsg) except KeyboardInterrupt: pass finally: kb.threadContinue = False if conf.get("showTime"): dataToStdout(u"\n[*] 结束时间 %s\n\n" % time.strftime("%X"), forceOutput=True) kb.threadException = True if kb.get("tempDir"): for prefix in (MKSTEMP_PREFIX.IPC, MKSTEMP_PREFIX.TESTING, MKSTEMP_PREFIX.COOKIE_JAR, MKSTEMP_PREFIX.BIG_ARRAY): for filepath in glob.glob( os.path.join(kb.tempDir, "%s*" % prefix)): try: os.remove(filepath) except OSError: pass if not filter( None, (filepath for filepath in glob.glob(os.path.join(kb.tempDir, '*')) if not any( filepath.endswith(_) for _ in ('.lock', '.exe', '_')))): shutil.rmtree(kb.tempDir, ignore_errors=True) if conf.get("hashDB"): try: conf.hashDB.flush(True) except KeyboardInterrupt: pass if conf.get("harFile"): with openFile(conf.harFile, "w+b") as f: json.dump(conf.httpCollector.obtain(), fp=f, indent=4, separators=(',', ': ')) if cmdLineOptions.get("sqlmapShell"): cmdLineOptions.clear() conf.clear() kb.clear() main() if conf.get("api"): try: conf.databaseCursor.disconnect() except KeyboardInterrupt: pass if conf.get("dumper"): conf.dumper.flush() # 线程完成的短暂延迟 try: _ = time.time() while threading.activeCount() > 1 and ( time.time() - _) > THREAD_FINALIZATION_TIMEOUT: time.sleep(0.01) except KeyboardInterrupt: pass finally: # Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program if threading.activeCount() > 1: os._exit(0)