SQL注入之宽字节注入


沉舟侧畔千帆过,病树前头万木春。


什么是宽字节注入?

当后端对用户的输入做了转义时,比如利用addslashes()或mysql_escape_string()函数。此时输入id=1’其中的单引号会被转义而变成id=1\',这样就使得单引号无法闭合数据库中的语句,一般情况下是很难绕过的。但是有两种情况可以通过宽字节注入绕过。

第一中情况是当数据库的编码为GBK时,注入格式为id=1%df',因为反斜杠\的编码为%5c,所以参数传到后端经过转义后就会变成id=1%df%5c',其中GBK会将%df%5c编码成一个繁体字,这样反斜杠就失去了转义的效果,使得单引号逃逸出来闭合了语句。第二种情况是,若后端的代码中有转换字符编码的函数,道理其实一样,就是将用户输入的参数用宽字节去解释了,从而使单引号逃逸。


靶场练习

1、pikachu之宽字节注入
  • 测试流程

输入%df' or 1=1#直接遍历出数据库内容:

image-20210412150242557

order by测出主查询字段数:

order by 2回显正常order by 3出现报错
image-20210412150517318image-20210412150535969

说明主查询字段数为2,接下来直接union注入:

测出回显点为1,2

image-20210412150723586

查询数据库信息:

image-20210412151002167

如图所示,查询出数据库名为pikachu,用户为root,数据库版本为5.5.53。

查询表名:

image-20210412151234651

查询字段名:

image-20210412151452743

查询字段值:

image-20210412151909686

整个过程的关键点在于单引号前面的%df,造成宽字节注入使得单引号逃逸处理闭合语句,才有了后面的操作。

  • 源码分析

    核心代码:

    if(isset($_POST['submit']) && $_POST['name']!=null){
    
        $name = escape($link,$_POST['name']);
        $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合
        //设置mysql客户端来源编码是gbk,这个设置导致出现宽字节注入问题
        $set = "set character_set_client=gbk";
        execute($link,$set);
    
        //mysqi_query不打印错误描述
        $result=mysqli_query($link, $query);
        if(mysqli_num_rows($result) >= 1){   #返回结果集中行的数量
            while ($data=mysqli_fetch_assoc($result)){      #从结果集中取得一行作为关联数组   
                $id=$data['id'];
                $email=$data['email'];
                $html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
            }
        }else{
            $html.="<p class='notice'>您输入的username不存在,请重新输入!</p>";
        }
    }
    

    如上述代码的第6,7行,设置为将用户输入的参数用GBK去编码,虽然第3行escape()有转义,但是依然可以用宽字节绕过,这属于在代码中有字符编码的转换函数而造成的,属于开篇提到的第二种情况。


2、sqli-labs之Less-36
  • 测试流程

    输入?id=1%df' and 1=1--+成功回显,说明单引号逃逸出来闭合了语句。

image-20210412153307310

然后和前面一样,order by 二分法测出主查询字段数为3。

直接union注入查数据库名、表名、字段名、字段值等等,进一步获取管理员账号和密码。

这里就不再赘述。

  • 源码分析

    核心代码:

    function check_quotes($string)
    {
        $string= mysql_real_escape_string($string);    
        return $string;
    }
    
    // take the variables 
    if(isset($_GET['id']))
    {
    $id=check_quotes($_GET['id']);
    //echo "The filtered request is :" .$id . "<br>";
    
    //logging the connection parameters to a file for analysis.
    $fp=fopen('result.txt','a');
    fwrite($fp,'ID:'.$id."\n");
    fclose($fp);
    
    // connectivity 
    
    mysql_query("SET NAMES gbk");
    $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
    $result=mysql_query($sql);
    $row = mysql_fetch_array($result);
    

    ​ 如上述代码第10行,虽然用mysql_real_escape_string()进行了转义,但是后面第20行将字符集编码设置成了GBK,所以直接宽字节就可以绕过,与上例大同小异。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值