PHP常见的SQL防注入方法

利用Mysqli和PDO

产生原因主要就是一些数据没有经过严格的验证,然后直接拼接 SQL 去查询。导致产生漏洞,比如:

$id = $_GET['id'];
$sql = "SELECT name FROM users WHERE id = $id";

因为没有对 $_GET[‘id’] 做数据类型验证,注入者可提交任何类型的数据,比如 " and 1= 1 or " 等不安全的数据。如果按照下面方式写,就安全一些。

$id = intval($_GET['id']);
$sql = "SELECT name FROM users WHERE id = $id";

把 id 转换成 int 类型,就可以去掉不安全的东西。

验证数据

防止注入的第一步就是验证数据,可以根据相应类型进行严格的验证。比如 int 类型直接通过 intval 进行转换就行:

$id = intval($_GET['id']);

字符处理起来比较复杂些,首先通过 sprintf 函数格式化输出,确保它是一个字符串。然后通过一些安全函数去掉一些不合法的字符,比如:

$str = addslashes(sprintf("%s",$str));

也可以用mysqli_real_escape_string 函数替代 addslashes 这样处理以后会比较安全。当然还可以进一步去判断字符串长度,去防止 [缓冲区溢出攻击] 比如:

$str = addslashes(sprintf("%s",$str));
$str = substr($str,0,40);	//最大长度为40

参数化绑定

参数化绑定,防止 SQL 注入的又一道屏障。php MySQLi 和 PDO 均能提供这样的功能。比如 MySQLi 可以这样去查询:

$mysqli = new mysqli('localhost','my_user','my_password','world');
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?,?,?,?)");
$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;
$stmt->bind_param('sssd',$code,$language,$official,$percent);

PDO 的更是方便,比如:

/* Execute a prepared statement by passing an array of values */
$sql = 'SELECT name,color,calories
FROM fruit
WHERE calories < :calories AND color = :colour';
$sth = $dbh->prepare($sql,array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':calories' => 150, ':colour' => 'red'));
$red = $sth->fetchAll();
$sth->execute(array(':calories' => 175, ':colour' => 'yellow'));
$yellow = $sth->fetchAll();

我们多数使用 php 的框架进行编程,所以最好不要自己拼写 SQL,按照框架给定参数绑定进行查询。遇到较为复杂的 SQL 语句,一定要自己拼写的时候,一定要注意严格的判断。没有用 PDO 或者 MySQLi 也可以自己写个 prepared,比如 wordpress db 查询语句,可以看出也是经过严格的类型验证。

function prepare( $query, $args ){if(is_null($query))return;// This is not meant to be foolproof --	// but it will catch obviously incorrect usage.if(strpos($query,'%') === false){_doing_it_wrong('wpdb::prepare',sprintf(__('The query argument of %s must have a placeholder.'),'wpdb::prepare()'),'3.9');}$args = fun_get_args();array_shift($args);// If args were passed as an array (as in vsprintf), move them upif(isset($args[0]) && is_array($args[0]))$args = $args[0];$query = str_replace("'%s'",'%s',$query);//in case someone mistakenly already singlequoted it$query = str_replace('"%s"','%s',$query);//doublequote unquoting$query = preg_replace('|(?<!%)%f|','%F',$query);	//Force floats to be locale unaware$query = pref_replace('|(?<!%)%s|',"'%s'",$query);//quote the strings,avoiding escaped strings like %%sarray_walk($args,array($this,'escape_by_ref'));return @ vsprintf($query,$args);
}

总结

安全性很重要,也可以看出一个人基本功,项目漏洞百出,扩展性和可维护性再好也没有用。平时多留意,树立安全意识,养成一种习惯,一些基本的安全当然也不会占用 coding 的时间。

养成这个习惯,即便在项目急,时间短的情况下,依然可以做的质量很高,不要等到自己以后负责的东西,数据库都被拿走了,造成损失才重视。

虽然国内很多PHP程序员仍在依靠addslashes防止SQL注入,还是建议大家加强中文防止SQL注入的检查。addslashes的问题在于黑客可以用0xbf27来代替单引号,而addslashes只是将0xbf27修改为0xbf5c27,成为一个有效的多字节字符,其中的0xbf5c仍会被看作是单引号,所以addslashes无法成功拦截。

