用户
搜索
  • TA的每日心情
    开心
    7 小时前
  • 签到天数: 193 天

    连续签到: 2 天

    [LV.7]常住居民III

    i春秋作家

    Rank: 7Rank: 7Rank: 7

    63

    主题

    127

    帖子

    3258

    魔法币
    收听
    0
    粉丝
    8
    注册时间
    2020-10-2

    积极活跃奖

    发表于 2021-7-29 10:01:12 01653
    本帖最后由 Johnson666 于 2021-8-5 16:55 编辑

    sqli-labs学习sql注入——宽字节注入篇

    本篇文章作者Johnson666,本篇文章参与i春秋作家连载计划所属从0到1团队,未经许可禁止转载。连载方向:web安全,内网安全

    目录

    1.sqli-labs学习sql注入——MySQL注入相关知识点+联合注入篇

    2.sqli-labs学习sql注入——GET和POST盲注篇+sql传马篇+增删改注入篇

    3.sqli-labs学习sql注入——绕过篇

    4.sqli-labs学习sql注入——HTTP头部注入篇

    5.sqli-labs学习sql注入——宽字节注入篇

    6.sqli-labs学习sql注入——堆叠注入篇

    7.sqli-labs学习sql注入——排序注入和排序堆叠注入篇

    8.sqli-labs学习sql注入——最后的挑战

    1.宽字节注入的知识点

    在旧版本的 MySQL 安装时,会有编码问题导致中文乱码,需要手动设置编码为 UTF-8,可看这里:手动设置编码为 UTF-8。而安装 MySQL 5.7 时并没有出现这个问题,默认编码已经是 UTF-8。

    SHOW VARIABLES LIKE 'character%';

    PHP 自带一些转义特殊字符的函数,如addslashes()mysql_real_escape_string()mysql_escape_string()等,这些函数可用来防止 SQL 注入。Less-17有具体讲这些函数,这里就不赘述了。

    id=1'or'1'='1,单引号本用来闭合语句,这些函数会自动转义这些闭合的单引号,在这些单引号前面加上转义符\,变为1\'or\'1\'=\'1,如此在 SQL 查询中仍然一个普通的字符串,不能进行注入。

    而网站在过滤'的时候,通常的思路就是将'转换为\',将'转义,因此我们在这里想办法要绕过这个转义处理,使单引号发挥作用,一般有两种思路:

    1. 让反斜杠(\)失去作用
    2. 让反斜杠(\)消失

    第一个思路就是借鉴程序员的防范思路,对反斜杠(\)转义,即将 \' 中的 \ 过滤掉,使其失去转义单引号的作用,成为‘内容’。例如可以构造 %5c%5c%27(\\')的情况,后面的%5c会被前面的%5c给注释掉。

    如果源代码中不是用上面那些转义特殊字符的函数,而是自定义的过滤函数:像遇到单引号'加上反斜杠\这样,而遇到反斜杠\不会转义,是可以用这个思路来绕过;但是如果用的是上面那些转义特殊字符的函数似乎都也会把反斜杠\转义,所以基本都是用第二个思路。

    第二个思路就是宽字节注入:

    原理:mysql在使用GBK编码的时候,会认为两个字符为一个汉字,例如%aa%5c就是一个汉字(前一个ascii码大于128才能到汉字的范围),URL解码为:。我们在过滤' 的时候,往往利用的思路是将 '转换为\'(转换的函数或者思路会在每一关遇到的时候介绍)。
    因此我们在此想办法将'前面添加的 \ 除掉:
    %df吃掉\ 具体的原因是urlencode(') = %5c%27,我们在%5c%27前面添加%df,形成%df%5c%27,而上面提到的mysql在GBK编码方式的时候会将两个字节当做一个汉字,此时%df%5c就是一个汉字,%27则作为一个单独的符号在外面,同时也就达到了我们的目的。

    其中%df也可以换成%bb,%aa等,因为\的url编码为%5c,宽字节注入实质上就是让将单引号转义处理的\消失,那么%aa%5c%27URL解码为:猏';%bb%5c%27URL解码为:籠'等等,所以他们都可以。具体可以到这个网站自己编码下:URL编码的解码(GBK) (mytju.com)

    Less-32:基于错误-GET-单引号-字符型-转义引号反斜杠-宽字节注入

    mysql_query("SET NAMES gbk");
    $id = check_addslashes($_GET['id']);
    function check_addslashes($string)
    {
        $string = preg_replace('/'.preg_quote('\\').'/',"\\\\\\",$string);      //escape any backslash
        $string = preg_replace('/\'/i','\\\'',$string);                         //escape single quote with a backslash
        $string = preg_replace('/\"/',"\\\"",$string);                          //escape double quote with a backslash
        return $string;
    }

    可以看到这个函数是个过滤\'"的函数,分别在前面加上\

    利用上述的原理,我们可以构造payload为:http://127.0.0.1/sqli-labs-master/Less-32/?id=-1%df%27union%20select%201,version(),3--+,得到数据库版本

    Less-33:基于错误-GET-单引号-字符型-addslashes()-宽字节注入

    Less-32是自定义的过滤函数,而这一关是直接使用了 PHP 的addslashes()函数,前面也有介绍过了,这里就不赘述,但是要注意一个点:

    使用addslashes(),我们需要将mysql_query设置为binary的方式,才能防御此漏洞。
    Mysql_query(“SET character_set_connection=gbk,character_set_result=gbk,character_set_client=binary”,$conn);

    本关的payload和上一关是一样的:

    我们可以构造payload为:http://127.0.0.1/sqli-labs-master/Less-33/?id=-1%df%27union%20select%201,version(),3--+,得到数据库版本

    Less-34:基于错误-POST-单引号-字符型-addslashes()-宽字节注入

    这一关是post型的注入漏洞,同样的也是将post过来的内容进行了 \的处理。由上面的例子可以看到我们的方法就是将过滤函数添加的 \给吃掉。而get型的方式我们是以url形式提交的,因此数据会通过URLencode,如何将方法用在post型的注入当中,我们这里不能像get型那样直接加上%df。这边用万能密码来尝试,我们来看看直接加上%df

    用户名输入admin%df' or 1=1#,密码随便输:

    可以发现这里会把我们输入的%df中的%给url编码成%25

    那么我们要手动把%2525给删除,留下%,然后再Go一下,可以看到成功了

    这里还有一种方法,就是将utf-8转换为utf-16或 utf-32,例如将'转为utf-16为 �' 。这个字符我不知道是啥,这里在该网站上转换:Unicode和UTF编码转换。得到如此结果:

    我们可以利用这个方式进行尝试:

    payload:admin�' or 1=1#

    成功

    Less-35:基于错误-GET-数字型-addslashes()-宽字节注入

    function check_addslashes($string)
    {
        $string = addslashes($string);
        return $string;
    }

    这一关很点题:why care for addslashes(),因为数字型注入根本不需要在乎是否被addslashes(),我们就没有必要去考虑check_addslashes()函数的意义了。

    payload:http://127.0.0.1/sqli-labs-master/Less-35?id=-1%20%20union%20select%201,user(),3--+,显示当前登陆的用户名与它对应的host

    Less-36:基于错误-GET-单引号-字符型-mysql_real_escape_string()-宽字节注入

    function check_quotes($string)
    {
        $string= mysql_real_escape_string($string);   
        return $string;
    }

    check_quotes()函数是利用了mysql_real_escape_string()函数进行的过滤。
    mysql_real_escape_string()函数转义 SQL 语句中使用的字符串中的特殊字符。Less-17有详细讲解,这里就不赘述了。

    payload:http://127.0.0.1/sqli-labs-master/Less-36?id=-1%df%27union%20select%201,current_user(),3--+,显示当前登陆用户对应在user表中的哪一个

    Less-37:基于错误-POST-单引号-字符型-mysql_real_escape_string()-宽字节注入

    本关与Less-34是大致相似的,区别在于处理post内容用的是mysql_real_escape_string()函数,而不是addslashes()函数。

    因为这两个函数都会过滤'\,所以这里完全可以用Less-34的方法来进行注入,这里就不赘述了。

    发新帖
    您需要登录后才可以回帖 登录 | 立即注册