OWASP TOP 10(一)SQL注入(自动化工具sqlmap)

本文介绍SQLMap这一开源渗透测试工具的基本参数及使用方法,包括检测注入点、列出数据库名称等内容,并深入解析其工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

sqlmap

一、概述

sqlmap是一个开源渗透测试工具,它可以自动检测和利用 SQL 注入漏洞并接管数据库服务器。它具有强大的检测引擎,同时有众多功能,包括数据库指纹识别、从数据库中获取数据、访问底层文件系统以及在操作系统上带内连接执行命令。

支持的数据库有:
MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase和SAP MaxDB

在这里插入图片描述

二、基本参数

1、判断可注入的参数
2、判断可以用哪种SQL注入技术来注入
3、识别出哪种数据库
4、根据用户选择,读取哪些数据

1. 检测注入点

-u "url"     

sqlmap -u "http://192.168.40.129/PHP/sqli-labs-master/Less-1/?id=1"

在这里插入图片描述

sqlmap支持五种不同的注入模式:

1、基于布尔的盲注,即可以根据返回页面判断条件真假的注入。
2、基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
3、基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
4、联合查询注入,可以使用union的情况下的注入。
5、堆查询注入,可以同时执行多条语句的执行时的注入。

2. 列出所有数据库名

--dbs 

sqlmap -u "http://192.168.40.129/PHP/sqli-labs-master/Less-1/?id=1" --dbs

在这里插入图片描述

3. 列出当前数据库名

--current-db

sqlmap -u "http://192.168.40.129/PHP/sqli-labs-master/Less-1/?id=1" --current-db

在这里插入图片描述

4. 列出数据库名表名

-D   指定一个数据库
--tables

sqlmap -u "http://192.168.40.129/PHP/sqli-labs-master/Less-1/?id=1" -D "security" --tables

在这里插入图片描述

5. 列出表中字段名

-T    指定表名
--columns

sqlmap -u "http://192.168.40.129/PHP/sqli-labs-master/Less-1/?id=1" -D "security" -T "users" --columns

在这里插入图片描述

6. 列出字段内容

-C     指定字段
--dump

sqlmap -u "http://192.168.40.129/PHP/sqli-labs-master/Less-1/?id=1" -D "security" -T "users" -C "username,password" --dump

在这里插入图片描述

- 读取post请求

使用bp抓包,将http信息保存为文件,使用sqlmap读取

在这里插入图片描述

抓包结果:

在这里插入图片描述

将结果保存为post.txt文件

-r 文件

sqlmap -r post.txt

在这里插入图片描述

三、sqlmap简单原理分析

- 测试环境

1.5.1.6版本的sqlmap;

使用 AWVS 提供的环境:

http://testphp.vulnweb.comhttp://testasp.vulnweb.com

- 测试

debug分析sqlmap源码

这里使用 IDEA 进行 debug,打开 SQLMap 项目之后,在【Run】-【Edit Configurations】设置参数:

-u http://testasp.vulnweb.com/showforum.asp?id=0 --flush-session

刷新session缓存 --flush-session

在这里插入图片描述

在 sqlmapy.py 文件的main方法下一个断点,然后开启 Debug:

在这里插入图片描述

1. 初始化&与目标站点建立连接

当进入main方法后:
在这里插入图片描述
发现main方法的前面几行代码是获取配置、路径、banner 等信息;当运行到 153 行的时候可以发现已经获取到前面设置的站点参数并进入initOptions () 函数(初始化选项)中:

def initOptions(inputOptions=AttribDict(), overrideOptions=False):
	# 此函数将一些所需的属性设置为配置单例
    _setConfAttributes()   
    # 此功能将一些所需的属性设置为知识库单例     
    _setKnowledgeBaseAttributes()
    # 将命令行选项与配置文件和默认选项合并
    _mergeOptions(inputOptions, overrideOptions)

当运行到173行时,进入init() 函数中,可以看到会进行一系列设置如:http、threads 等等;

