PHP中如何防止SQL注入
这是StackOverFlow上一个投票非常多的提问 How to prevent SQL injection in PHP? 我把问题和赞同最多的答题翻译了下来。
提问:如果用户的输入能直接插入到SQL语句中,那么这个应用就易收到SQL注入的攻击,举个例子:
$unsafe_variable = $_POST['user_input'];
mysqli_query("INSERT INTO table (column) VALUES ('" . $unsafe_variable . "')");
用户可以输入诸如 : value'); DROP TABLE table;-- ,SQL语句就变成这样了:
INSERT INTO table (column) VALUES('value'); DROP TABLE table;--')
(译者注:这样做的结果就是把table表给删掉了) 我们可以做什么去阻止这种情况呢?
回答:
使用prepared statements(预处理语句)和参数化的查询。这些SQL语句被发送到数据库服务器,它的参数全都会被单独解析。使用这种方式,攻击者想注入恶意的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数据库时,真正的prepared statements默认情况下是不使用的。为了解决这个问题,你需要禁用模拟的prepared statements。下面是使用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);
上面的例子中,错误报告模式并不是强制和必须的,但建议你还是添加它。通过这种方式,脚本在出问题的时候不会被一个致命错误终止,而是抛出PDO Exceptions,这就给了开发者机会去捕获这个错误。
然而第一行的 setAttribute() 是强制性的,它使得PDO禁用模拟的prepared statements并使用真正的prepared statements。这可以确保这些语句和值在被发送到MySQL服务器之前不会被PHP解析(这使得攻击者没有注入恶意SQL的机会)。
尽管你可以使用可选的构造函数参数去设置 charset ,但重点需要注意的是小于5.3.6的PHP版本,DSN(Data Source Name)是默认忽略 charset 参数的。
说明
当你传一个SQL语句做预处理时会发生什么?它被数据库服务器解析和编译了。通过指定参数(通过之前例子中的 ? 或者像 :name 这样的命名式参数)你告诉数据库引擎你是想过滤它。接着当你调用 execute() 函数时,prepared statements会和你刚才指定的参数的值结合。
在此重要的是,参数的值是和编译过的语句结合,而非一个SQL字符串。SQL注入就是当创建被发送到数据库的SQL语句时,通过欺骗的手段让脚本去引入恶意的字符串。因此当你使用单独的参数发送真实正确的SQL时,你就限制了被某些不是你真实意图的事情而搞挂掉的风险。使用prepared statements 传递的任何参数都会被当做字符串对待(不过数据库引擎可能会做一些优化,这些参数最终也可能变成numbers)(译者注:意思就是把参数当做一个字符串而不会去做额外的行为)。比如在上面的例子中,如果 $name 变量的值是 'Sarah'; DELETE * FROM employees ,产生的结果是会去搜索"'Sarah'; DELETE * FROM employees"这一整个字符串,最终的结果你也就不会面对的是一张空表了。
使用prepared statements的另一个好处是,如果你在同一session中再次执行相同的语句,也就不会被再次解析和编译,这样你就获得一些速度上的提升。
哦,既然你问的是插入操作该如果防止,下面给出一个例子(使用PDO):
$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');
$preparedStatement->execute(array(':column' => $unsafeValue));
翻译完,
本人翻译水平有限,请读者见谅。
PHP中如何防止SQL注入的更多相关文章
- Python中如何防止sql注入
sql注入中最常见的就是字符串拼接,研发人员对字符串拼接应该引起重视,不应忽略. 错误用法1: sql = "select id, name from test where id=%d an ...
- [转]开发中如何解决SQL注入的问题
Java防止SQL注入 SQL 注入简介: SQL注入是最常见的攻击方式之一,它不是利用操作系统或其它系统的漏洞来实现攻击的,而是程序员因为没有做好判断,被不法用户钻了SQL的空子,下面 ...
- node-mysql中防止SQL注入
备注: 本文针对mysqljs/mysql. 为了防止SQL注入,可以将SQL中传入参数进行编码,而不是直接进行字符串拼接.在node-mysql中,防止SQL注入的常用方法有以下四种: 方法一:使用 ...
- web 中防止sql注入
public class SqlInject:Page { //检测到注入后的处理方式: 0:仅警告:1:警告+记录:2:警告+自定义错误页面:3:警告+记录+自定义错误页面 ; private co ...
- Web攻防之XSS,CSRF,SQL注入
摘要:对Web服务器的攻击也可以说是形形色色.种类繁多,常见的有挂马.SQL注入.缓冲区溢出.嗅探.利用IIS等针对Webserver漏洞进行攻击.本文结合WEB TOP10漏洞中常见的SQL注入,跨 ...
- c#.net全站防止SQL注入类的代码
using System;using System.Collections.Generic;using System.Linq;using System.Web; /// <summary> ...
- Java程序员从笨鸟到菜鸟之(一百零一)sql注入攻击详解(二)sql注入过程详解
在上篇博客中我们分析了sql注入的原理,今天我们就来看一下sql注入的整体过程,也就是说如何进行sql注入,由于本人数据库和网络方面知识有限,此文章是对网上大量同类文章的分析与总结,其中有不少直接引用 ...
- 防止SQL注入的,网站安全的一些常用解决方案
--------------------------------------------------------过滤URL中的一些特殊字符,动态SQL语句使用PrepareStatement.. -- ...
- DFX 安全测试-- 告诉你什么是XSS、sql注入?POST和GET的区别....
1.用户权限测试 (1) 用户权限控制 1) 用户权限控制主要是对一些有权限控制的功能进行验证 2) 用户A才能进行的操作,B是否能够进行操作(可通过窜session,将在下面介绍) 3)只能有A条件 ...
随机推荐
- POJ 1135 Domino Effect(Dijkstra)
点我看题目 题意 : 一个新的多米诺骨牌游戏,就是这个多米诺骨中有许多关键牌,他们之间由一行普通的骨牌相连接,当一张关键牌倒下的时候,连接这个关键牌的每一行都会倒下,当倒下的行到达没有倒下的关键牌时, ...
- PHP file_exists() 函数
定义和用法 file_exists() 函数检查文件或目录是否存在. 如果指定的文件或目录存在则返回 true,否则返回 false. 语法 file_exists(path) 参数 描述 path ...
- 汇编语言中,SP,BP ,SI,DI作用?
这个很简单: sp:表示栈顶指针,指向栈顶地址.与SS相配合使用.ss为栈段. bp:是基址指针,段地址默认在SS中.可以定位物理地址,比如:"mov ax,[bp+si+6]/mov ax ...
- 定时显示提示控件 TToolTip
转载过来的,文章出自: http://www.delphifans.com/infoview/Article_3640.html { 修改者:ghs 日期:20071218 功能:在 ...
- Android Touch事件传递机制
1.基础知识 (1) 所有Touch事件都被封装成了MotionEvent对象,包括Touch的位置.时间.历史记录以及第几个手指(多指触摸)等. (2) 事件类型分为ACTION_DOWN, ACT ...
- Form.KeyPreview 属性2
在使用.Net Framework编写窗体应用程序的时候,有时有需要响应窗体的按键消息. 当窗体上没有任何其他控件的时候,窗体是可以直接响应这些消息的. 但是当窗体上有其他控件时,会发现窗体再也不会响 ...
- 转自 z55250825 的几篇关于FFT的博文(三)
题目大意:给出n个数qi,定义 Fj为 令 Ei=Fi/qi,求Ei. 其实这道题就是看到有FFT模板才觉得有必要学一下的... 所以实际上就是已经知道题解了... = ...
- Linux内核与根文件系统的关系
开篇题外话:对于Linux初学者来说,这是一个很纠结的问题,但这也是一个很关键的问题! 一语破天机: “尽管内核是 Linux 的核心,但文件却是用户与操作系统交互所采用的主要工具.这 ...
- ruby编程语言-学习笔记4(第4章 表达式和操作符)
4.6.9 范围 Flip-Flops: ..和... ..和... 操作符不是基于方法的,无法重定义.(优先级比较低) x+1 .. x*x #可以认为是x+1 至 x*x 的范围 因为操作 ...
- zookeeper使用和原理探究(一)(转)
zookeeper介绍zookeeper是一个为分布式应用提供一致性服务的软件,它是开源的Hadoop项目中的一个子项目,并且根据google发表的<The Chubby lock servic ...