sql注入详解
Posted 红客突击队
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql注入详解 相关的知识,希望对你有一定的参考价值。
sql注入详解 (四)
9、绕过各种过滤
一些普通的防护措施是过滤
过滤注释和空格
检测
确认过滤了
http://10.10.10.139/sql/Less-26/?id=%231
确认过滤了or
http://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 = charset
set character_set_connection = charset
set 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注入详解 的主要内容,如果未能解决你的问题,请参考以下文章