|
|
|
@ -10,16 +10,13 @@ from __future__ import print_function
|
|
|
|
|
try:
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
# 防止Python自动生成.pyc文件
|
|
|
|
|
sys.dont_write_bytecode = True
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 检查sqlmap的安装是否正确
|
|
|
|
|
__import__("lib.utils.versioncheck") # this has to be the first non-standard import
|
|
|
|
|
except ImportError:
|
|
|
|
|
sys.exit("[!] wrong installation detected (missing modules). Visit 'https://github.com/sqlmapproject/sqlmap/#installation' for further details")
|
|
|
|
|
|
|
|
|
|
# 导入标准库模块
|
|
|
|
|
import bdb
|
|
|
|
|
import glob
|
|
|
|
|
import inspect
|
|
|
|
@ -35,7 +32,6 @@ try:
|
|
|
|
|
import traceback
|
|
|
|
|
import warnings
|
|
|
|
|
|
|
|
|
|
# 忽略DeprecationWarning,除非命令行参数中包含"--deprecations"
|
|
|
|
|
if "--deprecations" not in sys.argv:
|
|
|
|
|
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
|
|
|
|
else:
|
|
|
|
@ -45,17 +41,14 @@ try:
|
|
|
|
|
if sys.version_info >= (3, 0):
|
|
|
|
|
warnings.simplefilter("ignore", category=ResourceWarning)
|
|
|
|
|
|
|
|
|
|
# 忽略特定警告
|
|
|
|
|
warnings.filterwarnings(action="ignore", message="Python 2 is no longer supported")
|
|
|
|
|
warnings.filterwarnings(action="ignore", message=".*was already imported", category=UserWarning)
|
|
|
|
|
warnings.filterwarnings(action="ignore", message=".*using a very old release", category=UserWarning)
|
|
|
|
|
warnings.filterwarnings(action="ignore", message=".*default buffer size will be used", category=RuntimeWarning)
|
|
|
|
|
warnings.filterwarnings(action="ignore", category=UserWarning, module="psycopg2")
|
|
|
|
|
|
|
|
|
|
# 导入sqlmap的核心日志模块
|
|
|
|
|
from lib.core.data import logger
|
|
|
|
|
|
|
|
|
|
# 导入sqlmap的核心功能模块
|
|
|
|
|
from lib.core.common import banner
|
|
|
|
|
from lib.core.common import checkPipedInput
|
|
|
|
|
from lib.core.common import checkSums
|
|
|
|
@ -97,8 +90,6 @@ try:
|
|
|
|
|
from lib.core.settings import VERSION
|
|
|
|
|
from lib.parse.cmdline import cmdLineParser
|
|
|
|
|
from lib.utils.crawler import crawl
|
|
|
|
|
except Exception as ex:
|
|
|
|
|
print("An error occurred: " + str(ex))
|
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
errMsg = "user aborted"
|
|
|
|
|
|
|
|
|
@ -111,38 +102,26 @@ except KeyboardInterrupt:
|
|
|
|
|
|
|
|
|
|
def modulePath():
|
|
|
|
|
"""
|
|
|
|
|
获取程序的目录路径,即使使用了 py2exe 进行冻结打包也能正确获取。
|
|
|
|
|
|
|
|
|
|
返回值:
|
|
|
|
|
返回程序所在目录的Unicode编码路径字符串。
|
|
|
|
|
This will get us the program's directory, even if we are frozen
|
|
|
|
|
using py2exe
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 如果程序被py2exe冻结,则使用sys.executable获取路径;否则使用__file__获取
|
|
|
|
|
_ = sys.executable if weAreFrozen() else __file__
|
|
|
|
|
except NameError:
|
|
|
|
|
# 如果__file__未定义(在某些环境下可能发生),则使用inspect模块获取当前函数的文件路径
|
|
|
|
|
_ = inspect.getsourcefile(modulePath)
|
|
|
|
|
|
|
|
|
|
# 获取_的目录路径,并转换为Unicode编码
|
|
|
|
|
return getUnicode(os.path.dirname(os.path.realpath(_)), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
|
|
|
|
|
|
|
|
|
|
def checkEnvironment():
|
|
|
|
|
"""
|
|
|
|
|
检查运行环境是否适合运行 sqlmap。
|
|
|
|
|
|
|
|
|
|
如果在检查过程中发现问题,则会记录错误信息并退出程序。
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# 检查程序目录是否存在
|
|
|
|
|
os.path.isdir(modulePath())
|
|
|
|
|
except UnicodeEncodeError:
|
|
|
|
|
# 如果系统无法正确处理非ASCII路径,则记录错误信息并退出
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
# 检查sqlmap的版本是否低于1.0,如果是,则说明运行环境有问题
|
|
|
|
|
if LooseVersion(VERSION) < LooseVersion("1.0"):
|
|
|
|
|
errMsg = "your runtime environment (e.g. PYTHONPATH) is "
|
|
|
|
|
errMsg += "broken. Please make sure that you are not running "
|
|
|
|
@ -151,81 +130,68 @@ def checkEnvironment():
|
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
raise SystemExit
|
|
|
|
|
|
|
|
|
|
# 如果是通过pip安装的sqlmap,则需要对sys.modules进行一些修补操作
|
|
|
|
|
# Patch for pip (import) environment
|
|
|
|
|
if "sqlmap.sqlmap" in sys.modules:
|
|
|
|
|
for _ in ("cmdLineOptions", "conf", "kb"):
|
|
|
|
|
# 将lib.core.data模块中的cmdLineOptions、conf、kb变量添加到全局变量中
|
|
|
|
|
globals()[_] = getattr(sys.modules["lib.core.data"], _)
|
|
|
|
|
|
|
|
|
|
for _ in ("SqlmapBaseException", "SqlmapShellQuitException", "SqlmapSilentQuitException", "SqlmapUserQuitException"):
|
|
|
|
|
# 将lib.core.exception模块中的异常类添加到全局变量中
|
|
|
|
|
globals()[_] = getattr(sys.modules["lib.core.exception"], _)
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
"""
|
|
|
|
|
当从命令行运行时,这是 sqlmap 的主函数。
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
# 如果配置了API,设置API日志和重定向标准输出和错误
|
|
|
|
|
if conf.get("api"):
|
|
|
|
|
# 延迟导入(重量级导入)
|
|
|
|
|
# heavy imports
|
|
|
|
|
from lib.utils.api import StdDbOut
|
|
|
|
|
from lib.utils.api import setRestAPILog
|
|
|
|
|
|
|
|
|
|
# 重定向标准输出和错误到IPC数据库
|
|
|
|
|
# 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)
|
|
|
|
|
else:
|
|
|
|
|
# 启动sqlmap控制器
|
|
|
|
|
from lib.controller.controller import start
|
|
|
|
|
if conf.profile:
|
|
|
|
|
# 如果设置了性能分析,则进行性能分析
|
|
|
|
|
from lib.core.profiling import profile
|
|
|
|
|
globals()["start"] = start
|
|
|
|
|
profile()
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
# 如果设置了爬取深度和批量文件,则开始爬取
|
|
|
|
|
if conf.crawlDepth and conf.bulkFile:
|
|
|
|
|
targets = getFileItems(conf.bulkFile)
|
|
|
|
|
|
|
|
|
@ -257,7 +223,6 @@ def main():
|
|
|
|
|
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)
|
|
|
|
@ -265,7 +230,6 @@ def main():
|
|
|
|
|
else:
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
# 捕获并处理各种异常,记录错误信息并退出
|
|
|
|
|
except SqlmapUserQuitException:
|
|
|
|
|
if not conf.batch:
|
|
|
|
|
errMsg = "user quit"
|
|
|
|
@ -308,73 +272,61 @@ def main():
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含权限拒绝和Metasploit相关的消息,则记录Metasploit权限错误并退出
|
|
|
|
|
elif all(_ in excMsg for _ in ("Access is denied", "subprocess", "metasploit")):
|
|
|
|
|
errMsg = "permission error occurred while running Metasploit"
|
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
raise SystemExit
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含权限拒绝和metasploit相关的消息,则记录Metasploit权限错误并退出
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含磁盘I/O错误的消息,则记录I/O错误并退出
|
|
|
|
|
elif "OperationalError: disk I/O error" in excMsg:
|
|
|
|
|
errMsg = "I/O error on output device"
|
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
raise SystemExit
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含URL违反BIDI规则的消息,则记录无效URL错误并退出
|
|
|
|
|
elif "Violation of BIDI" in excMsg:
|
|
|
|
|
errMsg = "invalid URL (violation of Bidi IDNA rule - RFC 5893)"
|
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
raise SystemExit
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含无效IPv6 URL的消息,则记录无效URL错误并退出
|
|
|
|
|
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 "
|
|
|
|
@ -383,35 +335,74 @@ def main():
|
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
raise SystemExit
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含权限拒绝的消息,则记录文件访问权限错误并退出
|
|
|
|
|
elif "Permission denied: '" in excMsg:
|
|
|
|
|
match = re.search(r"Permission denied: '([^']*)", excMsg)
|
|
|
|
|
errMsg = "permission error occurred while accessing file '%s'" % match.group(1)
|
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
raise SystemExit
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含sqlalchemy包版本问题的消息,则记录sqlalchemy版本错误并退出
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含Python版本问题的消息,则记录Python版本错误并退出
|
|
|
|
|
elif "invalid maximum character passed to PyUnicode_New" in excMsg and re.search(r"\A3\.[34]", sys.version) is not None:
|
|
|
|
|
errMsg = "please upgrade the Python version (>= 3.5) "
|
|
|
|
|
# 由于网络原因,无法解析提供的链接,可能是链接问题或网络问题,请检查链接的合法性并适当重试。
|
|
|
|
|
errMsg += "(Reference: 'https://bugs.python.org/issue18183')"
|
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
raise SystemExit
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含PyMySQL包版本问题的消息,则记录PyMySQL版本错误并退出
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
# 如果异常信息中包含Python解
|
|
|
|
|
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 ("OSError: [Errno 22] Invalid argument: '", "importlib")):
|
|
|
|
|
errMsg = "unable to read file '%s'" % extractRegexResult(r"OSError: \[Errno 22\] Invalid argument: '(?P<result>[^']+)", excMsg)
|
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
raise SystemExit
|
|
|
|
|
|
|
|
|
|
elif "hash_randomization" in excMsg:
|
|
|
|
|
errMsg = "error occurred at Python interpreter which "
|
|
|
|
|
errMsg += "is fixed in 2.7.3. Please update accordingly "
|
|
|
|
|
errMsg += "(Reference: 'https://docs.python.org/2/library/sys.html')"
|
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
raise SystemExit
|
|
|
|
|
|
|
|
|
|
elif "AttributeError: unable to access item" in excMsg and re.search(r"3\.11\.\d+a", sys.version):
|
|
|
|
|
errMsg = "there is a known issue when sqlmap is run with ALPHA versions of Python 3.11. "
|
|
|
|
|
errMsg += "Please downgrade to some stable Python version"
|
|
|
|
|
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)"
|
|
|
|
|