^-^
mysql (5.5之前)
1、
php.ini 配置 magic_quotes_gpc = On
开启魔术引号开关后,输入数据( _GET _POST _COOKIE 等)中含单引号( ‘ )、双引号( “ )、反斜线( \ )与 NULL(NULL 字符)等字符,都会被加上反斜线转义
addslashes 函数用于在上述符号前添加反斜杠转义,与 gpc 的作用大致相同
在仅使用 gpc 或 addslashes 函数的情况下
1 | function check_input($value) |
情况一: 数字型注入
1 | SELECT * FROM user WHERE id=-1 or 1=1 -- |
修复方法
1 | $id = intval($_GET['id']); |
情况二: 宽字节注入
mysql 在使用 gbk 编码时,会将两字节认作一个汉字;当 %df%27 和 gpc/addslashes 相遇,%27 前会添加转义字符 %5c ,%df 和 %5c 组成了新的汉字 %df%5c,单引号 %27 则逃逸出来
1 | // 设置编码 |
1 | username=admin1%df%27%20or%201=1%20--%20- |
修复方法
1 | 使用过滤函数: |
2、
情况一: 宽字节注入
mysql_real_escape_string(此方法在 php5.5 后不被建议使用,在 php7 中废除)
同样可在编码设置有问题的情况下用宽字节绕过
需要设置二进制连接避免该问题
1 | mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary"); |
情况二:二次注入
……
mysqli
在 php5.5 后 mysql 等方法被废弃,更提倡使用 mysqli 来连接操作 mysql 数据库。1、
转义方式的安全做法
1 | function check_input($conn, $value) |
2、
在 mysql 5.1 后,提供了类似于 jdbc 的预处理-参数化查询。它的查询方法是:
a. 先预发送一个 sql 模板过去
b. 再向 mysql 发送需要查询的参数
就好像填空题一样,不管参数怎么注入, mysql 都能知道这是变量,不会做语义解析,起到防注入的效果,这是在 mysql 中完成的。
mysqli 默认在服务端预处理
1 | <?php |
PDO
1 | <?php |
PHP5.3.6 之前,使用 PDO 预处理过程如下:
以一种本地预处理的方式向远程服务器提交查询信息,信息还是在本地组装成字符串后向mysql服务器请求;使用 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 禁止本地预处理无效。
查阅一些资料发现问题所在:有些驱动不支持或有限度地支持本地预处理。如果驱动不能成功预处理当前查询,它将总是回到模拟预处理语句上。在 win 下无法禁止本地预处理,在 linux 下可以禁止。
在本地预处理生效且有编码问题的情况下,仍有受到宽字节注入的危险:
1 | <?php |
1 | id=%df%27%20or%201=1%20--%20- |
php5.3.6 及之后的版本预处理过程如下
默认还是在本地预处理,但如果禁用本地预处理的情况会先传送模板,再传送数据,如下图所示
禁用本地预处理的可以有效防止宽字节注入。
小结
注:以上测试均在 windows 下 php5 环境下测试
php版本小于 5.3.6(5.2.17) :
无法关闭本地预处理,易受宽字节注入影响, linux 下可关闭本地预处理(未测试)
php版本大于 5.3.6(5.4.45) :
**可关闭本地预处理,在关闭本地预处理的情况下不受宽字节注入影响
测试结果与网上一些资料有点出入,有时间会深入再看看
最好设置 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); 避免本地预处理
若使用 php 5.3.6+ , 请在在 PDO 的 DSN 中指定 charset 属性
宽字节注入危害还是很大的
https://segmentfault.com/a/1190000008117968
https://www.iteye.com/blog/zhangxugg-163-com-1835721
https://xz.aliyun.com/t/3950
https://www.freebuf.com/articles/web/216336.html