心得体会---宽字节注入

作者:yzc    发布于:

宽字节注入心得体会

转载了p神的一篇写宽字节注入的,本来想自己总结,可是看了p神的文章后觉得写得太棒了,就转载了!

读完p神的文章后,也对宽字节注入有了一个大体的了解:

0x01 在什么情况下我们可能会使用宽字节注入来绕过
(1)存在 GBK 编码(这里说的比较含糊是因为宽字节注入可能是因为mysql的特性问题,也有可能是PHP本身的问题,在下面的原理中会详细说明)

(2)PHP 开启 magic_quotes_gpc 函数、使用 addslashes 函数、错误使用mysql_real_escape_string函数,或者使用 iconv 函数。
0x02 产生原因:

在知道了什么情况下我们可能利用宽字节注入后,接下来就是宽字节注入的原理了,产生宽字节注入的原因主要有两个:

(1)利用了 mysql 的特性:

mysql 在使用 GBK 编码的时候会认为两个字符是一个汉字(前一个字符的 ASCII 码值要大于128,才能进入汉字范围)

那么只要我们在构造的语句中加入 %df 、%aa 等这样的字符(0×81-0xFE都可以选择),这些字符就会和转义字符 \ 形成一个 GBK 编码认为的汉字,即使我们加入的符号和 \(%5c) 构成的不是一个汉字,可是 GBK 编码还是会将其合并在一起进行编码,这样注意字符 \ 就被除掉了,' 得以逃逸出来。这样就绕过了像 magic_quotes_gpc函数、addslashes 函数等函数的限制

(2)利用了 PHP 的函数 iconv 函数

iconv 函数引发的宽字节注入问题就和 mysql 没有关系了,有的时候针对于宽字节注入的防护做的非常好(具体防护问题后面细说),可是就是由于有些程序员为了避免乱码,使用了 iconv 函数(搜索框位置出现频繁)再次导致了宽字节注入的发生:

1' `iconv('utf-8', 'gbk', $变量);` 情况下,即将变量由 utf-8 的编码格式转换成 gbk 编码格式。

我们利用宽字节注入就是想绕过诸如 magic_quotes_gpc函数、addslashes 函数的限制,使这些函数对我们自己加入的 ' 失效,以达到注入的效果,iconv函数这样使用过后导致宽字节注入的情况比较特殊,特殊的地方在于只有少数的汉字的 GBK 编码的第二个字节是 %5C ,只有这样的汉字经过这样的转换才可以导致宽字节注入,0×81-0xFE 开头 + 0×5C 的字符都可以

2' `iconv('gbk', 'utf-8k', $变量);` 情况下,即将变量由 gbk 的编码格式转换成 utf-8 编码格式。

在这种情况下问题还是出现在 PHP 身上,因为 GBK 编码表示一个汉字使用两个字节,而 utf-8 编码表示一个汉字使用三个字节,如果把 GBK 转换成 utf-8 则 PHP 会每两个字节一转换。根据这个原理,如果我构造的语句中 ' 前面的字符数是奇数的话,在从 GBK 向 utf-8 转换的过程中 \ 势必会被我们前面添加的字符合并,使得 \ 被吞掉。

由 PHP 的 iconv('gbk', 'utf-8k', $变量); 导致的宽字节注入,在注入语句的构造方面和由 mysql 特性造成的宽字节注入语句是一致的,可是形成的原因却并不相同:一个是由 mysql 的特性造成的,而另一个则是由 PHP 函数的误用造成的。由 mysql 特性导致的宽字节注入可以在做好防护使宽字节注入不再发生;而由 PHP iconv 函数造成的问题是因为函数的误用导致的,如果误用了就会造成宽字节注入

0x03 宽字节注入的流程

1.先尝试加 ' ,尝试无果后猜测 ' 可能被转义了,于是尝试在 ' 前加上 %df 、%aa 等字符尝试是否存在宽字节注入,如果报错则可能为宽字节注入

2.若尝试无果,则尝试在 ' 前加 这样的汉字,如果报错则可能为宽字节注入

0x04 对于宽字节注入的修复

对于宽字节注入的修复主要有两种方式

(1)使用 mysql_set_charset('gbk', $conn); + mysql_real_escape_string($_GET['id']);

mysql_set_charset 函数的作用是:设置 PHP 连接 mysql 的字符集

mysql_real_escape_string 函数的作用和 addslashes 函数的作用是一致的,是用来过滤输入的,而且还考虑到连接的当前字符集

mysql_set_charset 函数设置了 PHP 连接 mysql 的字符集,使得 mysql_real_escape_string 函数在过滤用户输入时考虑到这是 gbk 编码,以避免宽字节注入的产生

但是值得注意的是:如果我们不使用 mysql_set_charset 函数而是只单独使用 mysql_real_escape_string 函数是无法避免宽字节注入的,因为 PHP 连接 mysql 时无法得知连接的字符集,所以就无法进行安全的过滤输入

(2)使用 SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary

当我们的mysql接受到客户端的数据后,会认为他的编码是character_set_client,然后会将之将换成character_set_connection的编码,然后进入具体表和字段后,再转换成字段对应的编码。

然后,当查询结果产生后,会从表和字段的编码,转换成character_set_results编码,返回给客户端。

所以,我们将character_set_client设置成binary,就不存在宽字节或多字节的问题了,所有数据以二进制的形式传递,就能有效避免宽字符注入。

0x05 注意事项

1.GB2312 与 GBK 的不同

数据库的编码设置成 GBK 时,利用 mysql 的特性可以进行宽字节注入,但是如果数据库的编码设置成 GB2312 编码的话宽字节注入就不成功了。

原因在于:GB2312 编码的取值范围。高位取值范围是 0xA1~0xF7 ;低位范围是 0xA1~0xFE ,而 \0x5c0x5c 是根本不在 GB2312 的低位范围内的,\ 根本就不属于 GB2312 编码,所以 \ 是不会被吃掉的

2.iconv 函数的使用问题

iconv 函数的功能是转换字符串编码,避免乱码的产生,但是这个函数也可能直接导致宽字节注入,所以这个函数请谨慎使用。只要我们把前端html/js/css所有编码设置成gbk,mysql/php编码设置成gbk,就不会出现乱码问题。

0x06

以上就是我最近学习宽字节注入的心得体会,文章中的图片都是我自己用 xmind 做的,自己做图也算是对原理的理解吧,感觉这些天收获挺大的,一直先研究一下注入方面的知识,可是一直没落实到行动上,这次终于真真正正的学习了一把,感觉注入方面比较抽象,只有通过 页面的回显 + 源码的分析 才可能真正理解到原理所在。这些天的学习之后,感觉自己任重而道远,还有很多很多东西要去学习,技术永无止境,只有先把基础打牢之后才有可能深入的去学习更加深层次的东西。

虽然进行了总结,可是对于宽字节注入我还是有不理解的地方,我会继续在这方面学习,争取把自己不懂的地方都弄明白~~

format_list_numbered

(无)

  1. 1. 宽字节注入心得体会
    1. 1.1. 0x01 在什么情况下我们可能会使用宽字节注入来绕过
    2. 1.2. 0x02 产生原因:
    3. 1.3. 0x03 宽字节注入的流程
    4. 1.4. 0x04 对于宽字节注入的修复
    5. 1.5. 0x05 注意事项
    6. 1.6. 0x06
vertical_align_top

Copyright © 2017 yzc's blog

Powered by Hexo & Theme - Vateral