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条件 ...
随机推荐
- C++ new operator, delete operator, operator new, operator delete, new placement
http://www.younfor.com/cpp-new-placement-new-operator-new.html http://www.cnblogs.com/luxiaoxun/arch ...
- w3c subscribe
http://www.w3.org/html/ig/zh/ http://blog.csdn.net/spring21st/article/details/6126537 http://www.w3c ...
- 李洪强漫谈iOS开发[C语言-019]-断点调试
- 板级支持包(BSP)
板级支持包(BSP)是介于主板硬件和操作系统中驱动层程序之间的一层,一般认为它属于操作系统一部分,主要是实现对操作系统的支持,为上层的驱动程序提供访问硬件设备寄存器的函数包,使之能够更好的运行于硬件主 ...
- YII CJson类
CJson文档: http://www.yiiframework.com/doc/api/1.1/CJSON CJson::encode可以编码任何类型的数据:源码如下: public static ...
- 多设备官方教程(6)控制多版本API
Supporting Different Platform Versions While the latest versions of Android often provide great APIs ...
- Trigger Execution Sequence in Oracle Forms
Introduction ------------ This document lists the order in which triggers fire in Oracle Forms 4.5: ...
- Delphi开发嵌入IE的OCX,调用页面上JavaScript的方法
利用Delphi的ActiveForm,可以很方便地开发出可以嵌入IE的ActiveX组件,无需知道太多幕后的COM知识.如何使得OCX可以很方便地调用Web上的JavaScript函数呢,研究了一个 ...
- msvc2010生成的指令序列有问题,可能跟pgo有关
正常序列 有问题序列 这段代码程序启动是执行,会导致崩溃 工程使用ltcg pgo,也就是说,第一次编译连接完成后,会跑一次profile,再执行连接器代码生成优化. 构建记录显示,ltcg已跑完,说 ...
- $destroy
ng-view 路由切换会触发 $destroy