1. 程式人生 > >SQL手工注入進階篇

SQL手工注入進階篇

0.前言

  上一篇我們介紹了SQL手工注入的流程以及步驟,但在實際的安全問題以及CTF題目中,查詢語句多種多樣,而且是肯定會對使用者的輸入進行一個安全過濾的,而這些過濾並不一定是百分百安全的,如何利用一些技巧繞過一些安全過濾,這就是我們這一篇要介紹的事情。

  如果你還不熟悉SQL注入的流程以及步驟,請先閱讀我的上一篇博文。

  文中有誤之處,還請各位師傅指出。

 

1.各種select語句繞過

 (1)select xxx from xxx limit $num;

  上篇我們講解了where條件查詢的注入方法,那麼如果不是where而是其他語句呢,例如limit限制,這可能會出現在限制每頁展示多少行中用到,例如對於如下語句

  select * from student limit $num;

  $num是我們上傳的變數,假如我們依然使用order進行查列數將於返回如下結果

 

   Mysql會提示語法錯誤,因為排序需要在分頁的前面使用,那麼這個時候我們該如何查列數呢,答案是上次提到的利用into @,@,@,@就是‘@’字元,它代表Mysql的一個臨時變數。

  例如  

 

  必須保證變數數等於列數,利用這個特性我們就可以查出列數。

  (2)updata,insert,delete相關

  和select類似,還是先找到引數的位置,再判斷注入型別,最後構造表示式進行SQL注入。

  (3)order by注入

  前面已經講了利用order by查列數,實際上order by可以通過位運算來執行表示式

select * from student order by 1|(sleep(5));

 

2.時間函式進行盲注

  有些時候當網頁沒有錯誤回顯時,可以考慮使用時間函式進行盲注。原理是利用條件判斷進行睡眠,我們只需要觀察響應時間即可。

  例如

select * from student where id=1 and if(user()='root@localhost',sleep(5),null);#判斷使用者

select * from student where id=1 and if(substr(user(),1,1)='r',sleep(5),null);#逐字判斷

  我們可以先用一個永真條件判斷sleep()是否可用,當sleep()被禁用的時候,我們可以用下面其他幾種延時方法代替。

 (1)延時方法

  • sleep()函式。
  • benchmark(count,expr),重複expr函式count次,我們可以利用一些MySql自帶的加密函式作為expr執行多次達到睡眠的效果。具體執行次數可以根據CPU來進行變動。
select * from student where id=1 and if(true,benchmark(10000000,sha(1)),null);
  • 笛卡爾積,利用計算笛卡爾積達到延時;
select count(*) from information_schema.columns A,information_schema.columns B;#count(*)返回行數
  • get_lock(str,timeout),這個需要開啟兩次會話,第一次給str進行上鎖,第二次再執行就會等待timeout的時間,若timeout為負,則無限等待。get_lock()只會在執行release_lock()或隱式的會話中止時顯式釋放鎖,事務提交或回滾不會釋放鎖。
  • length(str),利用rpad構造長字串,再用length返回一列。
select LENGTH(concat(rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a')));

 

  • rlike,regexp,先利用rpad或者式repeat構造長字串再利用rlike正則匹配返回一列,通過控制構造的字串長度控制時間。
select concat(rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a'),rpad(1,9999999,'a')) rlike '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)';

  p.s.構造字串長度不能超出MySql記憶體限制,否則會報錯。

 (2)條件判斷

  • if(expr,expr1,expr2).
  • case when xx then xx;利用case when語法達到判斷條件的方法。

 (3)字串擷取

  • substr(str,pos,len),同Python的substr()函式,但MySql中首位置為1或-len。
  • mid(str,pos,len),基本同上
  • substring_index(str,delim,count),返回第count個delim串左邊的所有內容
select substring_index('a.b.c.d','.',3);#返回a.b.c
  • left(str,len),返回str左邊len個字元。
  • right(str,len),返回str右邊len個字元。

  本質上時間盲注就是bool盲注的一種,利用回顯訊息不同,只是這裡的回顯沒有顯式顯示在螢幕上罷了。

 

3.bool盲注

  利用回顯的不同來猜測資料庫的資訊,例如order by就是一種bool盲注,一般可以利用二分或者逐位拆解的方式進行盲注。可以利用一些位運算的短路機制進行連線表示式。

 

4.多行注入

  當呼叫資料庫函式支援多行sql語句才能使用,原理就是利用';'結束語句插入自己的sql語句。

 

5.MySql編碼注入

(1)弱型別轉換

  先來看這樣一個查詢語句select * from student where name=1;

  

 

  為什麼可以被查詢呢,因為name會被轉換成數字和1比較,而MySql的預設轉換和php的轉換類似,找到第一個不為數字的字元就結束。利用這個特性我們可以進行一些查詢判斷。

(2)寬位元組注入

  噹噹前資料庫使用了GBK編碼的時候,會把兩個字元轉化為漢字(前一個字元大於128),利用這個特性再配合後端的過濾實現注入。

  例如當後端過濾'將其變成\'的時候,如果式gbk編碼,則傳入的就是%5C%27,這時候我們提交%df'則會被編碼成%df%5C%27,而前面的%df%5c則會被編碼成中文,達到了注入效果。

(3)SQL字符集特性

  對於utf8_unicode_ci字符集,不區分大小寫,而且Ä=A,Ö=O,Ü=U等條件都成立,且ß=ss,

  對於utf8_general_ci字符集,ß=s。

  更多條件等式可以自行測試。

(4)進位制轉換

  如果表名和列名過濾了字元可以將其轉換為16進位制實現,前面帶上0x

6.總結

  本篇博文就是在上一篇的基礎上講解了一些其他的注入方法,已經引入了很多MySql函式。到現在 對Mysql的知識已經講完了,下一篇我們將會著重講解如何繞過後端對傳輸引數的一些過濾繞過。

  如果還有什麼補充的地方,請各位師傅在評論區留言。

&n