5. 宽字符注入详解与实战

宽字节注入源于程序员设置MySQL连接时的错误配置,如下:

set character_set_client=gbk

这样的配置会引发编码转换从而导致绕过某些防护实现注入漏洞。具体分析一下原理:

  1. 正常情况下GPC开启或者使用addslashes函数过滤GET或POST提交的参数时,我们测试输入的‘,就会被转义为\‘;
  2. 若存在宽字节注入,输入%df%27时,经过单引号的转义变成了%df%5c%27,之后再数据库查询语句进行GBK多字节编码,即一个中文占用两个字节,一个英文同样占用两个字节且在汉字编码范围内两个编码为一个汉字。然后MySQL服务器会对查询语句进行GBK编码即%df%5c转换成汉字"運",单引号逃逸出来,从而绕过转义造成注入漏洞。

现在基本都会将mysql的连接配置设置为:

[set character_set_client=binary]

来解决这个问题,这篇博客将介绍php中因为编码或字符编码转换导致的注入问题。

mysql中的宽字符注入

测试搭建学习的环境利用了phithon内容管理系统,看代码

SQL语句是SELECT * FROM news WHERE tid=‘{$id}‘,根据文章的id把文章从news表中提取出来,在$sql之前,我们只用了限制函数addslashes函数,对$id进行转义,只要我们输入参数在单引号中,就逃逸不出单引号的限制,从而无法注入。

我们这里利用的是mysql的一个特性,mysql在使用GBK编码的时候,会认为两个字节是一个汉字(前一个ascii码要大于128,才到汉字范围),我们测试输入%df‘

已经报错,看到报错,说明sql语句出错,看到出错说明可以注入。报错的原因就是多了一个单引号,而单引号前面的反斜杠不见啦。这就是mysql的特性,因为gbk是多字节编码,它认为两个字节代表一个字符,所以%df和后面的%5c变成了汉字“運”,而’逃逸了出来。

因为是两个字节代表一个汉字,我们尝试%df%df%27

不报错了,因为%df%df组成了汉字"哌",%5c%27不是汉字,仍然是\‘

mysql如何判断一个字符是不是一个汉字,根据gbk编码,第一个字节的ascii码大于128,基本上就行,若不用%df而用%a1也可以

%a1%5c虽然不是一个汉字,但一定会被mysql认为是一个宽字符,所以就能让后面的%27逃逸出来,构造一个exp,查询管理人员的账号密码。

GB12和GBK的区别

gb2312和gbk都是宽字节家族医院,但是当把数据库编码设置为关闭gb2312时,结果就不能注入

这主要是gb2312编码取值范围的事情,它高位范围0xA1~0xF7,低位范围是0xA1~0xFE,\是%5c,是不在低范围中的,即其根本不是gb2312遍吗,故其不会被吃掉。故只要低位的范围中含有0x5c的编码,就可以进行宽字节的注入

利用mysql_real_escape_string解决问题

一些cms把addslashes替换为mysql_real_escape_string来防止宽字节的注入

我们若解决需要做的指定php连接mysql的字符集。我们需要在执行sql语句之前调用一下mysql_set_charset函数,设置当前的字符集为gbk,来避免问题

宽字节注入修复

character_set_client=‘binary‘设置为binary(二进制),只需要在所有的sql语句前指定一下连接的形式为二进制:mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $conn);,当我们的mysql接受到客户端的数据后,会认为他的编码是character_set_client,然后会将换成character_set_connection的编码,然后在进入具体表和字段后,再转换成字段对应的编码,然后当查询结果产生后,会从表和字段编码,转换成character_set_results编码,返回给客户端。

这个方法避免宽字节的注入还是有效的,但是如果开发者画蛇添足的增加一些东西,会让前期的努力前功尽弃。

iconv造成的严重后果

很多cms会将接收到的数据,调用这样一个函数,转换其编码:iconv(‘utf-8‘,‘gbk‘,$_GET[‘id‘]);,目的一般是避免乱码,特别是搜索框的位置

可以发现,在sql语句执行前,将character_set_client设置成了binary,所以避免宽字节的注入问题。但之后其调用了iconv将已经过滤的参数$id给转换了一下,测试一下

报错说明我们錦被iconv从utf-8转换成gbk后,变成了%e5%5c,而后面的‘被addslashes变成了%5c%27,这样组合起来就是%e5%5c%5c%27,两个%5c就是\,正好把反斜杠转义了,导致‘逃逸出单引号,产生注入。利用的是将\转移掉。

利用iconv将gbk转换成utf-8,则可以直接用宽字节注入的姿势来。gbk汉字2字节,utf-8汉字是3字节,若把gbk转换成utf-8,则php会每两个字节一转换。所以,如果\’前面的字符是奇数的话,势必会吞掉\,’逃出限制。

总结

  1. gbk编码造成的宽字符注入问题,解决方法是设置character_set_client=binary。
  2. 矫正人们对于mysql_real_escape_string的误解,单独调用set name=gbk和mysql_real_escape_string是无法避免宽字符注入问题的。还得调用mysql_set_charset来设置一下字符集。
  3. 谨慎使用iconv来转换字符串编码,很容易出现问题。只要我们把前端html/js/css所有编码设置成gbk,mysql/php编码设置成gbk,就不会出现乱码问题。不用画蛇添足地去调用iconv转换编码,造成不必要的麻烦。

代码审计实战

对骑士cms审计时发现在plus/ajax_street.php