def init():
    """
    Set attributes into both configuration and knowledge base singletons
    based upon command line and configuration file options.
    """

    _useWizardInterface()
    setVerbosity()
    _saveConfig()
    _setRequestFromFile()
    _cleanupOptions()
    _cleanupEnvironment()
    _purge()
    _checkDependencies()
    _createHomeDirectories()
    _createTemporaryDirectory()
    _basicOptionValidation()
    _setProxyList()
    _setTorProxySettings()
    _setDNSServer()
    _adjustLoggingFormatter()
    _setMultipleTargets()
    _listTamperingFunctions()
    _setTamperingFunctions()
    _setPreprocessFunctions()
    _setPostprocessFunctions()
    _setTrafficOutputFP()
    _setupHTTPCollector()
    _setHttpChunked()
    _checkWebSocket()

    parseTargetDirect()

    if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork, conf.stdinPipe)):
        _setHostname()
        _setHTTPTimeout()
        _setHTTPExtraHeaders()
        _setHTTPCookies()
        _setHTTPReferer()
        _setHTTPHost()
        _setHTTPUserAgent()
        _setHTTPAuthentication()
        _setHTTPHandlers()
        _setDNSCache()
        _setSocketPreConnect()
        _setSafeVisit()
        _doSearch()
        _setStdinPipeTargets()
        _setBulkMultipleTargets()
        _checkTor()
        _setCrawler()
        _findPageForms()
        _setDBMS()
        _setTechnique()

    _setThreads()
    _setOS()
    _setWriteFile()
    _setMetasploit()
    _setDBMSAuthentication()
    loadBoundaries()
    loadPayloads()
    _setPrefixSuffix()
    update()
    _loadQueries()

我们会发现http请求头中 sqlmap 默认发送的 User-Agent 是这样的:

User-Agent: sqlmap/1.4.12#stable (http://sqlmap.org)

所以为了避免被 waf 或者日志里面记录,我们一般可以添加一个 --random-agent 参数在后面:

之后的 User-Agent 会变成这类的:

User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.16 

接下来会进入 ./lib/core/decorators.py 的 stackedmethod() 函数,根据注释,该函数是用来堆栈对齐的回退函数(不太理解该函数)。看到 result 关键字直接步入,然后会执行到start() 函数:

start() 函数对URL稳定性以及所有GET,POST,Cookie和User-Agent参数进行检查,以检查它们是否动态以及是否受到SQL注入的影响

在这里插入图片描述

经过一系列的信息获取:Method、paramKey、Headers 等,来到了 437 行进行连接等检查:

在这里插入图片描述

我们跟进checkConnection() 函数,会来到 ./controller/checks.py,先检查 hostname 是否是 ip 形式(xxx.xxx.xxx.xxx),之后检查有没有设置代理,然后输出 log 信息:尝试连接目标 url

在这里插入图片描述

后面开始进行 request 请求,跟进 Request 函数,来到 ./request/connect.py,通过注释可以得知 queryPage 函数是用来获取目标 url 页面内容:

在这里插入图片描述

直到调用 Connect.getPage 发起请求开始获取页面内容:

在这里插入图片描述

进入 getPage() 函数,经过一系列的赋值:url、get 类型参数、cookie 等:

在这里插入图片描述

然后调用 urllib.request.urlopent 发起请求:

在这里插入图片描述

获取响应正文信息:

在这里插入图片描述

关闭连接:

在这里插入图片描述

最后 getPage 函数会 return 出响应正文、响应头以及响应状态码,继续运行回到 queryPage 函数,经过一系列处理 queryPage 函数将响应正文、响应头以及响应状态码也 return 出去:

在这里插入图片描述

之后会到 ./lib/core/decorators.py,会将获取到的 result 返回:

在这里插入图片描述

最后回到 checks.py,返回 True,这时候 SQLMap 已经获知目标站点可连接:

在这里插入图片描述

2. WAF 判断
2.1 WAF 检测

在 449 行进行 waf 检测:

在这里插入图片描述

跟进 checkWaf 函数,又会来到 stackedmethod 函数,直到在 result 进行步入,会来到 checkWaf 函数。根据注释可以得知 sqlmap 的 waf 检测能力来源 nmap 的 http-waf-detect 脚本:

在这里插入图片描述

首先将几种攻击类型的 payload(SQL 注入、目录遍历、XSS 等)拼接到已有参数发起请求:

在这里插入图片描述

如果直接连接错误,可以判断存在 WAF;若可正常连接,判断不存在 WAF。

2.2 WAF 识别

继续执行到了 identifyWaf 函数,但由于并未设置检测 waf 会被判断跳过。可以按住 command 点击 identifyWaf 函数跟进查看原理;

