本文将从sql注入风险说起,并且比较addslashes、mysql_escape_string、mysql_real_escape_string、mysqli和pdo的预处理的区别。

当一个变量从表单传入到php,需要查询mysql的话,需要进行处理。
举例:
$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表被删掉了。

这是一种常见的sql注入方法,那么在程序中,应该怎样预防呢?

1.魔术引用 (推荐指数3)
addslashes()与stripslashes()是功能相反的函数。
addslashes()用于对变量中的' " 和NULL添加斜杠,用于避免传入sql语句的参数格式错误,同时如果有人注入子查询,通过加可以将参数解释为内容,而非执行语句,避免被mysql执行。

不过,addslashes()添加的只在php中使用,并不会写入mysql中。
那么,tripslashes()的作用是将加了的php变量去掉,由于不会写入mysql中,所以从mysql查询出来的内容不需要再tripslashes()。

在防注入方面,addslashes()可以防止掉大多数的注入,但是此函数并不会检查变量的编码,当使用例如中文gbk的时候,由于长度比较长 ,会将某些gbk编码解释成两个ascii编码,造成新的注入风险(俗称宽字节注入)。见下面2。

如果从网页表单、php、mysql都使用utf8编码,则没有这个问题。
基于此函数的风险,并不建议使用,推荐使用下面3中的方法。

addslashes

(PHP 4, PHP 5, PHP 7)

addslashes — 使用反斜线引用字符串

说明 ¶

addslashes ( string $str ) : string

返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(

'

)、双引号(

"

)、反斜线(

\

)与 NUL(NULL 字符)。

一个使用 addslashes() 的例子是当你要往数据库中输入数据时。 例如,将名字

O'reilly

插入到数据库中,这就需要对其进行转义。 强烈建议使用 DBMS 指定的转义函数 (比如 MySQL 是 mysqli_real_escape_string(),PostgreSQL 是 pg_escape_string()),但是如果你使用的 DBMS 没有一个转义函数,并且使用

\

来转义特殊字符,你可以使用这个函数。 仅仅是为了获取插入数据库的数据,额外的

\

并不会插入。 当 PHP 指令 magic_quotes_sybase 被设置成

on

时,意味着插入

'

时将使用

'

进行转义。

PHP 5.4 之前 PHP 指令 magic_quotes_gpc 默认是

on

, 实际上所有的 GET、POST 和 COOKIE 数据都用被 addslashes() 了。 不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。 遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。

参数 ¶str要转义的字符。

返回值 ¶返回转义后的字符。

范例 ¶

Example #1 一个 *addslashes() 例子*

<?php $str = "Is your name O'reilly?"; // 输出: Is your name O\'reilly? echo addslashes($str); ?>

2. mysql_real_escape_string() (推荐指数4)

就用addslashes好了..暂时可以忘记掉mysql_real_escape_string了

