一, SQL 注入简介
SQL 注入是比较常见的网络攻击方式之一, 它不是利用操作系统的 BUG 来实现攻击, 而是针对程序员编写时的疏忽, 通过 SQL 语句, 实现无账号登录, 甚至篡改数据库.
二, SQL 注入攻击的总体思路
寻找到 SQL 注入的位置
判断服务器类型和后台数据库类型
针对不同的服务器和数据库特点进行 SQL 注入攻击
三, SQL 注入攻击实例
比如在一个登录界面, 要求输入用户名和密码:
可以这样输入实现免帐号登录:
用户名: 'or 1 = 1 -
密 码:
点登陆, 如若没有做特殊处理, 那么这个非法用户就很得意的登陆进去了.(当然现在的有些语言的数据库 API 已经处理了这些问题)
这是为什么呢? 下面我们分析一下:
从理论上说, 后台认证程序中会有如下的 SQL 语句:
- String sql = "select * from user_table where username=
- '"+userName+" 'and password=' "+password+" '";
当输入了上面的用户名和密码, 上面的 SQL 语句变成:
- SELECT * FROM user_table WHERE username=
- ''or 1 = 1 -- and password=''
- """
- 分析 SQL 语句:
- 条件后面 username="or 1=1 用户名等于" 或 1=1 那么这个条件一定会成功;
- 然后后面加两个 -, 这意味着注释, 它将后面的语句注释, 让他们不起作用, 这样语句永远都能正确执行, 用户轻易骗过系统, 获取合法身份.
- 这还是比较温柔的, 如果是执行
- SELECT * FROM user_table WHERE
- username='';DROP DATABASE (DB Name) --' and password=''
- 其后果可想而知...
- """
四, 如何防御 SQL 注入
注意: 但凡有 SQL 注入漏洞的程序, 都是因为程序要接受来自客户端用户输入的变量或 URL 传递的参数, 并且这个变量或参数是组成 SQL 语句的一部分,
对于用户输入的内容或传递的参数, 我们应该要时刻保持警惕, 这是安全领域里的「外部数据不可信任」的原则, 纵观 web 安全领域的各种攻击方式,
大多数都是因为开发者违反了这个原则而导致的, 所以自然能想到的, 就是从变量的检测, 过滤, 验证下手, 确保变量是开发者所预想的.
1, 检查变量数据类型和格式
如果你的 SQL 语句是类似 where id={$id} 这种形式, 数据库里所有的 id 都是数字, 那么就应该在 SQL 被执行前, 检查确保变量 id 是 int 类型; 如果是接受邮箱, 那就应该检查并严格确保变量一定是邮箱的格式, 其他的类型比如日期, 时间等也是一个道理. 总结起来: 只要是有固定格式的变量, 在 SQL 语句执行前, 应该严格按照固定格式去检查, 确保变量是我们预想的格式, 这样很大程度上可以避免 SQL 注入攻击.
比如, 我们前面接受 username 参数例子中, 我们的产品设计应该是在用户注册的一开始, 就有一个用户名的规则, 比如 5-20 个字符, 只能由大小写字母, 数字以及一些安全的符号组成, 不包含特殊字符. 此时我们应该有一个 check_username 的函数来进行统一的检查. 不过, 仍然有很多例外情况并不能应用到这一准则, 比如文章发布系统, 评论系统等必须要允许用户提交任意字符串的场景, 这就需要采用过滤等其他方案了.
2, 过滤特殊符号
对于无法确定固定格式的变量, 一定要进行特殊符号过滤或转义处理.
3, 绑定变量, 使用预编译语句
MySQL 的 mysqli 驱动提供了预编译语句的支持, 不同的程序语言, 都分别有使用预编译语句的方法
实际上, 绑定变量使用预编译语句是预防 SQL 注入的最佳方式, 使用预编译的 SQL 语句语义不会发生改变, 在 SQL 语句中, 变量用问号? 表示, 黑客即使本事再大, 也无法改变 SQL 语句的结构
小结:
1. 使用预编译绑定变量的 SQL 语句
2. 严格加密处理用户的机密信息
3. 不要随意开启生产环境中 Webserver 的错误显示
4. 使用正则表达式过滤传入的参数
5. 字符串过滤
6. 检查是否包函非法字符
总的来说, 防范一般的 SQL 注入只要在代码规范上下点功夫就能预防
来源: http://www.bubuko.com/infodetail-3155838.html