文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PHP常见的SQL防注入方法

2023-09-26 12:16

关注

利用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 的更是方便,比如:

$sql = 'SELECT name,color,caloriesFROM fruitWHERE 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',$query);//Force floats to be locale unaware$query = pref_replace('|(?,"'%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.

示例:

// 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() 不接受连接参数,也不遵循当前字符集设定。

示例

$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://blog.csdn.net/weixin_43741253/article/details/133169038

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