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 相关文章推荐
PHP语法速查表
Jan 02 PHP
PHP操作MongoDB时的整数问题及对策说明
May 02 PHP
PHPMYADMIN导入数据最大为2M的解决方法
Apr 23 PHP
PHP中使用unset销毁变量并内存释放问题
Jul 05 PHP
PHP取二进制文件头快速判断文件类型的实现代码
Aug 05 PHP
php中自定义函数dump查看数组信息类似var_dump
Jan 27 PHP
destoon调用discuz论坛中带图片帖子的实现方法
Aug 21 PHP
PHP与MYSQL中UTF8编码的中文排序实例
Oct 21 PHP
php自动获取关键字的方法
Jan 06 PHP
php fseek函数读取大文件两种方法
Oct 12 PHP
thinkPHP自定义类实现方法详解
Nov 30 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
Mar 29 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
提取HTML标签
2006/10/09 PHP
使用 MySQL Date/Time 类型
2008/03/26 PHP
40个迹象表明你还是PHP菜鸟
2008/09/29 PHP
解析PHP跨站刷票的实现代码
2013/06/18 PHP
PHP5.3连接Oracle客户端及PDO_OCI模块的安装方法
2016/05/13 PHP
PHP实现数据库统计时间戳按天分组输出数据的方法
2017/10/10 PHP
PHP设计模式之简单工厂和工厂模式实例分析
2019/03/25 PHP
通过jquery实现tab标签浏览效果
2007/02/20 Javascript
js程序中美元符号$是什么
2008/06/05 Javascript
javascript学习笔记(七)利用javascript来创建和存储cookie
2011/04/08 Javascript
JQuery入门——事件切换之hover()方法应用介绍
2013/02/05 Javascript
jQuery如何防止这种冒泡事件发生
2015/02/27 Javascript
AngularJS中$http服务常用的应用及参数
2016/08/22 Javascript
使用JavaScript获取Request中参数的值方法
2016/09/27 Javascript
JavaScript实现实时更新系统时间的实例代码
2017/04/04 Javascript
JS设置随机出现2个数字的实例代码
2017/07/19 Javascript
VS Code转换大小写、修改选中文字或代码颜色的方法
2017/12/15 Javascript
JS实现字符串去重及数组去重的方法示例
2018/04/21 Javascript
Vue实现导航栏的显示开关控制
2019/11/01 Javascript
JS原型和原型链原理与用法实例详解
2020/02/05 Javascript
解决vue项目本地启动时无法携带cookie的问题
2021/02/06 Vue.js
Python性能优化技巧
2015/03/09 Python
Python3下错误AttributeError: ‘dict’ object has no attribute’iteritems‘的分析与解决
2017/07/06 Python
Python自定义函数定义,参数,调用代码解析
2017/12/27 Python
Python 实现12306登录功能实例代码
2018/02/09 Python
Python 网络爬虫--关于简单的模拟登录实例讲解
2018/06/01 Python
Python进程的通信Queue、Pipe实例分析
2020/03/30 Python
Python logging模块写入中文出现乱码
2020/05/21 Python
解决selenium+Headless Chrome实现不弹出浏览器自动化登录的问题
2021/01/09 Python
介绍一下HDLC(High-Level Data Link Control)高层数据链路协议
2012/01/21 面试题
临床护士自荐信
2014/01/31 职场文书
培训楼经理岗位责任制
2014/02/10 职场文书
2015年乡镇党务公开工作总结
2015/05/19 职场文书
春风化雨观后感
2015/06/11 职场文书
奖学金发言稿(范文)
2019/08/21 职场文书
golang在GRPC中设置client的超时时间
2021/04/27 Golang