(https://www.cnblogs.com/suihui/archive/2012/09/20/2694751.html)
由于addslashes()不检测字符集,所以有宽字节注入风险,所以php中添加了这个函数。
这个函数本来是mysql的扩展,但是由于存在宽字节的问题,php基于mysql的扩展开发了此函数。

gbk宽字符漏洞导致的sql注入

mysql_real_escape_chars()是mysql_escape_chars()的替代用法。
与addslashes()相比,不仅会将' " NOL(ascii的0)转义,还会把r n进行转义。同时会检测数据编码。
按php官方的描述,此函数可以安全的用于mysql。

此函数在使用时会使用于数据库连接(因为要检测字符集),并根据不同的字符集做不同的操作。如果当前连接不存在,刚会使用上一次的连接。

mysql_real_escape_string()防注入详解
此方法在php5.5后不被建议使用,在php7中废除。
参考:https://segmentfault.com/q/10...

3.预处理查询 (Prepared Statements) (推荐指数5)
使用prepared statements(预处理语句)和参数化的查询,可以有效的防止sql注入。

为什么预处理和参数化查询可以防止sql注入呢?
在传统的写法中,sql查询语句在程序中拼接,防注入(加斜杠)是在php中处理的,然后就发语句发送到mysql中,mysql其实没有太好的办法对传进来的语句判断哪些是正常的,哪些是恶意的,所以直接查询的方法都有被注入的风险。
在mysql5.1后,提供了类似于jdbc的预处理-参数化查询。它的查询方法是:

  1. 先预发送一个sql模板过去
  2. 再向mysql发送需要查询的参数
    就好像填空题一样,不管参数怎么注入,mysql都能知道这是变量,不会做语义解析,起到防注入的效果,这是在mysql中完成的。

参考:
PHP中如何防止SQL注入 http://blog.csdn.net/sky_zhe/...

参数化查询为什么能够防止SQL注入 http://www.cnblogs.com/LoveJe...

上面提供的资料比较多,下面根据自己的理解整理出来。

预处理分为两种:
A.使用mysqli:prepare()实现
看一个完整的用法:
$mysqli = new mysqli("example.com", "user", "password", "database");
$stmt = $mysqli->prepare("SELECT id, label FROM test WHERE id = ?");
$stmt->bind_param(1, $city);
$stmt->execute();
$res = $stmt->get_result();
$row = $res->fetch_assoc();

a.写sql语句,然后用?占位符替代sql中的变量
b.替换变量
c.执行
d.得到一个二进制结果集,从二进制结果中取出php结果集
e.遍历结果集

使用预处理,一条查询分两步,所以很安全。也是php5.5及php7推荐方法。
参考: http://www.cnblogs.com/liuzha...

B. 使用pdo实现
pdo是一个php官方推荐的数据库抽象层,提供了很多实用的工具。

使用pdo的预处理-参数化查询可以有效防止sql注入。
使用方法跟上面差不多,区别在于pdo提供了更多样的方法。
使用这个pdo->$stmt对象进行查询后,会被结果集覆盖,类型是一个二维数组。

我们在上面预处理-参数化查询是在mysql中进行防注入操作的,其实pdo也内置了一个预处理的模拟器,叫做ATTR_EMULATE_PREPARES。
默认情况下,PDO会使用DSN中指定的字符集对输入参数进行本地转义(PHP手册中称为native prepared statements),然后拼接成完整的SQL语句,发送给MySQL Server。这有些像我们平时程序中拼接变量到SQL再执行查询的形式。

这种情况下,PDO驱动能否正确转义输入参数,是拦截SQL注入的关键。然而PHP 5.3.6及老版本,并不支持在DSN中定义charset属性(会忽略之),这时如果使用PDO的本地转义,仍然可能导致SQL注入,

如果ATTR_EMULATE_PREPARES=true(默认情况),预处理-参数化查询在pdo的模拟器中完成,模拟器根据字符集(dsn参数)进行处理,然后把语句发送给mysql。

如果ATTR_EMULATE_PREPARES=false,sql会分两次把参数给送给mysql,mysql根据自身的字符集(set names )进行处理,完成查询。

但由于各版本差异,pdo在各版本中的实现程度也不一样,有些版本还有bug,我们以php5.3.6做为分界线来进行说明:

php5.3.6以下版本
$pdo = new PDO("mysql:host=localhost;dbname=test;",'root','pwd');
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
$pdo->exec('set names utf8');
$id = '0 or 1 =1 order by id desc';
$sql = "select * from article where id = ?";
$statement = $pdo->prepare($sql);
$statement->bindParam(1, $id);
$statement->execute();
如上,我们关闭了本地预处理模拟器,参数会直接分批发送给mysql,由mysql根据set name utf8字符集进行检测,完成sql注入处理。以上代码不会产生注入。

php5.3.6以上版本
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8",'root','pwd');
$pdo->exec('set names utf8');
$id = '0 or 1 =1 order by id desc';
$sql = "select * from article where id = ?";
$statement = $pdo->prepare($sql);
$statement->bindParam(1, $id);
$statement->execute();
在php5.3.6以上版本中,默认情况下ATTR_EMULATE_PREPARES开启,模拟器会根据new PDO()中的charset=utf8进行检测,在模拟器上完成防注入操作。如果把模拟器关闭,也会像低版本一样送交mysql进行防注入处理。

参考:
PDO防注入原理分析以及使用PDO的注意事项 http://zhangxugg-163-com.itey...

PHP 5.3.6及以前版本的PDO的bindParam,bindValue潜在的安全隐患 http://zhangxugg-163-com.itey...

再论php 5.3.6以前版本中的PDO SQL注入漏洞问题 http://my.oschina.net/zxu/blo...

segmentfault讨论 https://segmentfault.com/q/10...

  1. html输出与防止xss注入
    特殊字符输出

比如' " < >有着特殊的意义,如果直接写到html中输出,会引起dom格式的错乱,那么就需要用到特殊的输出方法。

htmlspecialchars()
用于将一些特殊符号转义成只有浏览器识别的转义符。

举个例子:
$a = " ' "; =$a;?>

上面由于$a的值就是一个' ,当它输出在value=''之间时,会破坏html原有的dom格式,导致html解析错误。
下面那个'输出在标签对之间时没有问题。
上面那个问题怎么解决呢? 可以这样:
php会向浏览器输出:
这个符号只有流量器认识,源码中看到是这样,但是浏览器输出的就是一个'号。

xss注入
xss也就是常说的跨域攻击,这是一种在客户端浏览器上面执行的攻击。
比如在表单或者url参数中,人为写入javascript代码,看起来是普通的文字,但是被浏览器解析后变成可执行的javascript动作,用来做广告或者攻击等等。

举例:
有人在发贴的时候写入了javascript代码,一打开就弹窗口。

php操作mysql防止sql注入(合集)相关推荐

  1. MySQL安装及应用合集(2):zip安裝包的安装方式

    一.文件下载 在 MySQL官网上,点击DOWNLOADS ,可以进入到下载首页,拉到最底下的 MySQL Community (GPL) Downloads 点击进入到产品下载页面. 产品下载页面有 ...

  2. MySQL安装及应用合集(3):msi安裝包的安装方式

    一.文件下载 在 MySQL官网上,点击DOWNLOADS ,可以进入到下载首页,拉到最底下的 MySQL Community (GPL) Downloads点击进入到产品下载页面. 产品下载页面有很 ...

  3. mysql 防注入 php_PHP+mysql防止SQL注入的方法小结

    本文实例讲述了PHP+mysql防止SQL注入的方法.分享给大家供大家参考,具体如下: SQL注入 例:脚本逻辑 $sql = "SELECT * FROM user WHERE useri ...

  4. php mysql 防 sql注入_php 防sql注入方法

    php防sql注入的方法:1.使用mysql_real_escape_string方法转义SQL语句中使用的字符串中的特殊字符:2.打开magic_quotes_gpc来防止SQL注入:3.通过自定义 ...

  5. mysql注入实例获取答案_本文实例讲述了MySQL解决SQL注入的另类方法。分享给大家供大家参考,具体如下:问题解读我觉得,这个问题每年带来的成本可以高达数十亿美元了。本文就来谈谈,...

    本文实例讲述了MySQL解决SQL注入的另类方法.分享给大家供大家参考,具体如下: 问题解读 我觉得,这个问题每年带来的成本可以高达数十亿美元了.本文就来谈谈,假定我们有如下 SQL 模板语句: se ...

  6. 雷林鹏分享:MySQL 及 SQL 注入

    MySQL 及 SQL 注入 如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题. 本章节将为大家介绍如何防止SQL注入,并通过脚本来过滤SQL中注入 ...

  7. 三十一、MySQL 及 SQL 注入

    MySQL 及 SQL 注入 如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题. 本章节将为大家介绍如何防止SQL注入,并通过脚本来过滤SQL中注入 ...

  8. mysql 8.0 自定义函数_PHP+Mysql防止SQL注入的方法(life)

    这篇文章介绍的内容是关于PHP+Mysql防止SQL注入的方法,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 我的官方群点击此处. 方法一: mysql_real_escape_str ...

  9. decimal转为string sql_PHP+Mysql防止SQL注入的方法

    这篇文章介绍的内容是关于PHP+Mysql防止SQL注入的方法,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 我的官方群点击此处. 方法一:[1] mysql_real_escape_ ...

最新文章

  1. 亿级数据湖统一存储技术实践
  2. linux中的size_t和ssize_t区别
  3. Docker-Compose 使用简介
  4. 这5个有趣的Python库带你花式编码!
  5. VLM:Meta AI CMU提出任务无关视频语言模型视频理解预训练VLM,代码已开源!(ACL 2021)...
  6. 11个Javascript树形菜单
  7. 在装有Anaconda的情况下,使用默认的python程序方法
  8. nginx 监听非标准端口80,重定向端口丢失问题解决
  9. 物联网培训总结(C#)
  10. 关于CSDN登录没有微信二维码的问题
  11. python实现税后工资_Python实现扣除个人税后的工资计算器示例
  12. 靶向目标基因检测技术
  13. 阿里云智能编码插件Cosy,让你的开发过程既高效又轻松
  14. VMware Workstation中部署VMware vSphere 7.0
  15. silverlight mysql_Silverlight中衔接MySQL数据库实例详解
  16. GSR引擎专用工具更新使用贴子
  17. 方法教程:一分钟把网易云音乐上的MV/mv视频下载到本地电脑
  18. MySQL中information_schema详解
  19. word中选中所有拼音
  20. powerbi中的earlier函数

热门文章

  1. win7硬盘安装ubuntu
  2. Manifold Mixup 摘要速览
  3. 法国自助游 (转载)
  4. 怎么样编辑pdf文件文字部分的内容
  5. 浅析EasyCVR视频技术与AR实景智能管理平台在智慧厂区中的应用
  6. Qt用户图形界面设计应用(闹钟)
  7. 软件测试基础(十一)测试UI界面检查
  8. UE4官方课程笔记(1)——游戏设计师的蓝图与游戏玩法
  9. python实现AC自动机
  10. If you have database settings to be loaded from a particular profile you may need to activate it