sqlmap/sqlmap.py

423 lines
15 KiB
Python
Raw Normal View History

2019-03-21 16:00:09 +03:00
#!/usr/bin/env python2
2008-10-15 19:38:22 +04:00
"""
2019-01-05 23:38:52 +03:00
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
2017-10-11 15:50:46 +03:00
See the file 'LICENSE' for copying permission
2008-10-15 19:38:22 +04:00
"""
2019-01-22 03:28:24 +03:00
from __future__ import print_function
2018-09-27 10:15:53 +03:00
try:
import sys
2016-03-12 21:28:28 +03:00
2018-09-27 10:15:53 +03:00
sys.dont_write_bytecode = True
2016-03-12 21:28:28 +03:00
2018-09-27 10:15:53 +03:00
try:
__import__("lib.utils.versioncheck") # this has to be the first non-standard import
except ImportError:
2019-03-04 18:36:19 +03:00
sys.exit("[!] wrong installation detected (missing modules). Visit 'https://github.com/sqlmapproject/sqlmap/#installation' for further details")
2016-03-12 21:28:28 +03:00
2018-09-27 10:15:53 +03:00
import bdb
import distutils
import glob
import inspect
import json
import logging
import os
import re
import shutil
import sys
import threading
import time
import traceback
import warnings
2018-09-27 10:15:53 +03:00
warnings.filterwarnings(action="ignore", message=".*was already imported", category=UserWarning)
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
2008-10-15 19:38:22 +04:00
2018-09-27 10:15:53 +03:00
from lib.core.data import logger
2016-05-10 10:19:59 +03:00
from lib.core.common import banner
from lib.core.common import checkIntegrity
from lib.core.common import checkPipedInput
2016-05-10 10:19:59 +03:00
from lib.core.common import createGithubIssue
from lib.core.common import dataToStdout
2019-03-29 04:28:16 +03:00
from lib.core.common import filterNone
2019-04-15 16:15:12 +03:00
from lib.core.common import getDaysFromLastUpdate
2016-05-10 10:19:59 +03:00
from lib.core.common import getSafeExString
from lib.core.common import getUnicode
from lib.core.common import maskSensitiveData
2017-07-03 17:55:24 +03:00
from lib.core.common import openFile
2016-05-10 10:19:59 +03:00
from lib.core.common import setPaths
from lib.core.common import weAreFrozen
from lib.core.data import cmdLineOptions
from lib.core.data import conf
from lib.core.data import kb
from lib.core.common import unhandledExceptionMessage
from lib.core.common import MKSTEMP_PREFIX
from lib.core.common import setColor
2016-05-10 10:19:59 +03:00
from lib.core.exception import SqlmapBaseException
from lib.core.exception import SqlmapShellQuitException
from lib.core.exception import SqlmapSilentQuitException
from lib.core.exception import SqlmapUserQuitException
from lib.core.option import initOptions
from lib.core.option import init
2018-06-13 00:02:38 +03:00
from lib.core.patch import dirtyPatches
2016-06-18 02:21:57 +03:00
from lib.core.settings import GIT_PAGE
2016-05-10 10:19:59 +03:00
from lib.core.settings import IS_WIN
2019-04-15 16:15:12 +03:00
from lib.core.settings import LAST_UPDATE_NAGGING_DAYS
2016-05-10 10:19:59 +03:00
from lib.core.settings import LEGAL_DISCLAIMER
from lib.core.settings import THREAD_FINALIZATION_TIMEOUT
2016-06-19 18:44:47 +03:00
from lib.core.settings import UNICODE_ENCODING
2016-05-10 10:19:59 +03:00
from lib.core.settings import VERSION
from lib.parse.cmdline import cmdLineParser
from thirdparty.six import PY2
2016-05-10 10:19:59 +03:00
except KeyboardInterrupt:
errMsg = "user aborted"
2018-09-27 10:15:53 +03:00
if "logger" in globals():
2018-10-03 12:27:51 +03:00
logger.critical(errMsg)
2018-09-27 10:15:53 +03:00
raise SystemExit
else:
import time
2019-03-04 18:36:19 +03:00
sys.exit("\r[%s] [CRITICAL] %s" % (time.strftime("%X"), errMsg))
2013-02-06 13:28:17 +04:00
def modulePath():
"""
This will get us the program's directory, even if we are frozen
using py2exe
"""
2013-05-29 12:20:43 +04:00
try:
_ = sys.executable if weAreFrozen() else __file__
except NameError:
_ = inspect.getsourcefile(modulePath)
2016-06-19 18:44:47 +03:00
return getUnicode(os.path.dirname(os.path.realpath(_)), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
2013-02-06 13:28:17 +04:00
2016-05-06 11:23:57 +03:00
def checkEnvironment():
try:
2016-08-02 01:17:59 +03:00
os.path.isdir(modulePath())
2016-05-06 11:23:57 +03:00
except UnicodeEncodeError:
errMsg = "your system does not properly handle non-ASCII paths. "
errMsg += "Please move the sqlmap's directory to the other location"
logger.critical(errMsg)
raise SystemExit
if distutils.version.LooseVersion(VERSION) < distutils.version.LooseVersion("1.0"):
2016-05-06 11:23:57 +03:00
errMsg = "your runtime environment (e.g. PYTHONPATH) is "
errMsg += "broken. Please make sure that you are not running "
errMsg += "newer versions of sqlmap with runtime scripts for older "
errMsg += "versions"
logger.critical(errMsg)
raise SystemExit
2016-09-04 04:09:28 +03:00
# Patch for pip (import) environment
2016-09-04 02:33:52 +03:00
if "sqlmap.sqlmap" in sys.modules:
2016-09-04 04:09:28 +03:00
for _ in ("cmdLineOptions", "conf", "kb"):
globals()[_] = getattr(sys.modules["lib.core.data"], _)
for _ in ("SqlmapBaseException", "SqlmapShellQuitException", "SqlmapSilentQuitException", "SqlmapUserQuitException"):
globals()[_] = getattr(sys.modules["lib.core.exception"], _)
2013-02-06 13:28:17 +04:00
def main():
"""
Main function of sqlmap when running from command line.
"""
try:
2018-06-13 00:02:38 +03:00
dirtyPatches()
2016-05-06 11:23:57 +03:00
checkEnvironment()
2016-08-02 01:17:59 +03:00
setPaths(modulePath())
2016-04-19 14:45:49 +03:00
banner()
2013-02-06 13:28:17 +04:00
# Store original command line options for possible later restoration
cmdLineOptions.update(cmdLineParser().__dict__)
initOptions(cmdLineOptions)
if checkPipedInput():
conf.batch = True
2017-04-10 20:21:22 +03:00
if conf.get("api"):
2016-09-28 15:48:33 +03:00
# heavy imports
from lib.utils.api import StdDbOut
from lib.utils.api import setRestAPILog
2013-02-06 13:28:17 +04:00
# 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()
2014-09-16 18:28:38 +04:00
conf.showTime = True
2013-02-06 13:28:17 +04:00
dataToStdout("[!] legal disclaimer: %s\n\n" % LEGAL_DISCLAIMER, forceOutput=True)
2018-11-02 00:59:20 +03:00
dataToStdout("[*] starting @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True)
2013-02-06 13:28:17 +04:00
init()
2017-12-04 17:40:59 +03:00
if not conf.updateAll:
# Postponed imports (faster start)
2018-06-20 14:51:03 +03:00
if conf.smokeTest:
2017-12-04 17:40:59 +03:00
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)
2017-12-04 17:40:59 +03:00
elif conf.liveTest:
from lib.core.testing import liveTest
os._exitcode = 1 - (liveTest() or 0)
2017-12-04 17:40:59 +03:00
else:
from lib.controller.controller import start
if conf.profile and PY2:
2018-06-20 14:51:03 +03:00
from lib.core.profiling import profile
globals()["start"] = start
profile()
else:
try:
start()
2019-03-27 02:58:12 +03:00
except Exception as ex:
os._exitcode = 1
2018-06-20 14:51:03 +03:00
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
2013-02-06 13:28:17 +04:00
except SqlmapUserQuitException:
2018-12-21 12:38:27 +03:00
if not conf.batch:
errMsg = "user quit"
logger.error(errMsg)
2013-02-06 13:28:17 +04:00
except (SqlmapSilentQuitException, bdb.BdbQuit):
pass
2014-09-16 16:12:43 +04:00
except SqlmapShellQuitException:
cmdLineOptions.sqlmapShell = False
except SqlmapBaseException as ex:
errMsg = getSafeExString(ex)
2018-12-17 17:00:57 +03:00
logger.critical(errMsg)
2015-10-12 11:05:49 +03:00
raise SystemExit
2013-02-06 13:28:17 +04:00
except KeyboardInterrupt:
2019-01-22 03:28:24 +03:00
print()
2015-12-28 13:39:46 +03:00
2013-02-06 13:28:17 +04:00
except EOFError:
2019-01-22 03:28:24 +03:00
print()
2015-12-28 13:39:46 +03:00
2018-12-17 17:00:57 +03:00
errMsg = "exit"
logger.error(errMsg)
2013-02-06 13:28:17 +04:00
except SystemExit:
pass
except:
2019-01-22 03:28:24 +03:00
print()
2013-02-06 13:28:17 +04:00
errMsg = unhandledExceptionMessage()
2014-10-27 02:37:46 +03:00
excMsg = traceback.format_exc()
2017-04-11 11:01:37 +03:00
valid = checkIntegrity()
2014-10-28 16:08:06 +03:00
2018-12-17 17:00:57 +03:00
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)
2019-01-22 03:28:24 +03:00
print()
2018-12-17 17:00:57 +03:00
dataToStdout(excMsg)
raise SystemExit
elif any(_ in excMsg for _ in ("tamper/", "waf/")):
logger.critical(errMsg)
2019-01-22 03:28:24 +03:00
print()
2018-12-17 17:00:57 +03:00
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
2019-02-25 19:18:38 +03:00
elif any(_ in excMsg for _ in ("MemoryError", "Cannot allocate memory")):
2018-12-17 17:00:57 +03:00
errMsg = "memory exhaustion detected"
logger.critical(errMsg)
raise SystemExit
2019-01-22 12:12:17 +03:00
elif any(_ in excMsg for _ in ("No space left", "Disk quota exceeded", "Disk full while accessing")):
2018-12-17 17:00:57 +03:00
errMsg = "no space left on output device"
logger.critical(errMsg)
raise SystemExit
2019-01-22 12:12:17 +03:00
elif any(_ in excMsg for _ in ("The paging file is too small",)):
errMsg = "no space left for paging file"
logger.critical(errMsg)
raise SystemExit
2018-12-17 17:00:57 +03:00
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
2015-12-28 13:39:46 +03:00
2018-12-17 17:00:57 +03:00
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
2015-12-28 13:39:46 +03:00
2018-12-17 17:00:57 +03:00
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:
2018-12-17 17:00:57 +03:00
file_ = file_.lstrip('/')
file_ = re.sub(r"/{2,}", '/', file_)
excMsg = excMsg.replace(match.group(1), file_)
errMsg = maskSensitiveData(errMsg)
excMsg = maskSensitiveData(excMsg)
2018-12-17 17:00:57 +03:00
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))
2018-12-17 17:00:57 +03:00
createGithubIssue(errMsg, excMsg)
2013-02-06 13:28:17 +04:00
finally:
kb.threadContinue = False
2019-04-15 16:15:12 +03:00
_ = getDaysFromLastUpdate()
if _ > LAST_UPDATE_NAGGING_DAYS:
warnMsg = "you haven't updated sqlmap for more than %d days!!!" % _
logger.warn(warnMsg)
2016-01-11 02:03:22 +03:00
if conf.get("showTime"):
2018-11-02 00:59:20 +03:00
dataToStdout("\n[*] ending @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True)
2016-01-11 02:03:22 +03:00
kb.threadException = True
2016-01-11 01:27:32 +03:00
if kb.get("tempDir"):
2016-07-13 15:09:33 +03:00
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
2019-03-29 04:28:16 +03:00
if not filterNone(filepath for filepath in glob.glob(os.path.join(kb.tempDir, '*')) if not any(filepath.endswith(_) for _ in ('.lock', '.exe', '_'))):
2016-07-13 15:09:33 +03:00
shutil.rmtree(kb.tempDir, ignore_errors=True)
2016-01-11 01:27:32 +03:00
2013-02-06 13:28:17 +04:00
if conf.get("hashDB"):
2018-12-17 17:00:57 +03:00
conf.hashDB.flush(True)
2013-02-06 13:28:17 +04:00
2017-07-05 14:35:02 +03:00
if conf.get("harFile"):
2017-07-03 17:55:24 +03:00
with openFile(conf.harFile, "w+b") as f:
2017-07-05 15:07:21 +03:00
json.dump(conf.httpCollector.obtain(), fp=f, indent=4, separators=(',', ': '))
2017-07-03 17:55:24 +03:00
2017-04-10 20:21:22 +03:00
if conf.get("api"):
2018-12-17 17:00:57 +03:00
conf.databaseCursor.disconnect()
2013-02-06 13:28:17 +04:00
if conf.get("dumper"):
conf.dumper.flush()
# short delay for thread finalization
2018-12-17 17:00:57 +03:00
_ = 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()
2013-02-06 13:28:17 +04:00
if __name__ == "__main__":
2018-12-17 17:00:57 +03:00
try:
main()
except KeyboardInterrupt:
pass
2019-04-30 14:20:31 +03:00
except:
if int(os.environ.get("SQLMAP_DREI", 0)):
traceback.print_exc()
2018-12-17 17:00:57 +03:00
finally:
# Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program
if threading.activeCount() > 1:
os._exit(getattr(os, "_exitcode", 0))
else:
sys.exit(getattr(os, "_exitcode", 0))
else:
# cancelling postponed imports (because of Travis CI checks)
2018-06-10 00:38:00 +03:00
from lib.controller.controller import start