博主信息
博文 2
粉丝 0
评论 0
访问量 5521
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
谈谈如何防止SQL注入
Draymond的博客
原创
1008人浏览过

SQL注入

造成SQL注入的原因

SQL注入是通过在SQL语句被数据库解析之前,以修改其语法的形式工作的。只要你在解析语句之前插入动态部分,就存在SQL注入的风险。

动态部分:1、 用户传递进来的参数 2、 有可能是从数据库查询出来的

防止SQL注入的一些方法

转义

防止SQL语句包含任何不匹配的引号的最古老的方法,就是对所有的引号字符进行转义操作,使他们不至于成为字符串的结束符。

比如PDO的quote()函数

查询参数

查询参数的做法是在准备查询语句的时候,在对应参数的地方使用参数占位符。随后,在执行这个预先准备好的查询时提供一个参数。

$stmt = $pdo->prepare('select id,name from user where name = ?');

$params = array($_POST['name']);

$stmt->execute($params);

查询参数的不足:

   1. 多个值的列表不可以当成单一参数

       $stmt = $pdo->prepare('select * from user where id in (?)');

       $stmt->execute(array('1,2,3'));

       上面的查询结果和下面的不一样:

       select * from user where id in(1,2,3)

   2. 表名无法作为参数

       $stmt = $pdo->prepare('select id,name from ? where id =12');

       $stmt->execute(array('user'));

       这么做是想将一个字符串插入表名所在位置,但是这是报错的

   3. 列名无法作为参数

       //这是错误的
       $stmt = $pdo->prepare('select ? from ?user where id =12');

   4. SQL关键字不能作为参数

       //这是错误的
       $stmt = $pdo->prepare('select id,name from user order by id ?');

       $stmt->execute(array('desc'));

就算是使用预处理插入数据的,也需要转义

因为当你仅仅只是使用预处理执行插入语句,敏感字符是不会被转义的。后果是:在后续的查询中动态地使用未转义的数据也是有风险的。

$sql = 'select * from user where id = 3';

$row = $pdo->query($sql)->fetch(2);

//当$row['name']值为 o'jack就会导致执行错误。
//当$row['name']值为 ' or 1=1;#  就会将表的所有数据查询出来
$sql = "select * from user where name = "."'{$row['name']}'";

$stmtObj = $pdo->query($sql);

对策: 所以不管是不是用户传递过来的参数,最好也使用预处理的方式来执行查询语句

检查输入的数据是否具有所期望的数据格式

$sql = 'select id,name from user where id > ?';

//这个时候,保证传递进来的一定是一个数字
$stmt = $pdo->prepare($sql);
$params = array(
   intval($_GET['id'])
);
$stmt->execute($params);

预处理原理

数据库首先会解析准备好的SQL查询语句,在完成这一步操作之后,就没有任何方法能够改变那句SQL查询语句的结构。

在执行一个已经准备好的SQL查询语句时,需要提供对应的参数,每个你提供的参数都对应预先准备好的查询语句中的一个占位符

重复执行这个预先准备好的查询语句,只需要使用新的参数替换老的参数就行。

将用户与代码隔离

预处理(查询参数)和转义字符能够帮助你将字符串类型的值插入到SQL中,但这些技术在需要插入表/列名或者SQL关键字的时候不起作用。

问题:

$sortOrder = $_GET['sort'];//用户传递过来的

//直接将用户传递过来的数据,拼接成SQl语句,不安全。
$sql = "select id,name from user order by $sortOrder";

解决:

将请求的参数作为索引值去查找预先定义好的值,然后用这些预先定义的值来组织SQL查询语句。

$sortCondition = array(
   'up' => 'ASC',
   'down' => 'DESC'
);


//当需要倒序,用户传递down
$sortOrder = $_GET['sort'];//用户传递过来的数据

if (array_key_exists($sortOrder, $sortCondition) ) {

   $sort = $sortCondition[$sortOrder];
} else {
   $sort = 'DESC';
}

//现在$sort这变量就是安全的了,因为他只能是$sortCondition预先定义的值
$sql = "select id,name from user order by $sort";

审查代码

找到瑕疵的最好方法就是找一双眼睛一起来看看。

在检查代码是否包含SQL注入风险的时候,参考下面几点建议:

找出所有使用了程序变量、字符串连接或者替换等方法组成的SQL语句

跟踪在SQL语句中使用的动态内容来源。找出所有外部的输入,比如用户输入、文件、系统环境、网络服务、第三方代码、,甚至从数据库中获取的字符串

假设任何外部内容都是潜在的威胁。对于不受信任的内容都要进行过滤,验证或者使用数组映射的方式来处理(参考“将用户与代码隔离”)

在将外部数据合并到SQL语句时,使用查询参数,或者用稳健的转义函数预先处理

别忘了在存储过程的代码以及任何其他使用SQL动态查询语句的地方做同样的检查

备注: 代码检查是找出SQL注入缺陷的最正确和经济的方法


本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!
全部评论 文明上网理性发言,请遵守新闻评论服务协议
0条评论
作者最新博文
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

  • 登录PHP中文网,和优秀的人一起学习!
    全站2000+教程免费学