如何有效防止sql注入的方法


Posted in SQL Server onMay 25, 2021

SQL注入攻击是黑客对数据库进行攻击常用的手段之一,随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。但是由于程序员的水平及经验参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想获取的数据,这就是所谓的SQL Injection,即SQL注入。

一 背景

假如某高校开发了一个网课系统,要求学生选课后完成学习,数据库中有一张表course,这张表存放着每个学生的选课信息及完成情况,具体设计如下:

如何有效防止sql注入的方法

数据如下:

如何有效防止sql注入的方法

本系统采用mysql做为数据库,使用Jdbc来进行数据库的相关操作。系统提供了一个功能查询该学生的课程完成情况,代码如下。

@RestController
public class Controller {
    
    @Autowired
    SqlInject sqlInject;
    
    @GetMapping("list")
    public List<Course> courseList(@RequestParam("studentId") String studentId){
        List<Course> orders = sqlInject.orderList(studentId);
        return orders;
    }
}
@Service
public class SqlInject {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public List<Course> orderList(String studentId){
        String sql = "select id,course_id,student_id,status from course where student_id = "+ studentId;
        return jdbcTemplate.query(sql,new BeanPropertyRowMapper(Course.class));
    }
}

二 注入攻击演示

1. 正常情况下查询一个学生所选课程及完成情况只需要传入student_id,便可以查到相关数据。

如何有效防止sql注入的方法

根据响应结果,我们很快便能写出对应的sql,如下:

select id,course_id,student_id,status 
from course 
where student_id = 4

2. 如果我们想要获取这张表的所有数据,只需要保证上面这个sql的where条件恒真就可以了。

select id,course_id,student_id,status 
from course 
where student_id = 4 or 1 = 1

请求接口的时候将studendId 设置为4 or 1 = 1,这样这条sql的where条件就恒真了。sql也就等同于下面这样

select id,course_id,student_id,status 
from course

请求结果如下,我们拿到了这张表的所有数据

如何有效防止sql注入的方法

3. 查询mysql版本号,使用union拼接sql

union select 1,1,version(),1

如何有效防止sql注入的方法

4. 查询数据库名

union select 1,1,database(),1

如何有效防止sql注入的方法

5. 查询mysql当前用户的所有库

union select 1,1, (SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata) schemaName,1

如何有效防止sql注入的方法

看完上面这些演示后,你害怕了吗?你所有的数据配置都完全暴露出来了,除此之外,还可以完成很多操作,更新数据、删库、删表等等。

三 如何防止sql注入

1. 代码层防止sql注入攻击的最佳方案就是sql预编译

public List<Course> orderList(String studentId){
    String sql = "select id,course_id,student_id,status from course where student_id = ?";
    return jdbcTemplate.query(sql,new Object[]{studentId},new BeanPropertyRowMapper(Course.class));
}

这样我们传进来的参数 4 or 1 = 1就会被当作是一个student_id,所以就不会出现sql注入了。

2. 确认每种数据的类型,比如是数字,数据库则必须使用int类型来存储

3. 规定数据长度,能在一定程度上防止sql注入

4. 严格限制数据库权限,能最大程度减少sql注入的危害

5. 避免直接响应一些sql异常信息,sql发生异常后,自定义异常进行响应

6. 过滤参数中含有的一些数据库关键词

@Component
public class SqlInjectionFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req=(HttpServletRequest)servletRequest;
        HttpServletRequest res=(HttpServletRequest)servletResponse;
        //获得所有请求参数名
        Enumeration params = req.getParameterNames();
        String sql = "";
        while (params.hasMoreElements()) {
            // 得到参数名
            String name = params.nextElement().toString();
            // 得到参数对应值
            String[] value = req.getParameterValues(name);
            for (int i = 0; i < value.length; i++) {
                sql = sql + value[i];
            }
        }
        if (sqlValidate(sql)) {
            throw new IOException("您发送请求中的参数中含有非法字符");
        } else {
            chain.doFilter(servletRequest,servletResponse);
        }
    }

    /**
     * 关键词校验
     * @param str
     * @return
     */
    protected static boolean sqlValidate(String str) {
        // 统一转为小写
        str = str.toLowerCase();
        // 过滤掉的sql关键字,可以手动添加
        String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|" +
                "char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
                "table|from|grant|use|group_concat|column_name|" +
                "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
                "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";
        String[] badStrs = badStr.split("\\|");
        for (int i = 0; i < badStrs.length; i++) {
            if (str.indexOf(badStrs[i]) >= 0) {
                return true;
            }
        }
        return false;
    }
}

