测试代码大体如下:
1 | mysql_query("set names utf8"); |
利用ASCii码来理解
我们想要绕过,我们可以靠输入16进制进去,然后MySQL无法解析的字符会自动省略。 值得注意的是,00-1F 是自动忽略,而后面的特殊字符会进行截断
测试发现我们输入不可显示的字符的16进制可以绕过,如payload:
1 | http://127.0.0.1/test/mysql_char.php?username=admin%11 |
当然这里的%11
可以为其它任何的不可显示的字符的十六进制。 【ASCII码】
其实理解为 ASCII码也不能算错,但是这边还有一种理解是关于编码问题的。
字符集转换漏洞
因为字符集不同 躲过关键词过滤 进入mysql后产生的截断 恢复关键词查询。
MySQL语句
- 查看字符集 :
show variables like 'character_set_%'
- php中设置 客户端字符集 :
set names utf8
这个语句会修改如下客户端设置:然后下面这些服务端是不会修改的:1
2
3character_set_client=utf8
character_set_connection=utf8
character_set_results=utf8这样就造成了 服务端与客户端 不匹配1
2
3
4character_set_database
character_set_server
character_set_filesysytem
character_set_system
从而会造成 字符集转换漏洞
整体理解一遍
当我们的mysql接受到客户端的数据后,会认为他的编码是character_set_client,然后会将其将换成character_set_connection的编码,然后进入具体表和字段后,再转换成字段对应的编码。
当查询结果产生后,会从表和字段的编码,转换成character_set_results编码,返回给客户端。但是编码间的转换是会忽略掉无法解析的数据的,所以就造成了字符集转换漏洞。比如说 Latin1(系统默认) 他是无法处理中文的,但是utf-8 等编码会。
于是我们又做出了如下测试:
1 | username=admin%e4 #在mysql中utf8转为latin1被截断为admin |
这里截断原因是,MySQL在字符集转换的时候会自动将不完整的字符忽略。
转换出错的原因是,Latin1 不支持汉字。
关于编码
这里我们还了解一下 【编码理解】
顺便贴一下 【UTF-8查询表】
提取出重点,UTF-8是变长编码,有可能是1~4字节表示:
- 一个字节时,字节的范围是[00-7F]
- 两个字节时,字节的范围是[C0-DF] [80-BF]
- 三个字节时,字节的范围是[E0-EF] [80-BF] [80-BF]
- 四个字节时,字节的范围是[F0-F7] [80-BF] [80-BF] [80-BF]
mysql UTF-8 特性
Mysql的utf8其实是阉割版utf-8编码,Mysql中的utf8字符集最长只支持三个字节
utf8mb4编码才是包含完整的UTF8
所以相对来说,对于类似的绕过利用
- 对于UTF8,可以利用第一个字节范围[00-7F] [C2-EF]
- 对于UTF8mb4,可以利用第一个字节范围[00-7F] [C2-F4]
其实即使我的所有字符集设置都为 utf8 但是也是存在这个问题的,我在mysql中测试等出的结论就是会忽略那些 不太正常的字符 也有些是截断。
利用 两个字节的 字符进行绕过
如下代码:
1 | function check_password($str){ |
放回 1 就是触发waf了,那么我们怎么绕过?
我们可以使用一些特别的字符进行代替 【utf8表】 如这个链接里的一些字符就可以代替 a (mysql将它识别为a)截个图:
比如这里的这几个就可以代替a,如我们输入以下测试:
1 | http://127.0.0.1/test/mysql_char.php?username=%C3%A3dmin |
也是可以通过的(还是文章最前面那个环境) 。
这里除了a以为其它许多字符都基本可以找到代替的(b我没有找到),找的话就找长的像的然后一个一个测试。如:
记一个 payload
这边题目给的源码是:
1 | mysql_query("set names utf8"); |
但是我觉得正在的源码不是这样的,肯定还有其它的过滤 waf 。利用上面的知识测试和尝试最后得到一个payload(不唯一)
1 | ?username=admin%c2&password=%C3%A3dmins |
主要是这个 username 绕过,讲道理 我 %80
等等都可以过的,但是这里就%c2
可以过,应该还是内部控制了其范围。
这就记住了 测试就用%C2 (先用它测)。