当然addslashes也不是毫无用处,它是用于单字节字符串的处理,多字节字符还是用mysql_real_escape_string吧。

另外对于php手册中get_magic_quotes_gpc的举例:

if(!get_magic_quotes_gpc()){$lastname = addslashes($_POST[&lsquo;lastname&rsquo;]);
}else{$lastname = $_POST[&lsquo;lastname&rsquo;];
}

最好对magic_quotes_gpc已经开放的情况下,还是对$_POST[‘lastname’]进行检查一下。

再说下mysql_real_escape_string和mysql_escape_string这2个函数的区别:
mysql_real_escape_string 必须在(PHP >= 4.3.0,PHP5)的情况下才能使用。否则只能用mysql_escape_string,两者的区别是:mysql_real_escape_string 考虑到连接的当前字符集,而mysql_escape_string 不考虑。

总结一下:

addslashes() 是强行加;
mysql_real_escape_string() 会判断字符集,但是对PHP版本有要求;
mysql_escape_string不考虑连接的当前字符集。

参考文章链接:
https://mp.weixin.qq.com/s/X6q0xpbnJ9lojIIwNmDzdA

补充:

一:addslashes

php addslashes函数的作用是在预定义的字符前面加上反斜杠,这些预定义字符包括:

单引号(')
双引号(")
反斜杠(\)
NULL

$str="my name's wxp";
echo addslashes($str);//输出my name\'s wxp

然后在拼接mysql字符串:

$sql="insert into student(student_name)values('".addslashes($str)."')";
mysql_query($sql);

此时字符串被插入到数据库,那么大家是否知道插入的字符串是带反斜杠还是不带反斜杠呢?恐怕很多人都会认为肯定是带反斜杠的字符串。其实这个答案是错误的,插入的字符串是没有带反斜杠。至于为什么插入的字符串在数据库中是没有加反斜杠,请大家继续看下面讲解。

如果字符串$str="my name’s wxp"是使用POST和GET提交的数据,这个时候插入数据库中的数据是带反斜杠的,由此可知addslashes只是在POST和GET数据插入数据库时才会把反斜杠同时插入到数据库,其他情况下不会将反斜杠插入到数据库。

注释:默认地,PHP 对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。所以您不应对已转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测

参考:
原文链接:https://blog.csdn.net/MengJing_/article/details/89353942

二:mysql_real_escape_string

mysql_real_escape_string
(PHP 4 >= 4.3.0, PHP 5)

mysql_real_escape_string — 将字符串中的特殊字符进行转义,以在 SQL 语句中使用

警告 本扩展自 PHP 5.5.0 起已废弃,并在自 PHP 7.0.0 开始被移除。应使用 MySQLi 或 PDO_MySQL
扩展来替换之。参见 MySQL:选择 API 指南来获取更多信息。用以替代本函数的有:
mysqli_real_escape_string() PDO::quote()

说明

mysql_real_escape_string(string $unescaped_string, resource $link_identifier = NULL): string

考虑到连接的当前字符集,对 unescaped_string 进行特殊字符转义,以便安全地将其放置在 mysql_query() 中。如果要插入二进制数据,则必须使用此函数。

mysql_real_escape_string() 调用 mysql 库的函数 mysql_real_escape_string, 在以下字符前添加反斜线:\x00、\n、\r、\、'、" 和 \x1a.

在向 MySQL 发送查询之前,必须始终(有少数例外)使用此函数来确保数据的安全。

警告
安全: 默认字符集 The character set must be set either at the server level,or with the API function mysql_set_charset() for it to affect mysql_real_escape_string(). See the concepts section on character sets for more information.

示例:

<?php
// Connect
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')OR die(mysql_error());// Query
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",mysql_real_escape_string($user),mysql_real_escape_string($password));
?>
三:mysql_escape_string

mysql_escape_string
(PHP 4 >= 4.0.3, PHP 5)

mysql_escape_string — 转义字符串用于 mysql_query

警告 本函数自 PHP 4.3.0 起已废弃,并且它和整个 MySQL 扩展自 PHP 7.0.0 开始被移除。 可以选择出于活跃开发中的MySQLi 或 PDO_MySQL 扩展来作为替代。 参见 MySQL:选择 API 指南来获取更多信息。用以替代本函数的有:mysqli_escape_string() PDO::quote()

说明

mysql_escape_string(string $unescaped_string): string

本函数将转义 unescaped_string,使之可以安全用于 mysql_query()。此函数已弃用。

本函数和 mysql_real_escape_string() 相同,除了 mysql_real_escape_string() 接受连接处理程序并根据当前字符集进行转义。mysql_escape_string() 不接受连接参数,也不遵循当前字符集设定。

示例

<?php
$item = "Zak's Laptop";
$escaped_item = mysql_escape_string($item);
printf("Escaped string: %s\n", $escaped_item);
?>

以上示例会输出:

Escaped string: Zak\'s Laptop

注意:
mysql_escape_string() 不转义 % 和 _。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/85334.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

感知器算法

感知器是一种简单的机器学习算法&#xff0c;用于二元分类问题&#xff08;即将数据分为两个类别&#xff09;。它是人工神经网络的早期形式&#xff0c;由Frank Rosenblatt在1957年提出。感知器的主要思想是通过学习权重来分隔不同类别的数据点。 以下是感知器算法的基本步骤&…

Mac配置iTerm样式终端

一、MacOs系统 MacOs中终端使用iTerm2 1. 配置oh-my-zsh oh my zsh 的地址&#xff1a; https//github.com/ohmyzsh/ohmyzsh 插件存放位置&#xff1a;~/.oh-my-zsh/plugins 下载常用的插件 git clone http://github.com/zsh-users/zsh-syntax-highlighting.git 修改配…

英伟达 nvidia 官方code llama在线使用

新一代编程语言模型Code Llama面世&#xff1a;重新定义编程的未来 随着人工智能和机器学习技术的迅速发展&#xff0c;我们现在迎来了一款革命性的大型编程语言模型——Code Llama。该模型是基于Llama 2研发的&#xff0c;为开放模型中的佼佼者&#xff0c;其性能达到了行业领…

React组件化开发

1.组件的定义方式 函数组件Functional Component类组件Class Component 2.类组件 export class Profile extends Component {render() {console.log(this.context);return (<div>Profile</div>)} } 组件的名称是大写字符开头&#xff08;无论类组件还是函数组件…

ISTQB术语表

此术语表为国际软件测试认证委员会&#xff08;ISTQB&#xff09;发布的标准术语表。此表历经数次修改、完善&#xff0c;集纳了计算机行业界、商业界及政府相关机构的见解及意见&#xff0c;在国际化的层面上达到了罕有的统一性及一致性。参与编制此表的国际团体包括澳大利亚、…

MyBatisPlus(四)表映射:@TableName

表映射 数据库中的表名&#xff0c;和项目中的实体类名&#xff0c;并不相同&#xff0c;则需要通过注解TableName来进行映射。 未映射前报错示例 数据库表名&#xff1a;tb_user 实体类名&#xff1a;User 测试代码 Autowiredprivate UserMapper userMapper;Testvoid selec…

CUDA和cuDNN的安装

参考资料&#xff1a;https://zhuanlan.zhihu.com/p/83971195 目录 CUDA和cuDNN介绍安装验证 CUDA和cuDNN介绍 CUDA(ComputeUnified Device Architecture)&#xff0c;是显卡厂商NVIDIA推出的运算平台。 CUDA是一种由NVIDIA推出的通用并行计算架构&#xff0c;该架构使GPU能够…

Mrtrix3--将mif文件转换为nifit文件--以及批处理代码

#如果您想在mrview中看到fd.mif,则可以使用fixel2voxel fd.mif mean fd_mean.miffixel2voxel fd.mif mean fd_mean.mif mrconvert fd_mean.mif fd_mean.nii.gz #convert to nifit----fixel_in_template_space_NOT_REORIENTED/fd_mean#fixel2voxel fd.mif mean fd…

网络初识

一 IP 地址 概念: IP 地址主要用于表示网络主机、其他网络设备&#xff08;如路由器&#xff09;的网络地址。简单说&#xff0c;IP地址用于定位主机的网络地址 格式 IP 地址是一个32为的二进制数&#xff0c;通常被分割为4个“8位二进制数“&#xff08;也就是4个字节&…

排序算法(一)

排序算法(一&#xff09; 冒泡排序选择排序插入排序希尔排序堆排序 冒泡排序 冒泡排序是一种十分稳定的排序&#xff0c;其思想是通过两两比较&#xff0c;改变位置&#xff0c;从而每次让一个数出现在其该出现的位置该排序由于很稳定&#xff0c;所以不论数据是否有序&#xf…

什么是语法糖?Java中有哪些语法糖?

什么是语法糖&#xff1f;Java中有哪些语法糖&#xff1f; 语法糖 语法糖&#xff08;Syntactic Sugar&#xff09;&#xff0c;也称糖衣语法&#xff0c;是由英国计算机学家 Peter.J.Landin 发明的一个术语&#xff0c;指在计算机语言中添加的某种语法&#xff0c;这种语法对…

小米笔试题——01背包问题变种

这段代码的主要思路是使用动态规划来构建一个二维数组 dp&#xff0c;其中 dp[i][j] 表示前 i 个产品是否可以组合出金额 j。通过遍历产品列表和可能的目标金额&#xff0c;不断更新 dp 数组中的值&#xff0c;最终返回 dp[N][M] 来判断是否可以组合出目标金额 M。如果 dp[N][M…

C++提高编程:01 模板

这里写目录标题 1 模板的概念2 函数模板2.1 函数模板语法2.2 函数模板注意事项2.3 函数模板案例2.4 普通函数与函数模板的区别2.5 普通函数与函数模板的调用规则2.6 模板的局限性 3 类模板3.1 类模板语法3.2 类模板与函数模板区别3.3 类模板中成员函数创建时机3.4 类模板对象做…

thinkphp8路由

thinkphp8已出来有好一段时间了。这些天闲来无事&#xff0c;研究了下tp8的路由。默认情况下&#xff0c;tp8的路由是在route\app.php的文件里。但在实际工作中&#xff0c;我们并不会这样子去写路由。因为这样不好管理。更多的&#xff0c;是通过应用级别去管理路由。假如项目…

2023华为杯研究生数学建模C题分析

完整的分析查看文末名片获取&#xff01; 问题一 在每个评审阶段&#xff0c;作品通常都是随机分发的&#xff0c;每份作品需要多位评委独立评审。为了增加不同评审专家所给成绩之间的可比性&#xff0c;不同专家评审的作品集合之间应有一些交集。但有的交集大了&#xff0c;则…

conda的安装和使用

参考资料&#xff1a; https://www.bilibili.com/read/cv8956636/?spm_id_from333.999.0.0 https://www.bilibili.com/video/BV1Mv411x775/?spm_id_from333.999.0.0&vd_source98d31d5c9db8c0021988f2c2c25a9620 目录 conda是啥以及作用conda的安装conda的启动conda的配置…

操作符 | MATLAB

文章目录 算术运算模除法和舍入关系运算符逻辑运算集合运算按位运算 算术运算 操作符含义操作符含义操作符含义sum元素数组求和cumsum累计和movsum移动总和diff差分和近似导数.*乘法*矩阵乘法prod数组元素的乘积cumprod累积乘积pagemtimes按页矩阵乘法tensorprodTensor produc…

redis如何清空当前缓存和所有缓存

Windows环境下使用命令行进行redis缓存清理 redis安装目录下输入cmdredis-cli -p 端口号flushdb 清除当前数据库缓存flushall 清除整个redis所有缓存keys * 查看所有key值del key 删除指定索引的值 注意&#xff1a; 我们清空缓存的时候&#xff0c;需要确保redis-…

JCEF中js与java交互、js与java相互调用

jcef中js与java相互调用&#xff0c;java与js相互调用&#xff0c;chrome与java相互调用&#xff0c;java与chrome相互调用、jcef与java相互调用 前提&#xff1a;https://blog.csdn.net/weixin_44480167/article/details/133170970&#xff08;java内嵌浏览器CEF-JAVA、jcef、…

网络工程师的爬虫技术之路:跨界电商与游戏领域的探索

随着数字化时代的到来&#xff0c;跨界电商和游戏行业成为了网络工程师们充满机遇的领域。这两个领域都依赖于高度复杂的技术来实现商业目标和提供卓越的用户体验。本文将深入探讨网络工程师在跨界电商和游戏领域的技术挑战以及应对这些挑战的方法。 突破技术障碍的爬虫应用 …