8-Web安全——SQL注入WAF绕过之and,or,空格

目录

1. and和or绕过

2. 空格过滤绕过


 

1. and和or绕过

and和or的作用:

  1. and关键字表示同时满足两个条件,例如测试字符型注入和数字型注入用到的and 1=1和and1=2两个条件语句。
  2. or表示满足其中一个条件即可,例如报错注入时用到的or语句

下面是后台过滤and和or关键字的源代码:

function blacklist($id)
{
	$id= preg_replace('/or/i',"", $id);			//strip out OR (non case sensitive)
	$id= preg_replace('/AND/i',"", $id);		//Strip out AND (non case sensitive)
	
	return $id;
}

后端对于前端提交字符数据中or和and关键字是不以大小写区分进行过滤的,如果匹配到or或and关键字就以空字符进行替换。

 

 

例如直接在Less-25源代码中输入?id=1' and 1=1是无法判断其注入类型,从后台返回的信息来看,and关键字明显是被过滤了。

扫描二维码关注公众号,回复: 11353961 查看本文章

当后台对于一些常用的SQL注入方式进行了过滤时,SQL注入绕过WAF简单的常用思路一般会有以下几种:

  1. 可以先使用大小写绕过,例如?id=1' anD 1=1--+
  2. 复写过滤字符串,例如?id=1' anandd 1=1--+
  3. 用“&&”符号取代and关键字,用“||”符号取代or关键字

第一种:使用大小写绕过,输入?id=1 anD 1=1,页面返回的信息如下

and关键字依然被后台给过滤了。

 

 

第二种方式:既然使用大小写方式不可用,那就使用复写字符串

从页面返回的信息来看,使用复写字符串方式把and关键字隔开之后,这样后台就无法完全把and关键字过滤掉了。

 

 

使用or关键字的话同样也会被后台直接过滤掉:

 

 

使用||或运算符代替or关键字的话,页面可以正确返回信息:

 

1代表真,0代表假,“^”异或运算符在编程中的用法如下:

1 ^ 0 结果为1

0 ^ 1结果为1

1 ^ 1结果为0
0 ^ 0结果为0

使用异或运算符同样可以做到相同的注入效果:

对1^0^0进行拆解,1^0的结果为1,然后1再跟0进行异或运算得到的结果还是1,因此1^0^0的结果就是为真(1),页面返回正常,并且页面中没有把异或运算符过滤掉。

 

同理,如果输入?id=1'^'0'^'1的话,我们可以推出1^0^1的结果为假(0),页面就不会返回结果。

 

 

2. 空格过滤绕过

分析Less-26源代码:

function blacklist($id)
{
   $id= preg_replace('/or/i',"", $id);          //strip out OR (non case sensitive)
   $id= preg_replace('/and/i',"", $id);      //Strip out AND (non case sensitive)
   $id= preg_replace('/[\/\*]/',"", $id);    //strip out /*
   $id= preg_replace('/[--]/',"", $id);      //Strip out --
   $id= preg_replace('/[#]/',"", $id);          //Strip out #
//把空格过滤掉
   $id= preg_replace('/[\s]/',"", $id);      //Strip out spaces
   $id= preg_replace('/[\/\\\\]/',"", $id);      //Strip out slashes
   return $id;
}

Less-26后台的源代码中不仅是将and,or,--,#这些SQL关键字和注释符号过滤了,并且连空格这些也过滤了。

 

 

此时在Less-26中输入?id=1 group by 3 or 1=1,返回的结果如下:

当后台接收到id=1 group by 3 or 1=1命令时,会将空格,or等关键字替换成空字符,替换之后的结果就是页面所返回的内容:1groupby31=1,Less-26是用单引号闭合的,并且后台把1groupby31=1当做一个字符串处理,所以数据库在执行过程中id的取值实际上只从1groupby31=1字符串中取了第一个字符1,因此页面返回了id=1的用户名和密码。

 

空格绕过的有两种思路:使用“+”符号代替空格,使用URL编码代替空格。

 

可以使用以下URL编码来代替空格:

 

 

在上图中提供了多种URL编码方式来代替空格,但在sqli-LAB中只有%A0这种方式可以使用,构造的SQL命令语句如下:

?id=0'%a0union%a0select%a01,2,3%a0oorr%a0'1'='2

在web页面返回的信息中其中�符号就是用来替代空格字符的,也就是URL编码中的%A0,可以看到SQL命令可以正确执行,页面返回了正确的结果。

 

 

正式进行SQL注入的时候,例如查询数据库名和版本,就可以将1和2的位置替换成database()函数或者version()函数。如下所示:

 

 

聪明的小伙伴可以会想到,如果使用报错注入的话是不是也可以达到想要的目的,我们来看这个例子,构造的SQL语句如下:

?id=1000'||extractvalue(1,concat('$',(database())))||'1'='1

在整个构造的SQL语句中没有使用到空格,web页面返回的结果:

使用报错注入同样也可以过滤空格字符,达到同样的效果。

 

 

如果我们要查询当前数据库下的所有表名,构造SQL语句:

select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema=database())

 

由于不能使用空格,所以这里只能把所有空格的位置以括号来代替,另外information_schema数据库中出现了or关键字,所以这里要对information_schema进行混淆,即改为infoorrmation_schema。然后将构造的SQL语句作为参数将database()直接给替换掉,执行命令,页面返回的结果:

数据库的报错信息:Unknown XPATH variable at: '$emails,referers,uagents,users' 中,已经把当前数据库下的所有表名给爆出来了。同理,获取列名,用户名和密码也是按照这种方式。

 

 

猜你喜欢

转载自blog.csdn.net/qq_35733751/article/details/106507309