sql注入详解

Posted 红客突击队

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql注入详解 相关的知识,希望对你有一定的参考价值。

sql注入详解 (四)





9、绕过各种过滤

一些普通的防护措施是过滤

过滤注释和空格

检测

确认过滤了#http://10.10.10.139/sql/Less-26/?id=%231确认过滤了orhttp://10.10.10.139/sql/Less-26/?id=or1确认过滤多行注释符http://10.10.10.139/sql/Less-26/?id=/*1确认过滤了单行注释http://localhost/sqli-labs/Less-26/?id=--1 确认过滤了斜杠http://10.10.10.139/sql/Less-26/?id=/1确认过滤了反斜杠http://10.10.10.139/sql/Less-26/?id=\确认过滤了空格,报错注入才行哦,这个判断http://10.10.10.139/sql/Less-26/?id=1' ' '

绕过方法:

  注释可以尝试用'闭合后面语句

  空格:%09 TAB键(水平)、%0a 新建一行、%0c 新的一页、%0d return功能、%0b TAB键(垂直)、%a0 空格
  这里要注意,在windows下无法使用一些特殊的字符代替空格,因为apache的解析的问题

?id=-1' union select 1, 2, 3 '?id=-1'%a0union%a0select%a01,database(),3%26%26'1'='1


过滤or和and

想办法绕过or和and就行:

  大小写变形:Or,OR,oR

  双写:oorr,anandd

  编码:hex,urlencode

  添加注释:/or/

  利用符号:&& ,||

过滤union等指令

通常还是大小写和双写或编码绕过


10、绕过waf

这个简单提一嘴
通常是给个值欺骗waf

如这么个双服务器

  omcat为引擎的jsp型服务器

  apache为引擎的php服务器,提供web服务

输入给两个值

  一个是欺骗tomcat的

  一个是注入到apache的

?id=1&id=-1' union select 1,2,database() --+


11、宽字节注入

字符集

字符集也叫字符编码,是一种将符号转换为二进制数的映射关系
几种常见的字符集:

  ASCII编码:单字节编码

  latin1编码:单字节编码

  gbk编码:使用一字节和双字节编码,0x00-0x7F范围内是一位,和 ASCII 保持一致。双字节的第一字节范围是0x81-0xFE

  UTF-8编码:使用一至四字节编码,0x00–0x7F范围内是一位,和 ASCII 保持一致。其它字符用二至四个字节变长表示

  宽字节就是两个以上的字节,宽字节注入产生的原因就是各种字符编码的不当操作,使得攻击者可以通过宽字节编码绕过SQL注入防御

  通常来说,一个gbk编码汉字,占用2个字节。一个utf-8编码的汉字,占用3个字节。在php中,我们可以通过输出echo strlen("和");来测试,当将页面编码保存为gbk时输出2,utf-8时输出3

除了gbk以外,所有ANSI编码都是2个字节
  ansi只是一个标准,在不同的电脑上它代表的编码可能不相同,比如简体中文系统中ANSI就代表是GBK

概述

  宽字节注入主要是源于程序员设置数据库编码与PHP编码设置为不同的两个编码那么就有可能产生宽字节注入

 

数据提交到mysql数据库,需要进行字符集的转换,使得MySQL数据库可以对数据进行处理,这一过程一般有以下三个步骤:

  收到请求,将请求数据从 character_set_client ->character_set_connection。

  内部操作,将数据从character_set_connection-> 表创建的字符集。

  结果输出,将数据从表创建的字符集 -> character_set_results。

例:当执行set names “charset”,相当于执行

set character_set_client = charsetset character_set_connection = charsetset character_set_results = charset


  宽字符是指两个字节宽度的编码技术,如UNICODE、GBK、BIG5等
当MYSQL数据库数据在处理和存储过程中,涉及到的字符集相关信息包括:

  character_set_client:客户端发送过来的SQL语句编码,也就是PHP发送的SQL查询语句编码字符集

  character_set_connection:MySQL服务器接收客户端SQL查询语句后,在实施真正查询之前SQL查询语句编码字符集

  character_set_database:数据库缺省编码字符集

  character_set_filesystem:文件系统编码字符集

  character_set_results:SQL语句执行结果编码字符集

  character_set_server:服务器缺省编码字符集

  character_set_system:系统缺省编码字符集

  character_sets_dir:字符集存放目录,一般不要修改

宽字节对转义字符的影响发生在character_set_client=gbk的情况
也就是说,如果客户端发送的数据字符集是gbk,则可能会吃掉转义字符\,从而导致转义失败

例如说PHP的编码为 UTF-8, 而 MySql的编码设置为了SET NAMES 'gbk' 或是 SET character_set_client =gbk,这样配置会引发编码转换从而导致的注入漏洞


注入原理

mysql 在使用 GBK 编码的时候,会认为两个字符为一个汉字,例如%aa%5c 就是一个汉字(前一个 ascii 码大于 128 才能到汉字的范围)
我们在过滤 ' 的时候,往往利用的思路是将'转换为\'

PHP 自带一些转义特殊字符的函数,如addslashes(),mysql_real_escape_string(),mysql_escape_string()等,这些函数可用来防止 SQL 注入:

  addslashes() 函数:返回在预定义字符之前添加反斜杠的字符串,预定义字符——单引号(’)、双引号(")、反斜杠(\)、NULL

  tripslashes()函数:删除由 addslashes() 函数添加的反斜杠

  mysql_real_escape_string()函数:转义SQL 语句中使用的字符串中的特殊字符——\x00、 \n、 \r、 \、 '、 "、 \x1a


如id=1' or '1'='1,单引号本用来闭合语句,这些函数会自动转义这些闭合的单引号,在这些单引号前面加上转义符\,变为1\' or \'1\'=\'1,如此在 SQL 查询中是一个普通的字符串,不能进行注入


因此我们在此想办法将'前面添加的\去掉,一般有两种思路:

  %bb吃掉\

若在 PHP 中使用mysql_query("set names gbk")将默认字符集设为GBK,而使用addslashes()转义用户输入,这时如果用户输入%bb%27,则addslashes()会在%27前面加上一个%5c字符,即转义字符\
而 MySQL 在使用GBK编码时,会认为两个字符为一个汉字,%bb%5c是一个宽字符(前一个 ASCII 码大于 128 才能到汉字的范围),也就是籠,也就是说%bb%5c%27=籠',这样单引号就未被转义能闭合语句,从而产生 SQL 注入
%bb并不是唯一一个可以产生宽字节注入的字符,理论上%81-%FE均可

  

过滤\'中的\
构造%bb%5c%5c%27,addslashes()会在两个%5c间和%27前都加上\即%5c,变为%bb%5c%5c%5c%5c%5c%27,但宽字符集认为%bb%5c是一个字符即籠,则变为%bb%5c %5c%5c %5c%5c %27即籠\\\\',四个\正好转义为两个\,即'未被转义

  防御措施

先调用mysql_set_charset函数设置连接所使用的字符集为gbk
再调用mysql_real_escape_string函数来过滤用户输入

先编码也意味着反斜杠即%5c不会出现,到下一步的转义引号才出现
这就造成了编码过后转义引号的反斜杠即字符%5c不会和字符%bb变成一个宽字符,阻止了%bb和 %5c 的拼接,于是防宽字符注入成功


以上是关于sql注入详解 的主要内容,如果未能解决你的问题,请参考以下文章

SQL注入详解

SQL注入详解

sql注入详解

sql注入详解

SQL注入详解

SQL注入详解-转发