安全工具学习之SQLmap部分代码分析
字数 1135 2025-08-22 12:22:30
SQLMap源码分析与使用教学文档
1. SQLMap概述
SQLMap是一款开源的自动化SQL注入工具,用于检测和利用SQL注入漏洞。它支持多种数据库管理系统(DBMS),包括MySQL、Oracle、PostgreSQL等,并提供了丰富的功能选项。
2. SQLMap执行流程
2.1 主程序入口(sqlmap.py)
SQLMap的执行从sqlmap.py文件开始,主要流程如下:
-
初始化操作:
dirtyPatches() # 处理Python相关补丁 resolveCrossReferences() # 解决交叉引用 checkEnvironment() # 检查环境 setPaths(modulePath()) # 设置路径 banner() # 显示banner信息 -
参数解析:
args = cmdLineParser() # 解析命令行参数 cmdLineOptions.update(args.__dict__ if hasattr(args, "__dict__") else args) initOptions(cmdLineOptions) # 初始化选项 -
输入检查:
if checkPipedInput(): conf.batch = True -
API模式处理:
if conf.get("api"): from lib.utils.api import StdDbOut from lib.utils.api import setRestAPILog sys.stdout = StdDbOut(conf.taskid, messagetype="stdout") sys.stderr = StdDbOut(conf.taskid, messagetype="stderr") setRestAPILog() -
测试模式选择:
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: from lib.controller.controller import start if conf.profile: from lib.core.profiling import profile globals()["start"] = start profile() else: start()
2.2 路径设置
modulePath()函数用于获取程序目录:
def modulePath():
try:
_ = sys.executable if weAreFrozen() else __file__
except NameError:
_ = inspect.getsourcefile(modulePath)
return getUnicode(os.path.dirname(os.path.realpath(_)),
encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
2.3 参数解析系统
参数解析在lib/parse/cmdline.py中实现,例如:
parser.add_argument("--hh", dest="advancedHelp", action="store_true",
help="Show advanced help message and exit")
parser.add_argument("--version", dest="showVersion", action="store_true",
help="Show program's version number and exit")
parser.add_argument("-v", dest="verbose", type=int,
help="Verbosity level: 0-6 (default %d)" % defaults.verbose)
3. 请求文件处理
当使用-r参数指定请求文件时,SQLMap会进行以下处理:
-
文件检查:
if not checkFile(requestFile, False): errMsg = "specified HTTP request file '%s' does not exist" % requestFile raise SqlmapFilePathException(errMsg) -
解析请求文件:
for target in parseRequestFile(requestFile): url = target[0] if url not in seen: kb.targets.add(target) if len(kb.targets) > 1: conf.multipleTargets = True seen.add(url)
parseRequestFile()函数解析WebScarab和Burp日志文件,返回格式为:
('http://www.example.com:80/', 'POST', 'id=1', None,
(('User-agent', 'foobar'), ('Host', 'www.example.com')))
4. SQL注入检测机制
4.1 注入检测流程
-
URL解析:
parseTargetUrl() -
测试条件判断:
testSqlInj = False if PLACE.GET in conf.parameters and not any((conf.data, conf.testParameter)): for parameter in re.findall(r"([^%s]+%s?|\Z)" % (re.escape(conf.paramDel or "") or DEFAULT_GET_POST_DELIMITER, re.escape(conf.paramDel or "") or DEFAULT_GET_POST_DELIMITER), conf.parameters[PLACE.GET]): paramKey = (conf.hostname, conf.path, PLACE.GET, parameter[0]) if paramKey not in kb.testedParams: testSqlInj = True break -
启发式检测:
check = heuristicCheckSqlInjection(place, parameter)
4.2 启发式检测(heuristicCheckSqlInjection)
-
基本设置:
if conf.skipHeuristics: return None origValue = conf.paramDict[place][parameter] paramType = conf.method if conf.method not in (None, HTTPMETHOD.GET, HTTPMETHOD.POST) else place -
生成随机字符串:
while randStr.count('\'') != 1 or randStr.count('\"') != 1: randStr = randomStr(length=10, alphabet=HEURISTIC_CHECK_ALPHABET) -
构造payload:
payload = "%s%s%s" % (prefix, randStr, suffix) payload = agent.payload(place, parameter, newValue=payload) -
发送请求并分析响应:
page, _, _ = Request.queryPage(payload, place, content=True, raise404=False) kb.heuristicPage = page kb.heuristicMode = False parseFilePaths(page) result = wasLastResponseDBMSError() -
类型转换检测:
casting = _(page) and not _(kb.originalPage) if not casting and not result and kb.dynamicParameter and origValue.isdigit() and not kb.heavilyDynamic: randInt = int(randomInt()) payload = "%s%s%s" % (prefix, "%d-%d" % (int(origValue) + randInt, randInt), suffix) payload = agent.payload(place, parameter, newValue=payload, where=PAYLOAD.WHERE.REPLACE) result = Request.queryPage(payload, place, raise404=False) -
XSS和文件包含检测:
if value.upper() in (page or "").upper(): infoMsg = "heuristic (XSS) test shows that %s parameter '%s' might be vulnerable to cross-site scripting (XSS) attacks" % ("%s" % paramType if paramType != parameter else "", parameter) logger.info(infoMsg)
5. 关键函数解析
5.1 checkSqlInjection函数
这是SQLMap中实际检测SQL注入的核心函数,主要逻辑包括:
- 布尔型盲注检测
- 时间型盲注检测
- 基于错误的注入检测
- 联合查询注入检测
- **堆叠查询检测
5.2 agent.payload函数
负责构造各种类型的payload,包括:
- 边界值处理:添加前缀和后缀
- 参数替换:在原始参数值中插入payload
- 编码处理:根据需要对payload进行编码
6. 开发技巧
- 模块化设计:SQLMap将不同功能划分为独立模块,如参数解析、请求处理、注入检测等
- 配置管理:使用
conf和kb全局对象管理配置和知识库 - 错误处理:完善的异常处理机制确保程序稳定性
- 多线程支持:通过
_setThreads()函数设置并发线程数
7. 使用建议
-
基本用法:
python sqlmap.py -u "http://example.com/?id=1" -
从文件读取请求:
python sqlmap.py -r request.txt -
指定参数测试:
python sqlmap.py -u "http://example.com/?id=1&cat=2" -p "id" -
提高检测级别:
python sqlmap.py -u "http://example.com/?id=1" --level=5 --risk=3 -
使用tamper脚本:
python sqlmap.py -u "http://example.com/?id=1" --tamper=space2comment
8. 总结
SQLMap是一个功能强大且设计精良的SQL注入工具,其源码展示了:
- 完善的参数解析系统
- 灵活的请求处理机制
- 多层次的注入检测技术
- 丰富的功能选项
- 良好的错误处理和日志系统
通过分析其源码,可以深入理解自动化SQL注入检测的原理和实现方式,对于安全工具开发和Web安全研究都有重要参考价值。