zoukankan      html  css  js  c++  java
  • 宽字节注入和防御

    0、前言

    最近要为了自动化审计搜集所有PHP漏洞,在整理注入的时候,发现宽字节注入中使用iconv造成的漏洞原理没有真正搞懂,网上的文章也说得不是很清楚,于是看了荣哥(lxsec)以前发的一篇http://www.91ri.org/8611.html,加上我们两个人的讨论,最终有了这一篇深入的研究成果。

     

    1、概述

    主要是由于使用了宽字节编码造成的。,典型情景是网站使用GBK编码,数据库使用UTF-8编码

    什么是字符集?

    计算机显示的字符图形与保存该字符时的二进制编码的映射关系。

    如ASCII中,A(图形)对应编码01000001(65)。

    对于MYSQL数据库来说,涉及字符集的地方大致分为存储和传输时,即:

    (1)存储在服务器端的数据是何种编码

    (2)客户端和服务器交互的时候数据传输使用的编码。

     

    2、MYSQL服务器端存储字符集

    在MYSQL服务器端进行数据存储时,允许在以下的级别设置字符集:

    (1)服务器端字符集(character_set_server)

    (2)库字符集

    (3)表字符集

    (4)字段字符集

    优先级为:字段----->表------->库-------->服务器

    对应的语法是:

    Create table test(  
    name varchar(20) charset gbk,  
    number varchar(10),  
    age int  
    )engine=innodb charset=utf-8 ;

    3、客户端与服务器交互数据传输的字符集

    存储时的字符集已经确定了,不会影响交互阶段的字符集。

    在MYSQL中,还有一个中间层的结构,负责客户端和服务器之间的连接,所以称为连接层。

    交互的过程如下:

    (1)客户端以某种字符集生成的SQL语句发送至服务器端,这个“某种字符集”其实是任意规定的,PHP作为客户端连接MYSQL时,这个字符集就是PHP文件默认的编码。

    (2)服务器会将这个SQL语句转为连接层的字符集。问题在于MYSQL是怎么知道我们传过来的这个SQL语句是什么编码呢?这时主要依靠两个MYSQL的内部变量来表示,一个是character_set_client(客户端的字符集)和character_set_connection(连接层的字符集)。可以使用show variables like ‘character_set_%’ ;进行查看。

    可以看到,这里的客户端字符集为GBK,连接层字符集也是为GBK。

    两者相同,就不会有问题,如果不一致,就会出现乱码问题了。

    使用MYSQL中的set命令可以对这些内部变量做设置,如修改客户端编码为UTF-8;

    set character_set_client = UTF-8

    (1)服务器将转换好的SQL语句,转为服务器内部编码与存储在服务器上的数据进行交互

    (2)服务器处理完之后,将结果返回给客户端,还是转为服务器认为客户端可以认识的编码,如上图的GBK,使用character_set_results来确定返回客户端的编码。

    平时在PHP中写的set names UTF-8相当于下面三条同时执行:

    (1)set character_set_client = UTF-8

    (2)set character_set_connection = UTF-8

    (3)set character_set_results = UTF-8

     

    4、乱码问题原理

    设置三个字符集相同,这也就不会出现乱码的真正原理。网页上有时会出现乱码是因为PHP动态文件将数据打印到浏览器的时候,浏览器也会按照一定的字符集进行判断,如果PHP的响应数据编码和浏览器编码一致,就不会出现乱码,否则就出现乱码。可以通过在PHP中使用header()来指定这个响应数据的编码。

     

    5、宽字节注入原理

    有三种形式:

    (1)情景一:在PHP中使用mysql_query(“set names GBK”);指定三个字符集(客户端、连接层、结果集)都是GBK编码。

    情景代码: 

     

    mysql_query(“set names GBK”);  
    $bar = addslashes($_GET[‘bar’]) ;  
    $sql = “select password from user where bar=’{$bar}’”;  
    $res = mysql_query($sql) ;  

    提交:http://127.0.0.1/foo.php?bar=admin%df%27

    这时,发生如下转换:

    %df%27=====(addslashes)======>%df%5c%27======(GBK)======>運’

    带入sql为:

    Select password from user where bar=‘運’

    成功将单引号闭合。为了避免漏洞,网站一般会设置UTF-8编码,然后进行转义过滤。但是由于一些不经意的字符集转换,又会导致漏洞。

     

    (2)情景二:

    使用set names UTF-8指定了UTF-8字符集,并且也使用转义函数进行转义。有时候,为了避免乱码,会将一些用户提交的GBK字符使用iconv函数(或者mb_convert_encoding)先转为UTF-8,然后再拼接入SQL语句。

    情景代码:

     

    mysql_query(“set names UTF-8”) ;  
    $bar =iconv(“GBK”,”UTF-8”, addslashes($_GET[‘’bar])) ;  
    $sql = “select password from user where bar=’{$bar}’” ;  
    $res = mysql_query($sql) ;  

    我们可以看到,为了使得SQL语句中的字符集保持一致,一般都会使用iconv等字符集转换函数进行字符集转换,问题就是出在了GBK向UTF-8转换的过程中。

    提交:http://127.0.0.1/foo.php?bar=%e5%5c%27

    变换过程:(e55c转为UTF-8为e98ca6)

    e55c27====(addslashes)====>e55c5c5c27====(iconv)====>e98ca65c5c27

    可以看到,多出了一个5c,将转义符(反斜杠)本身转义,使得后面的%27发挥了作用。

    测试如下:



     

    (3)情景三:使用iconv进行字符集转换,将UTF-8转为GBK,同时,set names字符集为GBK。提交%e9%8c%a6即可。

    这个情景的大前提是先编码后转义:

    e98ca6====(iconv)=====>e55c=====(addslashes)====>e55c5c

    同样可以多出一个反斜杠进行利用,在此不再详述,因为漏洞条件比较苛刻。

     

     

    6、安全方案

    对于宽字节编码,有一种最好的修补就是:

    (1)使用mysql_set_charset(GBK)指定字符集

    (2)使用mysql_real_escape_string进行转义

    原理是,mysql_real_escape_string与addslashes的不同之处在于其会考虑当前设置的字符集,不会出现前面e5和5c拼接为一个宽字节的问题,但是这个“当前字符集”如何确定呢?

    就是使用mysql_set_charset进行指定。

    上述的两个条件是“与”运算的关系,少一条都不行。

    测试;

    输出:

     

     

    转自http://write.blog.csdn.net/postedit/42874517

     

     
  • 相关阅读:
    Unable To Open Database After ASM Upgrade From Release 11.1 To Release 11.2
    11g Understanding Automatic Diagnostic Repository.
    How to perform Rolling UpgradeDowngrade in 11g ASM
    Oracle 11.2.0.2 Patch 说明
    Pattern Matching Metacharacters For asm_diskstring
    Steps To MigrateMove a Database From NonASM to ASM And ViceVersa
    Upgrading ASM instance from Oracle 10.1 to Oracle 10.2. (Single Instance)
    OCSSD.BIN Process is Running in a NonRAC Environment
    Steps To MigrateMove a Database From NonASM to ASM And ViceVersa
    On RAC, expdp Removes the Service Name [ID 1269319.1]
  • 原文地址:https://www.cnblogs.com/drkang/p/8644435.html
Copyright © 2011-2022 走看看