白话宽字节注入-以彼之道,还施彼身

白话宽字节注入

各位看官,在正式了解宽字节注入前,我先介绍几个概念:

简单概念

  • 宽字节:两个字节,代表宽字节编码。
  • 宽字节注入属于sql注入攻击。
  • 字符编码:ASCII:127个字符,每个字符用一个字节表示 ,Unicode:最常用的两个字节表示一个字符,如果非常生僻的字符用4个字节表示, UTF-8:根据unicode字符根据不同的数字大小编成1-6个字节,常用的英文的字母为1个字节,汉字通常3个字节或者4-6字节(生僻字)。计算机内存中统一使用unicode编码。GBK:包含全部中文字符,字符均使用双字节表示,为区分中文,最高位都为1.

故事主角

王姑娘:熟悉各种web攻击原理。
慕容姑娘:刚学会sql注入,最近一直被宽字节注入所困扰。

宽字节注入产生的原因

  • 王:慕容姑娘,假如给你一个存在字符型注入漏洞的url你会怎么进行注入攻击?
    慕容:很简单嘛,利用单引号,双引号等特殊字符,来闭合原sql语句中的单或双引号,使得自己注入的代码得以执行。

  • 王:既然简单,开发者肯定也会想到你会这么做,为了防御这种情况,会通过使用转义字符(addslashes函数)使单双引号无效,这样你输入的非法sql语句就没用了。
    慕容:啊,那我之前学的不是都没用武之地了。。。
    王:哈哈,这就被吓倒了?难道你忘了你慕容家的绝学:以彼之道,还施彼身吗,既然他用转义字符使得你的单/双引号无效,那你想办法把他加入的转义字符变得无效不就行了吗?

  • 慕容:话是这么说,sql语句是由英文字母组成一个字节就可以表示,每个字节都表示对应字符,要怎么使转义字符无效呢?

  • 王:的确,在ASCII编码中,每个字节表示一个字符,但是在咱们中文编码GBK中,是两个字节表示一个字符。而转义字符的十六进制:0x5c,单引号十六进制:0x27 在GBK编码中,0xbf5c这两个字节会被当做一个字符,即咱们的中文字“縗”,所以假如你输入0xbf27 or 1=1客户端检查到你输入了单引号0x27,便在单引号前加入转义字符0x5c,于是客户端提交给服务端便是0xbf5c27 or 1=1假如此时mysql数据库采用GBK编码,0xbf5c成了一个字符“縗”,转义字符0x5c不能起到转义的作用,你输入的单引号0x27依然有效,注入攻击就成功啦!

  • 慕容:原来如此,不过如果数据库中不采用GBK编码,我输入的单/双引号依旧不是依旧会被转义。

  • 王:没错,所以编码不统一就是宽字节注入产生的原因之一,防御sql注入,一定要注意编码问题。
    在 mysql中数据的存储和传输涉及到字符集和编码:因此要特别注意存储在服务器端的数据编码形式(设置字符集的优先级:字段-表-库-服务器),客户端与服务器端交互时数据的编码形式。
    此外,mysql中有一个中间层(连接层),负责客户端和服务器间的连接。
    (1)当你输入构造的注入语句时,客户端会根据某种字符集将你输入生成相应SQL语句发送至服务器端,这个“某种字符集”其实是任意规定的,PHP作为客户端连接MYSQL时,这个字符集就是php文件默认的编码。
    (2)服务器会将这个SQL语句转为连接层的字符集。服务器将转换好的SQL语句,转为服务器内部编码与存储在服务器上的数据进行交互。
    (3)服务器处理完之后,将结果返回给客户端,使用character_set_results来确定返回客户端的编码。 整个过程涉及到三个编码,并用以下三个变量表示: character_set_client(客户端), character_set_connection (连接层),character_set_results(结果集)

  • 慕容:不愧是运用我慕容家绝学:开发者想给我输入的单/双引号等特殊字符前加入转义字符让我构造的sql语句无效,而我则利用他客户端,连接层,结果集编码不统一,构造输入吃掉转义字符,让我输入的单/双引号等特殊字符依然有效。

  • 王:Bingo

有什么危害

  • 宽字节注入就是让你成功执行sql注入,所以它产生的危害跟sql注入一样。

如何防御

(1) 统一字符编码,使用mysql_set_charset:指定字符集。

(2)使用mysql_real_escape_string进行转义,与addslashes不同,前者会考虑当前设置的字符集(mysql_set_charset),不会出现将e5和5c拼接。 注意:转编码函数(iconv)同样会引起宽字节注入,即使使用了安全的设置函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值