php操作mysql防止sql注入(合集)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: php操作mysql防止sql注入(合集)

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


当一个变量从表单传入到php,需要查询mysql的话,需要进行处理。


举例:

unsafe_variable=unsafe\_variable = 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了

(www.cnblogs.com/suihui/arch…)


由于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中废除。


参考: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注入


blog.csdn.net/sky_zhe/...


参数化查询为什么能够防止SQL注入


www.cnblogs.com/LoveJe...


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

预处理分为两种:


A.使用mysqli:prepare()实现


看一个完整的用法:

mysqli=newmysqli("example.com","user","password","database");mysqli = new mysqli("example.com", "user", "password", "database"); mysqli=newmysqli("example.com","user","password","database");stmt = mysqli−>prepare("SELECTid,labelFROMtestWHEREid=?");mysqli->prepare("SELECT id, label FROM test WHERE id = ?"); mysqli−>prepare("SELECTid,labelFROMtestWHEREid=?");stmt->bind_param(1, city);city); city);stmt->execute();
res=res = res=stmt->get_result();
row=row = row=res->fetch_assoc();

a.写sql语句,然后用?占位符替代sql中的变量

b.替换变量

c.执行

d.得到一个二进制结果集,从二进制结果中取出php结果集

e.遍历结果集

使用预处理,一条查询分两步,所以很安全。也是php5.5及php7推荐方法。

参考:

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=newPDO("mysql:host=localhost;dbname=test;",′root′,′pwd′);pdo = new


PDO("mysql:host=localhost;dbname=test;",'root','pwd'); pdo=newPDO("mysql:host=localhost;dbname=test;",root,pwd);pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

pdo−>exec(′setnamesutf8′);pdo->exec('set names utf8'); pdo>exec(setnamesutf8);id = '0 or 1 =1 order by id desc';

sql="select\*fromarticlewhereid=?";sql = "select \* from article where id = ?"; sql="select\*fromarticlewhereid=?";statement = pdo−>prepare(pdo->prepare(pdo>prepare(sql);

statement−>bindParam(1,statement->bindParam(1, statement>bindParam(1,id);

$statement->execute();

如上,我们关闭了本地预处理模拟器,参数会直接分批发送给mysql,由mysql根据set name utf8字符集进行检测,完成sql注入处理。以上代码不会产生注入。

php5.3.6以上版本

pdo=newPDO("mysql:host=localhost;dbname=test;charset=utf8",′root′,′pwd′);pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8",'root','pwd'); pdo=newPDO("mysql:host=localhost;dbname=test;charset=utf8",root,pwd);pdo->exec('set names utf8');

id=′0or1=1orderbyiddesc′;id = '0 or 1 =1 order by id desc'; id=0or1=1orderbyiddesc;sql = "select * from article where id = ?";

statement=statement = statement=pdo->prepare(sql);sql); sql);statement->bindParam(1, id);id); id);statement->execute();

在php5.3.6以上版本中,默认情况下ATTR_EMULATE_PREPARES开启,模拟器会根据new PDO()中的charset=utf8进行检测,在模拟器上完成防注入操作。如果把模拟器关闭,也会像低版本一样送交mysql进行防注入处理。


参考:


PDO防注入原理分析以及使用PDO的注意事项

zhangxugg-163-com.itey...

PHP 5.3.6及以前版本的PDO的bindParam,bindValue潜在的安全隐患

zhangxugg-163-com.itey...

再论php 5.3.6以前版本中的PDO SQL注入漏洞问题

my.oschina.net/zxu/blo...

segmentfault讨论

segmentfault.com/q/10...

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


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

htmlspecialchars()


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

举个例子:


a="′";


上面由于a的值就是一个′,当它输出在value=′′之间时,会破坏html原有的dom格式,导致html解析错误。下面那个′输出在标签对之间时没有问题。上面那个问题怎么解决呢?可以这样:

php会向浏览器输出:


这个符号只有流量器认识,源码中看到是这样,但是浏览器输出的就是一个'号。


xss注入


xss也就是常说的跨域攻击,这是一种在客户端浏览器上面执行的攻击。


比如在表单或者url参数中,人为写入javascript代码,看起来是普通的文字,但是被浏览器解析后变成可执行的javascript动作,用来做广告或者攻击等等。


举例:

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

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
11天前
|
SQL 存储 关系型数据库
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
本文详细介绍了MySQL中的SQL语法,包括数据定义(DDL)、数据操作(DML)、数据查询(DQL)和数据控制(DCL)四个主要部分。内容涵盖了创建、修改和删除数据库、表以及表字段的操作,以及通过图形化工具DataGrip进行数据库管理和查询。此外,还讲解了数据的增、删、改、查操作,以及查询语句的条件、聚合函数、分组、排序和分页等知识点。
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
|
29天前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
28天前
|
SQL 关系型数据库 MySQL
MySQL 高级(进阶) SQL 语句
MySQL 提供了丰富的高级 SQL 语句功能,能够处理复杂的数据查询和管理需求。通过掌握窗口函数、子查询、联合查询、复杂连接操作和事务处理等高级技术,能够大幅提升数据库操作的效率和灵活性。在实际应用中,合理使用这些高级功能,可以更高效地管理和查询数据,满足多样化的业务需求。
110 3
|
1月前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
1月前
|
SQL 存储 关系型数据库
MySQL进阶突击系列(01)一条简单SQL搞懂MySQL架构原理 | 含实用命令参数集
本文从MySQL的架构原理出发,详细介绍其SQL查询的全过程,涵盖客户端发起SQL查询、服务端SQL接口、解析器、优化器、存储引擎及日志数据等内容。同时提供了MySQL常用的管理命令参数集,帮助读者深入了解MySQL的技术细节和优化方法。
|
1月前
|
SQL Oracle 关系型数据库
SQL(MySQL)
SQL语言是指结构化查询语言,是一门ANSI的标准计算机语言,用来访问和操作数据库。 数据库包括SQL server,MySQL和Oracle。(语法大致相同) 创建数据库指令:CRATE DATABASE websecurity; 查看数据库:show datebase; 切换数据库:USE websecurity; 删除数据库:DROP DATABASE websecurity;
|
2月前
|
SQL 安全 PHP
PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全
本文深入探讨了PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全。
67 4
|
2月前
|
SQL 安全 前端开发
Web学习_SQL注入_联合查询注入
联合查询注入是一种强大的SQL注入攻击方式,攻击者可以通过 `UNION`语句合并多个查询的结果,从而获取敏感信息。防御SQL注入需要多层次的措施,包括使用预处理语句和参数化查询、输入验证和过滤、最小权限原则、隐藏错误信息以及使用Web应用防火墙。通过这些措施,可以有效地提高Web应用程序的安全性,防止SQL注入攻击。
65 2
|
MySQL 关系型数据库 数据安全/隐私保护
|
2月前
|
前端开发 关系型数据库 MySQL
PHP与MySQL动态网站开发实战指南####
【10月更文挑战第21天】 本文将深入浅出地探讨如何使用PHP与MySQL构建一个动态网站,从环境搭建到项目部署,全程实战演示。无论你是编程新手还是希望巩固Web开发技能的老手,都能在这篇文章中找到实用的技巧和启发。我们将一起探索如何通过PHP处理用户请求,利用MySQL存储数据,并最终呈现动态内容给用户,打造属于自己的在线平台。 ####
60 0