大概原理是调用 waf 文件夹下脚本进行检测 —> 得到结果;

脚本脚本大概逻辑为:发起请求 —> 获取响应正文、响应头、响应码 —> 根据规则判断 —> 返回结果。

3. 稳定性检测

跟进checkStability() 函数,通过注释发现该函数是用来进行稳定性检测:

此函数检查URL内容是否稳定,两次请求同一页面,每次请求中的延迟很小,以假定它是稳定的;如果请求同一页面时页面的内容不同,则动态性可能取决于其他参数。

在这里插入图片描述
在这里插入图片描述

4. 参数动态检测

经过一系列赋值、判断,运行至 checkDynParam 函数:

在这里插入图片描述

此函数检查URL参数是否为动态,如果是动态的,则页面的内容会有所不同,否则动态性可能取决于另一个参数。

在这里插入图片描述

5. 注入检测

运行至 580 行,终于来到关键的注入检测:

在这里插入图片描述

跟进 heuristicCheckSqlInjection 函数,在 1023 行进行随机字符串获取,随机字符串长度为 10,并且该随机字符串需满足单引号或者双引号出现次数为 1:

在这里插入图片描述

接下来将随机字符串拼接成 payload,发起请求:

在这里插入图片描述

1075 行调用 parseFilePaths 函数检测响应正文中是否包含绝对路径:

在这里插入图片描述
在这里插入图片描述

1076 行检测上一个响应是否有数据库错误信息,这时候的上个请求 payload 是包含单双引号的,通过这种方式可以极快的判断是否存在注入:

在这里插入图片描述
在这里插入图片描述

当没有数据库的报错信息,还需要继续运行;在 1132 行会生成两个随机变量,长度为 6。接下来生成带 <’ "> 的 payload,该 payload 为第一个随机字符串加上 <’ "> 加上第二个随机字符串。

在这里插入图片描述

1088 行出现 agent.payload 函数,跟进该函数 ./lib/core/agent.py,根据注释得知该函数将受影响的参数替换为要请求的SQL注入语句:

在这里插入图片描述

然后调用 cleanupPayload 函数,根据函数名猜测该函数主要是用来进行 payload 清理;最终返回经过处理之后的 payload;之后使用处理之后的 payload 发起请求,最后返回 kb.heuristicTest:

在这里插入图片描述

继续运行回到 start 函数,591 行调用 checkSqlInjection 开始进行注入检测:

在这里插入图片描述

跟进 checkSqlInjection 函数,调用 InjectionDict 函数设置注入字典,之后对参数值类型进行检查:

在这里插入图片描述

134 行调用 getSortedInjectionTests 函数获取待注入类型及其 payload 等信息:

在这里插入图片描述

141 行会将 tests 数据取出来,直至取完才能跳出 140 行的 while 循环:

在这里插入图片描述

之后对 payload 进行处理,直至 506、527 行调用 Request.queryPage 请求。这时候的 payload 包含 AND 关键字:

在这里插入图片描述

之后对结果进行判断,没有满足条件的判断都直接 pass 掉,再开始重新构造 payload 发起请求,直至 payload 为 boolen 类型注入,会进入判断设置 injectable = True:在这里插入图片描述

拆分一下这里的判断逻辑:

  1. falsePage 与 truePage 是否相等,falsePage 使用的 payload 为 cmpPayload、TruePage 使用的 payload 为 reqPayload。假设得到结果为 A,A 为布尔类型;
  2. 获取 not kb.nullConnection 结果,假设得到结果为 B,B 为布尔类型;
  3. 判断 not (A and B),假设得到结果为 C,C 为布尔类型;
  4. 判断 trueResult and C,假设得到结果为 D,只有 trueResult、C 同为 True。D 才能为 True,满足条件判断;
  5. 正常情况下 B 为 True,这时候只有 falsePage 不等于 truePage,才能满足条件。

之后对该注入信息进行赋值存储 injection 变量中。由于这时候 injectable 为 True,所以会跳出 372 行的 for 循环:

在这里插入图片描述

- 总结

SQLMap 整个运行机制:

  1. 获取 url、thread、headers 等信息存储至变量中;

  2. 网站存活性检测;

  3. WAF 检测 & WAF 类型识别;

  4. 稳定性检测;

  5. 注入检测。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值