在php的逻辑漏洞中,有很大一部分trick跟编码转换机制有关(典型的如宽字节注入),其中除了受到php本身的编码函数如iconv、mb_convert_encoding等影响之外,很多payload源于mysql内部的编码转换机制。这篇文章主要从实例角度出发,以图说话,深入mysql编码转换机制。
0x01 准备知识
常见编码
ascii
编码范围:00-7F
超过7F的属于其他字符集,所以你看到所有的字符trick的首字节,必定在80-FF
latin
编码范围:00-FFmysql默认字符集,可以把其他所有字符集的序列都看成latin1
gbk
编码范围:8140-FEFE第一字节81-FE第二字节40-FE
UTF-8
编码范围:
每种编码也可能存在自身的限制,比如GBK 在某些情况下第二字节不能为7F
UTF-8,某些首字节编码不允许出现等等,这些特例就不在这介绍了,如果在实际操作中如果遇到特别奇怪的现象,一般就是有一些特殊限制或者编码实现的bug
准备代码
仅针对windows环境,linux环境会有部分差异
MYSQL表create table shadow4u(
id int auto_increment not null,
name varchar(50),
shadow varchar(50),
primary key (id)
)default charset=utf8;
PHP代码<?php
$a=$_GET['a'];
var_dump(bin2hex($a));
$sql="insert intoshadow4u(name,shadow) values('$a','zzz')";
$conn=mysql_connect("localhost","root","shadow4u");
$result=mysql_query('show variables like"char%"') or die(mysql_error());
echo"---------------------
";
while($row=mysql_fetch_array($result))
echo$row[0].' : '.$row[1]."
";
mysql_query('set names gbk');
echo"---------------------
";
$result=mysql_query('show variables like"char%"') or die(mysql_error());
while($row=mysql_fetch_array($result))
echo$row[0].' : '.$row[1]."
";
mysql_select_db("test",$conn);
mysql_query($sql,$conn) ordie(mysql_error());
?>
0x02 MYSQL字符集
在mysql命令行下输入命令
show variables like 'char%' 即可看到相应的字符集的设置情况
我们重点关注红框中的部分客户端相关 character_set_client 客户端数据来源使用的字符集
character_set_connection 连接层使用的字符集
character_set_results 查询结果字符集服务端相关 character_set_server 默认的内部操作字符集(字符集)
character_set_database 当前选中数据库的默认字符集
在执行SQL语句之前,一般先通过setnames xx设置客户端相关的字符集
相当于
set character_set_client=xx
set character_set_connection=xx
set character_set_results=xx
客户端的字符集跟具体的客户端有关,不同的客户端连接的字符集不一样&#x