Web 安全 - SQL注入

2017-01-11 Kevin 更多博文 » 博客 » GitHub »

Web安全

原文链接 https://kevindiamen.github.io/web%E5%AE%89%E5%85%A8/2017/01/11/Web%E5%AE%89%E5%85%A8-Sql%E6%B3%A8%E5%85%A5.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


Web 安全 - SQL注入

介绍

SQL注入攻击(SQL Injection), 是由于程序没有过滤恶意提交的SQL查询,最终达到欺骗服务器执行恶意的SQL命令

SQL注入案例

如果直接拼接 SQL 而没有进行任何处理, 像下面这样就会有恶意的用户输入导致改变你的 SQL queries

mysql_query('UPDATE users  SET first_name="' . $_POST['first_name'] . '"
  WHERE id=1001');

你期望生成的SQL:

UPDATE users set first_name="Liz" WHERE id=1001;

但是如果恶意的用户 first_name 的值为:

Liz", last_name="Lemon"; --

最终的 SQL 变成:

UPDATE users SET first_name="Liz", last_name="Lemon"; --" WHERE id=1001;

现在所有的 users 表中名字为 Liz Lemon 的就会查询出来

SQL注入防御

绑定参数

一个比较好的并且简单的方法就是绑定参数的方法, 用绑定参数的每个值将会被转义并且也会忽略掉编码问题, 不要用拼接SQL的方法这样已经被证实并不安全, 也不建议用 addslashes() 方法, 因为在 Mysql5.5 之前 可以通过编码单字节双字节问题进行绕过, 下面是PHP的PDO class.

绑定参数 Mysql 会创建 sql语句模板,并发送到数据库。预留的值使用参数 ? 标记数据库对模板解析,编译,对sql 语句模板执行查询优化 ,预处理语句能很好的防止 sql注入,因为参数的发送不会影响一开始对模板的解析,编译。

$db = new PDO(...);
$query = $db->prepare('UPDATE users SET first_name = :first_name WHERE id = :id');

$query->execute([
  ':first_name' => $_POST['first_name']
]);
  • 输出处理 : 虽然绑定参数可以保护你的query 但是数据可能是恶意的 所以你显示给用户的时候还需要做处理
  • 过滤参数 : 比如手机号 邮箱可以用正则表达式匹配, PHP 建议使用 filter_ var() 和 filter_input() 函数可以过滤文本并对格式进行校验

存储过程

存储过程是另一个方法去避免SQL注入, 他是一组完成特定功能的SQL,经过编译后存储在数据库中, 但是存储过程比较麻烦主要有几点原因:

  • 调试麻烦
  • 移植问题
  • 逻辑在另一个应用上