PHP常见的SQL防注入方法

这篇具有很好参考价值的文章主要介绍了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 up
	if(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 %%s
	array_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() 不转义 % 和 _。文章来源地址https://www.toymoban.com/news/detail-731223.html

到了这里,关于PHP常见的SQL防注入方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【MySQL】MySQL PHP 语法,PHP MySQL 简介,查询,下载 MySQL 数据库, SQL 教程

    作者简介: 辭七七,目前大一,正在学习C/C++,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 七七的闲谈 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 MySQL 可应用于多种语言,包括 PERL, C, C++, JAVA 和 PHP,在这些语言中,MySQL 在 PHP 的 web 开发中是应用最广泛。 我们

    2024年02月11日
    浏览(41)
  • 金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞复现 [附POC]

    免责声明:请勿利用文章内的相关

    2024年02月03日
    浏览(48)
  • SQL 日期处理和视图创建:常见数据类型、示例查询和防范 SQL 注入方法

    在数据库操作中,处理日期是一个关键的方面。确保插入的日期格式与数据库中日期列的格式匹配至关重要。以下是一些常见的SQL日期数据类型和处理方法。 DATE - 格式为YYYY-MM-DD DATETIME - 格式为YYYY-MM-DD HH:MI:SS TIMESTAMP - 格式为YYYY-MM-DD HH:MI:SS YEAR - 格式为YYYY或YY DATE - 格式为YY

    2024年02月05日
    浏览(45)
  • SQL注入常见方式

    许多网页都有如下的网址 注入点 id 类型为数字,在大多数的网页中,例如查看用户个人信息,查看文章等,大都会使用这种形式的结构传递id等信息,交给后端,查询出数据库中对应的信息,返回给前台。 这一类的 SQL 语句原型大概为 select * from 表名 where id=1 若存在注入,我

    2024年01月24日
    浏览(24)
  • 常见的SQL注入类型

    SQL注入简单原理 * 注:?为php语言中的输入符 (1)、按注入点区分: 1、数字型注入 数字型注入主要存在于网站的 url 中有?id=处,如:http://xxx.com/index.php?id=1 通过改变id=的数值来判断是否有注入点,一般常见测试手段是令id等于一个不常见的大数,通过页面是否变化来判断是

    2023年04月24日
    浏览(30)
  • 常见的一些SQL注入漏洞类型

    刚接触SQL注入,写一遍笔记帮助自己回顾知识或者给其他有需要的小伙伴。可能文中有的地方讲的不对,希望可以得到大佬们的纠正,谢谢! SQL 注入是一种网络安全漏洞,允许攻击者干扰应用程序对其数据库的查询。它通常允许攻击者查看他们通常无法检索的数据。这可能

    2024年02月07日
    浏览(38)
  • php怎么连接sql server

    在PHP中,可以使用不同的函数来连接SQL Server数据库。根据不同的版本和需求,有以下几种方法可以连接SQL Server。一、mssql_系列函数:主要适用于PHP5.3以下的版本和SQL Server 2000及以上的版本。需要在php.ini文件中去掉以下代码前的分号: 以上是几种常用的连接SQL Server数据库的

    2024年02月09日
    浏览(33)
  • 无涯教程-PHP - sql_regcase()函数

    可以将sql_regcase()函数视为实用程序函数,它将输入参数字符串中的每个字符转换为包含两个字符的带括号的表达式。 返回带括号的表达式字符串以及转换后的字符。 这将产生以下输出- PHP 中的 sql_regcase()函数 - 无涯教程网 无涯教程网提供sql_regcase() - 语法 string sql_regcase ( s

    2024年02月11日
    浏览(20)
  • SQL注入之MYSQL注入

    前言(菜鸡教程大佬勿喷) MYSQL注入中首先要明确当前注入点权限,高权限注入时有更多的攻击手法,有的能直接进行getshell操作。其中也会遇到很多阻碍,相关防御方案也要明确,所谓知己知彼,百战不殆。不论作为攻击还是防御都需要了解其中的手法和原理,这样才是一个

    2024年02月05日
    浏览(42)
  • 搭建sql-lab出现的php不兼容

    下载不了的时候,直接打开该网址下载5.xphp版本,解压到C:php_studyv8phpstudyphpstudy_proExtensionsphp(可能路径都不一样,找到Extensionsphp放到该目录下) 

    2024年04月23日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包