mysql decs倒叙查询_MySql字符研究

0x01 字符集和字符序

http://www.laruence.com/2008/01/05/12.html

字符集 character set

针对给定的字符 赋予一个数值,这个数值就是这个字符的编码,多个字符以及对应的编码,就组成了字符集

eg:    A->1  B->2  A的字符编码是1  B的字符编码是2  当给定的字符是AB的时候,{A->1  B->2}就是字符集

no.1 查看字符集

mysql支持的字符集

mysql> SHOW CHARACTER SET;

+----------+-----------------------------+---------------------+--------+

| Charset  | Description                 | Default collation   | Maxlen |

+----------+-----------------------------+---------------------+--------+

| big5     | Big5 Traditional Chinese    | big5_chinese_ci     |      2 |

| dec8     | DEC West European           | dec8_swedish_ci     |      1 |

| cp850    | DOS West European           | cp850_general_ci    |      1 |

| hp8      | HP West European            | hp8_english_ci      |      1 |

no.2 查看指定的字符集

mysql> SHOW CHARACTER SET WHERE Charset="utf8";

+---------+---------------+-------------------+--------+

| Charset | Description   | Default collation | Maxlen |

+---------+---------------+-------------------+--------+

| utf8    | UTF-8 Unicode | utf8_general_ci   |      3 |

+---------+---------------+-------------------+--------+

或者

mysql> SHOW CHARACTER SET LIKE "utf8%";

+---------+---------------+--------------------+--------+

| Charset | Description   | Default collation  | Maxlen |

+---------+---------------+--------------------+--------+

| utf8    | UTF-8 Unicode | utf8_general_ci    |      3 |

| utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci |      4 |

+---------+---------------+--------------------+--------+

no.3 查看指定库的字符集 字符序

切换到要查看的数据库

mysql> SELECT @@character_set_database, @@collation_database;

+--------------------------+----------------------+

| @@character_set_database | @@collation_database |

+--------------------------+----------------------+

| gbk                      | gbk_chinese_ci       |

+--------------------------+----------------------+

或者 通过创建库的语句

mysql> SHOW CREATE DATABASE security;

+----------+------------------------------------------------------------------+

| Database | Create Database                                                  |

+----------+------------------------------------------------------------------+

| security | CREATE DATABASE `security` /*!40100 DEFAULT CHARACTER SET gbk */ |

+----------+------------------------------------------------------------------+

no.4 查看指定表的字符集

通过查询创建表的语句

mysql> SHOW CREATE TABLE users;

+-------+------------------------------------------------------------------------------

| Table | Create Table                                       |

+-------+------------------------------------------------------------------------------