到此这篇关于如何有效防止sql注入的方法的文章就介绍到这了,更多相关sql防止注入内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

SQL Server 相关文章推荐
SQL 尚未定义空闲 CPU 条件 - OnIdle 作业计划将不起任何作用
Jun 30 SQL Server
利用 SQL Server 过滤索引提高查询语句的性能分析
Jul 15 SQL Server
SQL中的三种去重方法小结
Nov 01 SQL Server
SQL SERVER触发器详解
Feb 24 SQL Server
通过T-SQL语句创建游标与实现数据库加解密功能
Mar 16 SQL Server
SQL Server表分区降低运维和维护成本
Apr 08 SQL Server
SQL Server 忘记密码以及重新添加新账号
Apr 26 SQL Server
SQL Server中搜索特定的对象
May 25 SQL Server
一次SQL查询优化原理分析(900W+数据从17s到300ms)
Jun 10 SQL Server
详解SQL报错盲注
Jul 23 SQL Server
SQL 窗口函数实现高效分页查询的案例分析
mybatis调用sqlserver存储过程返回结果集的方法
SQL Server2019数据库之简单子查询的具有方法
Apr 27 #SQL Server
SQL Server中交叉联接的用法详解
SqlServer 垂直分表(减少程序改动)
Apr 16 #SQL Server
sqlserver2017共享功能目录路径不可改的解决方法
SQLServer2008提示评估期已过解决方案
You might like
php仿ZOL分页类代码
2008/10/02 PHP
php file_exists 检查文件或目录是否存在的函数
2010/05/10 PHP
浏览器预览PHP文件时顶部出现空白影响布局分析原因及解决办法
2013/01/11 PHP
Zend Framework框架之Zend_Mail实现发送Email邮件验证功能及解决标题乱码的方法
2016/03/21 PHP
PHP基于回溯算法解决n皇后问题的方法示例
2017/11/07 PHP
用php定义一个数组最简单的方法
2019/10/04 PHP
JavaScript CSS 修改学习第四章 透明度设置
2010/02/19 Javascript
使用jQuery.fn自定义jQuery翻页插件
2013/01/20 Javascript
jQuery异步验证用户名是否存在示例代码
2014/05/21 Javascript
jQuery实现行文字链接提示效果的方法
2015/03/10 Javascript
JavaScript和jQuery获取input框的绝对位置实现方法
2016/10/13 Javascript
微信小程序 swiper组件详解及实例代码
2016/10/25 Javascript
bootstrapValidator.min.js表单验证插件
2017/02/09 Javascript
JavaScript中常见的八个陷阱总结
2017/06/28 Javascript
AngularJs点击状态值改变背景色的实例
2017/12/18 Javascript
vue-cli实现多页面多路由的示例代码
2018/01/30 Javascript
p5.js入门教程之小球动画示例代码
2018/03/15 Javascript
详解基于Node.js的HTTP/2 Server实践
2018/05/31 Javascript
微信小程序页面调用自定义组件内的事件详解
2019/09/12 Javascript
原生js实现俄罗斯方块
2020/10/20 Javascript
[50:15]VP vs Mineski 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
Python做简单的字符串匹配详解
2017/03/21 Python
Java实现的执行python脚本工具类示例【使用jython.jar】
2018/03/29 Python
根据DataFrame某一列的值来选择具体的某一行方法
2018/07/03 Python
Python 字符串换行的多种方式
2018/09/06 Python
python实现爬山算法的思路详解
2019/04/09 Python
Python 的字典(Dict)是如何存储的
2019/07/05 Python
python set集合使用方法解析
2019/11/05 Python
python实现加密的方式总结
2020/01/19 Python
伦敦香水公司:The London Perfume Company
2019/11/13 全球购物
元宵节主持词
2014/03/25 职场文书
《第一朵杏花》教学反思
2014/04/16 职场文书
学校对教师的评语
2014/04/28 职场文书
搞笑的爱情检讨书
2014/10/01 职场文书
党员民主评议个人总结
2014/10/20 职场文书
初中军训感言
2015/08/01 职场文书