PHP函数addslashes和mysql_real_escape_string的区别


Posted in PHP onApril 22, 2014

首先:不要使用mysql_escape_string,它已被弃用,请使用mysql_real_escape_string代替它。

mysql_real_escape_string和addslashes的区别在于:

区别一:

addslashes不知道任何有关MySQL连接的字符集。如果你给所使用的MySQL连接传递一个包含字节编码之外的其他编码的字符串,它会很愉快地把所有值为字符‘、“、\和\x00的字节进行转义。如果你正在使用不同于8位和UTF-8的其它字符,这些字节的值不一定全部都是表示字符‘、“、\和\x00。可能造成的结果是,MySQL接收这些字符后出现错误。

如果要修正这个bug,可尝试使用iconv函数,将变量转为UTF-16,然后再使用addslashes进行转义。

这是不使用addslashes进行转义的原因之一。

区别二:

与addslashes对比,mysql_real_escape_string同时还对\r、\n和\x1a进行转义。看来,这些字符必须正确地告诉MySQL,否则会得到错误的查询结果。

这是不使用addslashes进行转义的另一个原因。

addslashes V.S. mysql_real_escape_string

在GBK里,0xbf27不是一个合法的多字符字符,但0xbf5c却是。在单字节环境里,0xbf27被视为0xbf后面跟着0×27(‘),同时0xbf5c被视为0xbf后面跟着0x5c(\)。

一个用反斜杠转义的单引号,是无法有效阻止针对MySQL的SQL注入攻击的。如果你使用addslashes,那么,我(攻击者,下同)是很幸运的。我只要注入一些类似0xbf27,然后addslashes将它修改为0xbf5c27,一个合法的多字节字符后面接着一个单引号。换句话说,我可以无视你的转义,成功地注入一个单引号。这是因为0xbf5c被当作单字节字符,而非双字节。

在这个演示中,我将使用MySQL 5.0和PHP的mysqli扩展。如果你想尝试,请确保你使用GBK。

创建一个名为users的表:

CREATE TABLE users(
 username VARCHAR(32) CHARACTER SET GBK,
 password VARCHAR(32) CHARACTER SET GBK,
 PRIMARY KEY(username)
);

下面的代码模拟只使用addslashes(或magic_quotes_gpc)对查询数据进行转义时的情况:
<?php
$mysql = array();
$db = mysqli_init();
$db->real_connect('localhost', 'lorui', 'lorui.com', 'lorui_db');
/* SQL注入示例 */
$_POST['username'] = chr(0xbf) . chr(0×27) . ‘ OR username = username /*'; $_POST['password'] = ‘guess'; $mysql['username'] = addslashes($_POST['username']); $mysql['password'] = addslashes($_POST['password']); $sql = “SELECT * FROM users WHERE username = ‘{$mysql['username']}' AND password = ‘{$mysql['password']}'”; $result = $db->query($sql); if ($result->num_rows) { /* 成功 */ } else { /* 失败 */ }

尽管使用了addslashes,我还是可以在不知道用户名和密码的情况下成功登录。我可以轻松的利用这个漏洞进行SQL注入。

要以免这种漏洞,使用mysql_real_escape_string、准备语句(Prepared Statements,即“参数化查询”)或者任意一款主流的数据库抽象类库。

PHP 相关文章推荐
Smarty模板快速入门
Jan 04 PHP
关于在php.ini中添加extension=php_mysqli.dll指令的说明
Jun 14 PHP
PHP读取网页文件内容的实现代码(fopen,curl等)
Jun 23 PHP
浅析PHP 按位与或 (^ 、&amp;)
Jun 21 PHP
改写函数实现PHP二维/三维数组转字符串
Sep 13 PHP
PHP开发Apache服务器配置
Jul 15 PHP
利用PHP fsockopen 模拟POST/GET传送数据的方法
Sep 22 PHP
详谈PHP中的密码安全性Password Hashing
Feb 04 PHP
PHP中函数gzuncompress无法使用的解决方法
Mar 02 PHP
深入理解PHP的远程多会话调试
Sep 21 PHP
Laravel 5.4因特殊字段太长导致migrations报错的解决
Oct 22 PHP
php+js实现的无刷新下载文件功能示例
Aug 23 PHP
自己写了一个php检测文件编码的函数
Apr 21 #PHP
CodeIgniter框架提示Disallowed Key Characters的解决办法
Apr 21 #PHP
PHP5中实现多态的两种方法实例分享
Apr 21 #PHP
PHP开发中常见的安全问题详解和解决方法(如Sql注入、CSRF、Xss、CC等)
Apr 21 #PHP
PHP正则提取不包含指定网址的图片地址的例子
Apr 21 #PHP
phpmyadmin打开很慢的解决方法
Apr 21 #PHP
PHP递归删除目录几个代码实例
Apr 21 #PHP
You might like
Zend 输出产生XML解析错误
2009/03/03 PHP
获取PHP警告错误信息的解决方法
2013/06/03 PHP
在PHP模板引擎smarty生成随机数的方法和math函数详解
2014/04/24 PHP
PHP根据key删除数组中指定的元素
2019/02/28 PHP
js function使用心得
2010/05/10 Javascript
javascript之querySelector和querySelectorAll使用介绍
2011/12/20 Javascript
JQuery 常用方法和事件详细介绍
2013/04/18 Javascript
Egret引擎开发指南之发布项目
2014/09/03 Javascript
AngularJS入门教程之AngularJS模型
2016/04/18 Javascript
AngularJS入门教程之与服务器(Ajax)交互操作示例【附完整demo源码下载】
2016/11/02 Javascript
jQuery实现判断控件是否显示的方法
2017/01/11 Javascript
JS实现的自动打字效果示例
2017/03/10 Javascript
ES6新特性之Symbol类型用法分析
2017/03/31 Javascript
微信小程序实现简单input正则表达式验证功能示例
2017/11/30 Javascript
详解vue-admin和后端(flask)分离结合的例子
2018/02/12 Javascript
使用vue中的v-for遍历二维数组的方法
2018/03/07 Javascript
vue+mousemove实现鼠标拖动功能(拖动过快失效问题解决方法)
2018/08/24 Javascript
ES6中let 和 const 的新特性
2018/09/03 Javascript
JavaScript装箱及拆箱boxing及unBoxing用法解析
2020/06/15 Javascript
微信小程序实现多图上传
2020/06/19 Javascript
vue 图片裁剪上传组件的实现
2020/11/12 Javascript
[03:21]辉夜杯主赛事 12月25日TOP5
2015/12/26 DOTA
跟老齐学Python之永远强大的函数
2014/09/14 Python
使用实现pandas读取csv文件指定的前几行
2018/04/20 Python
Python编程实现tail-n查看日志文件的方法
2019/07/08 Python
利用ImageAI库只需几行python代码实现目标检测
2019/08/09 Python
Python 变量的创建过程详解
2019/09/02 Python
python3中编码获取网页的实例方法
2020/11/16 Python
秋季运动会活动方案
2014/02/05 职场文书
教师个人鉴定材料
2014/02/08 职场文书
关于孝道的演讲稿
2014/05/21 职场文书
2014年业务工作总结
2014/11/17 职场文书
GoLang中生成UUID唯一标识的实现
2021/05/08 Golang
5种 JavaScript 方式实现数组扁平化
2021/10/05 Javascript
python脚本框架webpy的url映射详解
2021/11/20 Python
Android实现获取短信验证码并自动填充
2023/05/21 Java/Android