注入过程中UNION在不同环境的使用注意事项

注入过程中UNION在不同环境的使用注意事项

2010-08-18 11:23:10
标签: sql  union  休闲  注入  职场
http://ynhu33.blog.51cto.com/412835/378872
原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://ynhu33.blog.51cto.com/412835/378824

注入过程中经常会遇到UNION,很多人使用时会报错,主要是不熟悉UNION的使用规则,以下分别对UNION在不同数据库下的使用注意事项解说。
1.关于UNION 与 ORDER BY
    1.1 SQL SERVER
        在SQL SERVER中,只有最后一个SELECT子句允许有ORDER BY 。前面的任何SELECT子句都不能有。
        比如:
        select name from a order by id union select content from b  
        会报在关键字UNION附近有语法错误。
        order by 只能加在最后的select 的后面,改成这样:
        select name from a union select content from b order by id  
        这样就正确了。
    1.2 ACCESS
        ACCESS中没有强制要求ORDER BY 只能出现在最后一个SELECT子句中,所以
        select name from a order by id union select content from b 
        在ACCESS中可以正确运行。
    1.3 MYSQL
        MYSQL与SQL SERVER一样,强制要求ORDER BY 只能出现在最后一个SELECT子句中。
        如果出现在了前面,会报错
        ERROR 1221 (HY000): Incorrect usage of UNION and ORDER BY
2.关于UNION 与FROM
     2.1 SQL SERVER
        只要UNION连接的几个查询的字段数一样且列的数据类型转换没有问题,就可以查询出结果。
        下面这样的查询也是可以的:
        select 1 union select 2;   
    2.2 ACCESS
        ACCESS的UNION好像强制要求它所连接的查询只能是select xxx from table的这种形式,
        select 1 union select 2 这种查询在ACCESS里面执行的话会提示“查询输入必须包含至少一个表或者查询”
        要将查询改成:
        select 1 from table union select 2 from table  
        查询才能成功。
        但是如果不用union,只是执行select 1,是允许的。
    2.3 MYSQL
        与SQL SERVER基本一样。唯一不一样的地方就是,如果后面跟了where,就一定要跟from
        select 1 where 1=1; 在mysql里面是会报错的,但是在sql server里面没有错误。
        要改成
        select 1 from table where 1=1;
3.关于数据类型的转换
    3.1 SQL SERVER
        SQL SERVER的数据类型转换是有优先级的,低优先级的会向高优先级的进行转换。
        而并不是第一个SELECT的数据类型为准。
        比如:
        select 1,'f' union select 1,2   
        上面的语句会报错,将varchar值'f'转换为......
        这证明了转换不是以第一个SELECT列的数据类型为准的,虽然最终生成的列名是以第一个SELECT所用的列名为准。
        下面是摘自SQL SERVER联机丛书的:
        数据类型的优先顺序
        当两个不同数据类型的表达式用运算符组合后,数据类型的优先顺序规则确定哪种数据类型要向另一种转换。
        优先顺序低的数据类型向优先顺序高的数据类型转换。如果此转换不是所支持的固有转换,则返回错误。
        当两个操作数表达式有相同的数据类型时,运算的结果就为那种数据类型。
        下面是 Microsoft SQL Server 2000 数据类型的优先顺序:
        sql_variant(最高)
        datetime
        smalldatetime
        float
        real
        decimal
        money
        smallmoney
        bigint
        int
        smallint
        tinyint
        bit
        ntext
        text
        image
        timestamp
        uniqueidentifier
        nvarchar
        nchar
        varchar
        char
        varbinary
        binary(最低)
        可以发现varchar比int的优先级低,所以varchar会向int进行转换,而不是int向字符串进行转换。

      遇到这种情况可以使前面的查询结果为空就可以规避数据类型转换的报错,顺利执行第二个查询了。
   3.2 Access
        我没发现ACCESS在使用UNION的时候会有数据类型转换的问题,好像任何类型的字段都可以UNION在一起。
   3.3 MYSQL
        MYSQL我没找到什么讲的比较清楚的类型转换的文章。
        只简单地说一下,在字符器转换为数字类型的时候,会从字符串的第一个字符开始转换,直到遇到非数字为止。
        比如7sie32 转成数字就是7,8732ds8转换数字就是8732
        如果第一个字符就是非数字,就转换结果就是0。
        在一些低版本的MYSQL中,下面这个查询:
        select 1 union select 'a';   
        得到的结果是1 0,a被转换成0了。
        不过这个问题在4.1以后的版本就没有了。
        新版本的MYSQL具体是怎么转换的不太清楚,不过好像它会自动寻找合适的数据类型。然后将UNION的那些列进行转换。
        也就是说我们基本上不用考虑它在UNION时的数据类型转换问题。



在注射的时候,access和mysql环境下,我们通常是通过union来获取数据的。但是遇到mssql环境,union很多时候都行不通,如果页面不报错,openrowset不可用,往往时候就只有暴力了。这样多不好,大家都是文明人,怎么可以用这么野蛮的手段呢?研究了一下,mssql中的union选择主要有以下几个方面的限制。
第一个是varchar/nvarchar和int类型的字段union到一起会强制转换出错。这个可以去看superhei大牛N久以前的文章,用and 1=2 把union前面的结果集置空就可以解决了。
第二个是当前面语句选择的字段有text、ntext 或者image格式的时候,不能用DISTINCT 方式来选择,而带union的语句必然是以DISTINCT 方式来选择的。这也是为什么很多搜索型的注射点可以用union猜解的原因,因为搜索点的语句很少会选到前面三种格式的字段。Image是二进制格式,一般不会出现在需要回显的sql语句中。这种限制前段时间也看到牛淫给出了解决方法,union后面跟一个all,即union all就搞定了。真是神奇啊,牛淫就是牛淫。
最后还有一个限制是text/ntext 与 int类型的字段 union到一起时并不兼容,会报操作数类型冲突的错误,就算用1=2把union前面语句的结果置空也一样。前几天突然想到,union的时候我们经常用1,2,3……之类的常数来补齐相差的列数。这时候后面的语句选择的都是int类型的字段,遇到前面有text/ntext的字段当然会出错,如果加上引号呢,即'1’,'2’,'3’……的形式?这时候后面的字段都是char或者varchar的类型了,应该就不会出错了。如果注射点过滤了引号怎么办?因为mssql对16进制格式的支持不是太好,很多地方用16进制必须declare――set,那就用char吧,即and 1=2 union all select char(49),char(50)……的形式。
本地测试一下,完全成功:

你可能感兴趣的:(Web安全)