在之前配置文件设置的是mysql_query("SET character_set_connection=" . $dbcharset . ", character_set_results=" . $dbcharset . ", character_set_client=binary", $this->linkid);,其中利用了iconv函数造成致命的错误,同时分析发现页面将查询结果回显回来,构造一些union的查询语句即可获取数据库的敏感信息

漏洞的利用

测试有几个字段,发现category表一共有9个字段,所以可以构造获取数据库用户和先关信息的exp

然后利用union的查询语句爆出可利用的列为4,8,exp:

http://localhost/74cms/upload/plus/ajax_street.php?act=key&key=-%e9%8c%a6‘ union select 1,2,3,4,5,6,7,8,9-- -),

然后是爆出数据库和用户名等相关信息

补充

GBK编码中的两个字符是一个汉字,第一个字符需要大于128

----------------文章转载自微信公众号---信安之路

原文地址:https://www.cnblogs.com/bmjoker/p/9134830.html

时间: 2024-10-07 21:41:24

5. 宽字符注入详解与实战的相关文章

宽字节注入详解

前言 在mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性. 首先,宽字节注入与HTML页面编码是无关的,笔者曾经看到 <meta charset=utf8> 就放弃了尝试,这是一个误区,SQL注入不是XSS.虽然他们中编码的成因相似,不过发生的地点不同. 很多网上的材料都说程序使用了宽字节来处理程序,却又不指出具体是指什么

转宽字节注入详解

---恢复内容开始---   在mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等, 还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性. 首先,宽字节注入与HTML页面编码是无关的,笔者曾经看到 <meta charset=utf8> 就放弃了尝试,这是一个误区,SQL注入不是XSS.虽然他们中编码的成因相似,不过发生的地点不同. 很多网上的材料都说程序使用了宽字节来处理程

Python字符编码详解(转)

1. 字符编码简介 1.1. ASCII ASCII(American Standard Code for Information Interchange),是一种单字节的编码.计算机世界里一开始只有英文,而单字节可以表示256个不同的字符,可以表示所有的英文字符和许多的控制符号.不过ASCII只用到了其中的一半(\x80以下),这也是MBCS得以实现的基础. 1.2. MBCS 然而计算机世界里很快就有了其他语言,单字节的ASCII已无法满足需求.后来每个语言就制定了一套自己的编码,由于单字节

iptables详解加实战

iptables 组件是一种工具,也称为用户空间(userspace),它使插入.修改和除去信息包过滤表中的规则变得容易.分为四个表和五个链,其中表是按照对数据包的操作区分的,链是按照不同的Hook点来区分的,表和链实际上是netfilter的两个维度. 4个表:filter,nat,mangle,raw,默认表是filter(没有指定表的时候就是filter表).表的处理优先级:raw>mangle>nat>filter. filter:一般的过滤功能,如不-t指定表,则默认filte

Sql 注入详解:宽字节注入+二次注入

sql注入漏洞 原理:由于开发者在编写操作数据库代码时,直接将外部可控参数拼接到sql 语句中,没有经过任何过滤就直接放入到数据库引擎中执行了. 攻击方式: (1) 权限较大时,直接写入webshell 或者直接执行系统命令 (2) 权限较小时,通过注入获得管理员密码信息,或者修改数据库内容进行钓鱼等 常出现的地方: 登录页面.获取HTTP头(user-agent.client-ip等).订单处理等,HTTP头里面client-ip 和 x-forward-for 常出现漏洞,在涉及购物车的地方

SQL注入详解-转发

转发自飞天小子如有侵权请联系删除 1:什么是SQL注入 SQL注入是一种将SQL代码插入或添加到应用(用户)的输入参数中的攻击,之后再将这些参数传递给后台的SQL服务器加以解析并执行. www.xx.com/news.php?id=1 www.xx.com/news.php?id=1 and 1=1 这里我们来理解一下SQL注入 首先,SQL注入常年蝉联OWASP排行榜第一名~ SQL注入产生的过程是怎样的呢?见下图 SQL注入的危害有哪些呢? 数据库信息泄露 网页篡改 网站被挂马 数据库被恶意

Mysql 字符函数详解

MySql 所有字符串函数函数详解 ASCII(str) 返回str最左边第一位字符的ASCII编码,如果str为空,则返回 0 .如果str为NULL,则返回NULL -- 只返回a的ASCII编码 SELECT ASCII('ab') - 97 SELECT ASCII('a') - 97 -- 如果是数字,带不带引号是一样的效果 SELECT ASCII(23) - 50 SELECT ASCII(2) - 50 SELECT ASCII('2') - 50 BIN(N) 返回N的二进制数

log4j详解与实战

log4j是一个非常强大的log记录软件,下面我们就来看看在项目中如何使log4j. 首先当然是得到log4j的jar档,推荐使用1.2.X版,下载地址: http://logging.apache.org/log4j/1.2/download.html 我们先看一个最简单的示例: [示例1] 项目结构: [注:由于这里的多个项目公用一个jar档,我们可以创建一个专门放置jar档的Java工程,然后将jar档放到lib目录下.在要使用的工程中按图所示进行引用 ] Java代码: Java代码  

AdaBoost算法详解与实战

[原创]Liu_LongPo 转载请注明出处 [CSDN]http://blog.csdn.net/llp1992 AdaBoost算法是基于单层决策树等弱分类算法的强学习分类算法.单层决策树算法也是一种分类算法,但是其分类效果较差,只根据一个特征进行数据划分,因此单层决策树算法被称为弱分类算法:而AdaBoost算法通过将多个弱分类算法串行训练而成,属于强分类算法. AdaBoost算法是boosting算法的一种,它所串联的弱分类器一般都是一致的,而且它训练是的关注点在于被之前分类器分错的数