防止SQL注入简述

作者:小虾米 发表时间:2017-05-13 00:58:40 类别:MySql

Web安全常见的攻击方式:

  • SQL注入攻击
  • 跨站脚本攻击 - XSS
  • 跨站伪造请求攻击 - CSRF
  • 文件上传漏洞攻击
  • 分布式拒绝服务攻击 - DDOS

主要的防范方式:

  • 变量的检测、过滤、验证

具体方式:

1、检查变量数据类型和格式:
       确保传进来的数据都是所需要的数据格式。如id就确保是int类型,email的格式做严格检查,用户注册登录的用户名就要设置要检查规则(字符长度、字符串组成方式、不包含特殊字符等)。只要是有固定格式的变量,在SQL语句执行前,应该严格按照固定格式去检查,确保变量是我们预想的格式。

2、过滤特殊符号:

       无法确定固定格式的变量,进行特殊符号过滤或转义。对于PHP程序+MySQL构架的程序,在动态的SQL语句中,使用单引号把变量包含起来配合addslashes函数是应对SQL注入攻击的有效手段,但这做的还不够,像上面的2条SQL语句,根据「检查数据类型」的原则,uid都应该经过intval函数格式为int型,这样不仅能有效避免第二条语句的SQL注入漏洞,还能使得程序看起来更自然,尤其是在NoSQL(如MongoDB)中,变量类型一定要与字段类型相匹配才可以。

       但是黑客可以将字符串转为16进制编码数据或使用char函数进行转化,同样能达到相同的目的,如果对这部分内容感兴趣,可以点击这里查看。而且由于SQL保留关键字,如「HAVING」、「ORDER BY」的存在,即使是基于黑白名单的过滤方法仍然会有或多或少问题,那么是否还有其他方法来防御SQL注入呢?

3、绑定变量,使用预编译语句
MySQL的mysqli驱动提供了预编译语句的支持,不同的程序语言,都分别有使用预编译语句的方法,我们这里仍然以PHP为例,编写userinfo2.php代码:

<?php
header('Content-type:text/html; charset=UTF-8');
$username = isset($_GET['username']) ? $_GET['username'] : '';
$userinfo = array();
if($username){
    //使用mysqli驱动连接demo数据库
    $mysqli = new mysqli("localhost", "root", "root", 'demo');
    //使用问号替代变量位置
    $sql = "SELECT uid,username FROM user WHERE username=?";
    $stmt = $mysqli->prepare($sql);
    //绑定变量
    $stmt->bind_param("s", $username);
    $stmt->execute();
    $stmt->bind_result($uid, $username);
    while ($stmt->fetch()) {
        $row = array();
        $row['uid'] = $uid;
        $row['username'] = $username;
        $userinfo[] = $row;
    }
}
echo '<pre>',print_r($userinfo, 1),'</pre>';

从上面的代码可以看到,我们程序里并没有使用addslashes函数,但是浏览器里运行 http://localhost/test/userinfo2.php?username=plhwin' AND 1=1-- hack里得不到任何结果,说明SQL漏洞在这个程序里并不存在。

实际上,绑定变量使用预编译语句是预防SQL注入的最佳方式,使用预编译的SQL语句语义不会发生改变,在SQL语句中,变量用问号?表示,黑客即使本事再大,也无法改变SQL语句的结构,像上面例子中,username变量传递的plhwin' AND 1=1-- hack参数,也只会当作username字符串来解释查询,从根本上杜绝了SQL注入攻击的发生。

总结:
1、不要随意开启生产环境中Webserver的错误显示。
2、永远不要信任来自用户端的变量输入,有固定格式的变量一定要严格检查对应的格式,没有固定格式的变量需要对引号等特殊字符进行必要的过滤转义。
3、使用预编译绑定变量的SQL语句。
4、做好数据库帐号权限管理。
5、严格加密处理用户的机密信息。

本文节选自博客《潘良虎的随想录》

参考网址:
生活的主色调就是无奈的。比的就是谁过的更精彩。
沪ICP备17012897号-1 | Copyright ©2024