| users | CREATE TABLE `users` (

`id` int(3) NOT NULL AUTO_INCREMENT,

`username` varchar(20) NOT NULL,

`password` varchar(20) NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=gbk |

字符序 collation

是指同一字符集中,各字符之间的比较规则,确定了字符序之后,就可以比较字符集中字符的大小关系

在数据的存储上,MySQL提供了不同的字符集

在数据的比较上,MySQL提供了不同的字符序

no.1 查看指定表的字符序

SELECT TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = "security" AND TABLE_NAME = "users";

+-----------------+

| TABLE_COLLATION |

+-----------------+

| gbk_chinese_ci  |

+-----------------+

no.2 查看指定列的字符序

mysql> SELECT CHARACTER_SET_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA="security" AND TABLE_NAME="users" AND COLUMN_NAME="username";

+--------------------+----------------+

| CHARACTER_SET_NAME | COLLATION_NAME |

+--------------------+----------------+

| gbk                | gbk_chinese_ci |

+--------------------+----------------+

针对字符集和字符序的详情参考

https://www.cnblogs.com/chyingp/p/mysql-character-set-collation.html

0x02 字符集存在的问题

MySQL字符集设置

– character_set_server:默认的内部操作字符集

– character_set_client:客户端来源数据使用的字符集

– character_set_connection:连接层字符集

– character_set_results:查询结果字符集

– character_set_database:当前选中数据库的默认字符集

– character_set_system:系统元数据(字段名等)字符集

查看MySQL字符集设置

mysql> SHOW VARIABLES LIKE 'character_set_%';

+--------------------------+-----------------------------------------------+

| Variable_name            | Value                                         |

+--------------------------+-----------------------------------------------+

| character_set_client     | utf8                                          |

| character_set_connection | utf8                                          |

| character_set_database   | latin1                                        |

| character_set_filesystem | binary                                        |

| character_set_results    | utf8                                          |

| character_set_server     | utf8                                          |

| character_set_system     | utf8                                          |

no.1 宽字节注入

https://www.leavesongs.com/PENETRATION/mutibyte-sql-inject.html

utf8编码处理一个汉字用3个字节表示,gbk编码处理一个汉字用2个字节表示

查看php中 使用的是那种编码

echo strlen("和");

?>

输出是2 就是gbk

输出是3 就是utf8

大多数程序会使用addslashes来转义单引号 ' == '

两种方式绕过

1 转义掉   这种 \'    单引号就可以逃逸出来

2 把 弄没有

利用宽字节就可以把弄没有  MySQL使用GBK编码时,会认为两个字符表示一个汉字,不过第一个字符的ascii值要大于128(%80),才能达到汉字的范围

把上面的代码稍微改动一下

$mysqli->query("set names gbk");$username = addslashes($_GET['username']);

测试一下

加上单引号试一下

617207763617c6cd78c477a198ac0073.png

不行

加上%df试一下

payload

?username=admin%df%27%20or%201=1%23

84f38b6d1adcac8c06fb9665adcba66a.png

ok了

这里%df还可以换成%a1  %81 等等  大于%80的 都可以

gb2312

gb23112编码就不存在宽字节的问题,因为gb2312编码的取值范围。它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE,而是0x5c,是不在低位范围中的。所以,0x5c根本不是gb2312中的编码 ,自然就不会存在宽字节注入的问题啦

mysqlrealescape_string

转义单引号的函数不只有addslashes    还有 mysqlrealescape_string

该函数会考虑到当前使用的字符集,是不是就不存在宽字节注入的问题啦

试试看

char.php写入

payload还是能打通

c05f167c333bf31eeab9e2b77fdcb05e.png

指定一下php连接MySQL的字符集,

mysql_set_charset('gbk',$conn);

返回bool(flase)

结论

如果不加上mysqlsetcharset('gbk',$conn);  这一行代码 依旧存在

还有另外一个解决方案 通过设置客户来源字符集为binary 把数据保存为二进制,以二进制的形式传递,就不存在宽字节的问题了

SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary

iconv转换编码

iconv('utf-8', 'gbk', $_GET['word']);

很多网站为了避免乱码,把utf8转成了gbk

后端代码

@$conn = mysql_connect('localhost','root','root');

mysql_query("SET NAMES 'gbk'");

mysql_select_db('lianxi',$conn);

mysql_query('SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary');

$username = addslashes($_GET['username']);

$username = iconv('utf-8', 'gbk', $username);

$sql = "SELECT * FROM `user` WHERE name='{$username}'";

$result=mysql_query($sql,$conn);

$row=mysql_fetch_array($result);var_dump($row);

mysql_free_result($result);

?>

连接层字符集设置了binary 并且转义了单引号

上面的payload已经不行了

再试一下第二种方法 转义掉

汉字  錦  utf8编码为 0xe98ca6   gbk编码为  0xe55c

试一下

639c2abc076a1047370c59831155f0e6.png

可以打通,payload被转为gbk编码后,出现了5c 两个5c放到一起,就变成了这个字符,失去了转义的作用

如果是gbk转为utf8呢 是不是同样存在问题

修改一下 代码

$username = iconv('gbk', 'utf-8', $username);

a805a08cd47435095afb4080b190572e.png

直接用第一种方法 就行

gbk编码 2个字节一组 直接吞掉%5c

Note: 说明一下 utf8编码 不是3个字节一组嘛  为什么a%E9%8C没有放在一起转码,因为3个字节一组的是汉字 对于ASCII 是单字节  a被单独解码 后面的%E9满足大于128的条件被当作汉字解码,3个一组

而gbk编码 当第一个字节大于128的时候 表示的就是汉字 所以%df%5c才会放到一起

no.2 字符集转换

https://www.leavesongs.com/PENETRATION/mysql-charset-trick.html

MySQL默认的字符集是Latin1

Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。

客户端输入一个字符,经过的编码过程如下

character_set_client -> character_set_connection -> character_set_server

这里三个编码 都设置为了utf8

mysql> SHOW VARIABLES LIKE 'character_set_%';

+--------------------------+-----------------------------------------------+

| Variable_name            | Value                                         |

+--------------------------+-----------------------------------------------+

| character_set_client     | utf8                                          |

| character_set_connection | utf8                                          |

| character_set_database   | utf8                                          |

| character_set_filesystem | binary                                        |

| character_set_results    | utf8                                          |

| character_set_server     | utf8                                          |

| character_set_system     | utf8                                          |

输入

admin%e4

admin%e4%db

admin%e4%bd%ac

只有第一个能绕过 第二个和第三个都不行 貌似应该是凑不成一个字符 会被丢掉,

0x03 字符序存在的问题

MySQL中的字符序名称遵从命名惯例:以字符序对应的字符集名称开头;以_ci(表示大小写不敏感)、_cs(表示大小写敏感)或_bin(表示按编码值比较)结尾。

utf8unicodeci 和 utf8generalci

utf8generalci不区分大小写, 对于法语和德语校对有问题,例如

Ä/ä = AÖ/ö = OÜ/ü = UA=a这几种条件都成立,

对于utf8generalci下面的等式成立:ß = s ,但是,对于utf8unicodeci下面等式才成立:ß = ss 。

http://collation-charts.org/mysql60/mysql604.utf8generalci.european.html

验证一下

在数据库中插入一条admin的记录

mysql> insert `user` values(212,'admin','sex',20190102,'programer');

Query OK, 1 row affected (0.00 sec)

连接数据库

<?php $mysqli = new mysqli("localhost", "root", "root", "lianxi");/* check connection */if ($mysqli->connect_errno) {printf("Connect failed: %sn", $mysqli->connect_error);exit();

}

$mysqli->query("set names utf8");$username = $_GET['username'];/* Select queries return a resultset */$sql = "SELECT * FROM `user` WHERE name='{$username}'";if ($result = $mysqli->query( $sql )) {printf("Select returned %d rows.n", $result->num_rows);while ($row = $result->fetch_array(MYSQLI_ASSOC)){var_dump($row);}/* free result set */$result->close();} else {var_dump($mysqli->error);}$mysqli->close();

德语测试

61a3155b4fe680a1e0852619b517c0e3.png

%C3%84是Ä的url编码

%C3%A4是ä的url编码

大小写测试

ADMIN = admin

394b49a38120f7ca11e4ec3e02c52d2b.png

utf8unicodeci和utf8generalci对中、英文来说没有实质的差别。

utf8generalci校对速度快,但准确度稍差。

utf8unicodeci准确度高,但校对速度稍慢。

如果你的应用有德语、法语或者俄语,请一定使用utf8unicodeci

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值