宽字节注入初探

7erry

简介

SQL注入的要点很大一部分在于闭合’使我们的输入成为指令而非仅是参数。因此,过滤或处理这些不良的输入正是防御SQL注入的要点。一种常用的方式是使用addslashes这样的方式对用户的输入进行转义,将用户输入的特殊符号进行替换或者在其前面添加反斜杠进行转义,例如 ‘ -> \‘ 使得这些特殊符号变为普通的不带有特殊意义的字符。为了从addslashes这样的过滤处理逃逸出来,我们很容易想到,可以在 \ 前再加一个 \ ,把 \ 字符转义掉使它不再能转义它本要转义的字符,或者干脆把 \ 弄没。宽字节注入就是实现这种逃逸的一种注入方式。

基本概念

字符集

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

常见字符集

几种常见的字符集:

  • ASCII编码:单字节编码
  • latin1编码:单字节编码
  • GBK编码:使用一字节和双字节编码,0x00-0x7F范围内是一位,和 ASCII 保持一致。双字节的第一字节范围是0x81-0xFE
  • UTF-8编码:使用一至四字节编码,0x00~0x7F范围内是一位,和 ASCII 保持一致。其它字符用二至四个字节变长表示。

宽字节

字符大小为一个字节的字符是窄字节,字节数大于等于二的字符叫做宽字节,比如GB2312、GBK、GB18030、BIG5、Shift_JIS等编码。英文字符往往是窄字节,汉字字符往往是宽字节。

MySQL特性

在MYSQL中,有一个中间层的结构,负责客户端和服务器之间的连接,称为连接层
交互的过程如下:

  1. 客户端(例如php)以某种字符集生成的SQL语句发送至服务器端(例如Mysql),这个某种字符集其实是任意规定的,PHP作为客户端连接MYSQL时,这个字符集就是PHP文件的默认的编码
  2. 服务器(Mysql)会将这个SQL语句转为连接层的字符集。问题在于MYSQL是怎么知道我们传过来的这个SQL语句是什么编码呢?这时主要依靠两个MYSQL的内部变量来表示,一个是character_set_client(客户端的字符集)和character_set_connection(连接层的字符集)
  3. php把sql语句传给mysql时,要转换character_set_connection字符集的编码,执行流程就是:将php的sql语句以character_set_client编码(也就是转为16进制数),再将16进制数以character_set_connection进行编码(也就是转换为url编码),然后以内部操作字符集进行url解码,最后以character_set_results编码输出结果
    内部操作字符集怎么确定?进行内部操作前将请求数据从character_set_connection转换为内部操作

字符转换时的确定方法如下:

  • 使用每个数据字段的CHARACTER SET设定值;
  • 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);
  • 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值;
  • 若上述值不存在,则使用character_set_server设定值。
    流程图解

查看MySQL字符集

show variables like '%char%';

修改字符集

set names "charset"; #相当于执行以下三句
set character_set_client = charset;
set character_set_connection = charset;
set character_set_results = charset;

URL转码

  • ' —> %27
  • ‘ ‘(空格) —> %20
  • # —> %23
  • \ —> %5c

常见转移函数与配置

  • addslashes
  • mysql_real_escape_string
  • mysql_escape_string
  • php.ini中magic_quote_gpc的配置
  • magic_qutes_gpc

攻击原理

MySQL在使用GBK编码的时候,如果两个字符的前一个ASCII码大于128,会认为两个字符是一个汉字(两个窄字节组成了宽字节)。GBK首字节对应0×81-0xFE,尾字节对应0×40-0xFE(除0×7F)。利用MySQL的这种特性和GBK编码的规则,我们可以提前在\会被插入的位置前加上一个字符使得这个字符与\凑成一个宽字节,从而让\失效实现逃逸。

攻击实现

传参时引号前加个%DF再及逆行正常的注入即可
例如

1
2
3
4
5
%df%27 浏览器url自动解码
===> β\' 转为16进制
===> 0xdf0x5c0x27 转换为url编码
===> %df%5c%27 进行url解码(因为是GBK编码,%df和%5c结合为汉字)
===> 運'

Reference

https://blog.csdn.net/weixin_39934520/article/details/105968747

  • Title: 宽字节注入初探
  • Author: 7erry
  • Created at : 2023-07-09 00:00:00
  • Updated at : 2023-07-09 00:00:00
  • Link: http://7erry.com/2023/07/09/宽字节注入初探/
  • License: This work is licensed under CC BY-NC 4.0.