PHP中防止SQL注入方法详解


Posted in PHP onDecember 25, 2014

问题描述:

如果用户输入的数据在未经处理的情况下插入到一条SQL查询语句,那么应用将很可能遭受到SQL注入攻击,正如下面的例子:

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('" . $unsafe_variable . "')");

因为用户的输入可能是这样的:

value'); DROP TABLE table;--

那么SQL查询将变成如下:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

应该采取哪些有效的方法来防止SQL注入?

 最佳回答(来自Theo):

使用预处理语句和参数化查询。预处理语句和参数分别发送到数据库服务器进行解析,参数将会被当作普通字符处理。这种方式使得攻击者无法注入恶意的SQL。 你有两种选择来实现该方法:

1、使用PDO:

$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');

 

$stmt->execute(array('name' => $name));

 

foreach ($stmt as $row) {

    // do something with $row

}

2、使用mysqli:

$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');

$stmt->bind_param('s', $name);

 

$stmt->execute();

 

$result = $stmt->get_result();

while ($row = $result->fetch_assoc()) {

    // do something with $row

}

 PDO

注意,在默认情况使用PDO并没有让MySQL数据库执行真正的预处理语句(原因见下文)。为了解决这个问题,你应该禁止PDO模拟预处理语句。一个正确使用PDO创建数据库连接的例子如下:

$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');

$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

在上面的例子中,报错模式(ATTR_ERRMODE)并不是必须的,但建议加上它。这样,当发生致命错误(Fatal Error)时,脚本就不会停止运行,而是给了程序员一个捕获PDOExceptions的机会,以便对错误进行妥善处理。 然而,第一个setAttribute()调用是必须的,它禁止PDO模拟预处理语句,而使用真正的预处理语句,即有MySQL执行预处理语句。这能确保语句和参数在发送给MySQL之前没有被PHP处理过,这将使得攻击者无法注入恶意SQL。了解原因,可参考这篇博文:PDO防注入原理分析以及使用PDO的注意事项。 注意在老版本的PHP(<5.3.6),你无法通过在PDO的构造器的DSN上设置字符集,参考:silently ignored the charset parameter。

 解析

当你将SQL语句发送给数据库服务器进行预处理和解析时发生了什么?通过指定占位符(一个?或者一个上面例子中命名的 :name),告诉数据库引擎你想在哪里进行过滤。当你调用execute的时候,预处理语句将会与你指定的参数值结合。 关键点就在这里:参数的值是和经过解析的SQL语句结合到一起,而不是SQL字符串。SQL注入是通过触发脚本在构造SQL语句时包含恶意的字符串。所以,通过将SQL语句和参数分开,你防止了SQL注入的风险。任何你发送的参数的值都将被当作普通字符串,而不会被数据库服务器解析。回到上面的例子,如果$name变量的值为 'Sarah'; DELETE FROM employees ,那么实际的查询将是在 employees 中查找 name 字段值为 'Sarah'; DELETE FROM employees 的记录。 另一个使用预处理语句的好处是:如果你在同一次数据库连接会话中执行同样的语句许多次,它将只被解析一次,这可以提升一点执行速度。 如果你想问插入该如何做,请看下面这个例子(使用PDO):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');

$preparedStatement->execute(array('column' => $unsafeValue));
PHP 相关文章推荐
PHP教程 预定义变量
Oct 23 PHP
PHP学习之输出字符串(echo,print,printf,print_r和var_dump)
Apr 17 PHP
php中利用explode函数分割字符串到数组
Feb 08 PHP
php下Memcached入门实例解析
Jan 05 PHP
再推荐十款免费的php开发工具
Nov 09 PHP
详解WordPress中过滤链接与过滤SQL语句的方法
Dec 18 PHP
php使用pdo连接sqlite3的配置示例
May 27 PHP
PHP学习笔记之php文件操作
Jun 03 PHP
PHP实现的折半查找算法示例
Dec 19 PHP
php实现文章评论系统
Feb 18 PHP
PHP常见的几种攻击方式实例小结
Apr 29 PHP
thinkphp框架实现路由重定义简化url访问地址的方法分析
Apr 04 PHP
使用PHP实现阻止用户上传成人照片或者裸照
Dec 25 #PHP
浅析PHP文件下载原理
Dec 25 #PHP
php使用sql server验证连接数据库的方法
Dec 25 #PHP
php实现mysql事务处理的方法
Dec 25 #PHP
php使用pdo连接mssql server数据库实例
Dec 25 #PHP
php连接与操作PostgreSQL数据库的方法
Dec 25 #PHP
完整删除ecshop中获取店铺信息的API
Dec 24 #PHP
You might like
坏狼的PHP学习教程之第1天
2008/06/15 PHP
PHP 存储文本换行实现方法
2010/01/05 PHP
PHP字符串比较函数strcmp()和strcasecmp()使用总结
2014/11/19 PHP
php多次include后导致全局变量global失效的解决方法
2015/02/28 PHP
php 字符串中是否包含指定字符串的多种方法
2018/04/12 PHP
jQuery语法总结和注意事项小结
2012/11/11 Javascript
Jquery 表单验证类介绍与实例
2013/06/09 Javascript
JavaScript的strict模式与with关键字介绍
2014/02/08 Javascript
windows下安装nodejs及框架express
2015/08/07 NodeJs
用户代理字符串userAgent可实现的四个识别
2015/09/20 Javascript
JQuery 获取Dom元素的实例讲解
2017/07/08 jQuery
vue实现图书管理demo详解
2017/10/17 Javascript
JS在if中的强制类型转换方式
2018/07/15 Javascript
微信小程序生成海报分享朋友圈的实现方法
2019/05/06 Javascript
ES6如何用一句代码实现函数的柯里化
2020/01/18 Javascript
JS面向对象编程实现的Tab选项卡案例详解
2020/03/03 Javascript
vue 在单页面应用里使用二级套嵌路由
2020/12/19 Vue.js
详解Golang 与python中的字符串反转
2017/07/21 Python
PYTHON基础-时间日期处理小结
2018/05/05 Python
对pandas写入读取h5文件的方法详解
2018/12/28 Python
python爬虫爬取微博评论案例详解
2019/03/27 Python
python中时间、日期、时间戳的转换的实现方法
2019/07/06 Python
python操作yaml说明
2020/04/08 Python
将pymysql获取到的数据类型是tuple转化为pandas方式
2020/05/15 Python
PyCharm Community安装与配置的详细教程
2020/11/24 Python
Kenneth Cole官网:纽约时尚优雅品牌
2016/11/14 全球购物
澳大利亚领先的在线美容商城:Adore Beauty
2017/04/14 全球购物
澳大利亚最受欢迎的女士度假服装:Kabana Shop
2020/10/10 全球购物
描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理
2015/03/25 面试题
四议两公开实施方案
2014/03/28 职场文书
操行评语大全
2014/04/30 职场文书
2014入党积极分子批评与自我批评思想汇报
2014/09/20 职场文书
2014物价局群众路线对照检查材料思想汇报
2014/09/21 职场文书
小学英语听课心得体会
2016/01/14 职场文书
详解Java分布式事务的 6 种解决方案
2021/06/26 Java/Android
PostgreSQL常用字符串分割函数整理汇总
2022/07/07 PostgreSQL