如何有效防止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 相关文章推荐
SqlServer 垂直分表(减少程序改动)
Apr 16 SQL Server
如何有效防止sql注入的方法
May 25 SQL Server
利用 SQL Server 过滤索引提高查询语句的性能分析
Jul 15 SQL Server
SQLServer之常用函数总结详解
Aug 30 SQL Server
SQL Server2019数据库备份与还原脚本,数据库可批量备份
Nov 20 SQL Server
sql server 累计求和实现代码
Feb 28 SQL Server
Sql Server之数据类型详解
Feb 28 SQL Server
通过T-SQL语句创建游标与实现数据库加解密功能
Mar 16 SQL Server
SQL Server远程连接的设置步骤(图文)
Mar 23 SQL Server
Sql Server 行数据的某列值想作为字段列显示的方法
Apr 20 SQL Server
使用MybatisPlus打印sql语句
Apr 22 SQL Server
SQL Server中T-SQL标识符介绍与无排序生成序号的方法
May 25 SQL Server
SQL 窗口函数实现高效分页查询的案例分析
mybatis调用sqlserver存储过程返回结果集的方法
SQL Server2019数据库之简单子查询的具有方法
Apr 27 #SQL Server
SQL Server中交叉联接的用法详解
SqlServer 垂直分表(减少程序改动)
Apr 16 #SQL Server
sqlserver2017共享功能目录路径不可改的解决方法
SQLServer2008提示评估期已过解决方案
You might like
5.PHP的其他功能
2006/10/09 PHP
Thinkphp模板中使用自定义函数的方法
2012/09/23 PHP
使用php发送有附件的电子邮件-(PHPMailer使用的实例分析)
2013/04/26 PHP
php模拟ping命令(php exec函数的使用方法)
2013/10/25 PHP
jQuery 选择器、DOM操作、事件、动画
2010/11/25 Javascript
远离JS灾难css灾难之 js私有函数和css选择器作为容器
2011/12/11 Javascript
javascript中的window.location.search方法简介
2013/09/02 Javascript
Jquery EasyUI的添加,修改,删除,查询等基本操作介绍
2013/10/11 Javascript
JS设置获取cookies的方法
2014/01/26 Javascript
使用js实现数据格式化
2014/12/03 Javascript
Flash图片上传组件 swfupload使用指南
2015/03/14 Javascript
jQuery原理系列-常用Dom操作详解
2016/06/07 Javascript
nodejs redis 发布订阅机制封装实现方法及实例代码
2016/12/15 NodeJs
VueJs路由跳转——vue-router的使用详解
2017/01/10 Javascript
详解vue-cli 构建Vue项目遇到的坑
2017/08/30 Javascript
JS实现集合的交集、补集、差集、去重运算示例【ES5与ES6写法】
2019/02/18 Javascript
微信小程序swiper实现文字纵向轮播提示效果
2020/01/21 Javascript
解决echarts数据二次渲染不成功的问题
2020/07/20 Javascript
js实现弹窗效果
2020/08/09 Javascript
js实现Element中input组件的部分功能并封装成组件(实例代码)
2021/03/02 Javascript
[05:06]TI4西雅图DOTA2前线报道 海涛密探LGD训练
2014/07/09 DOTA
[03:35]2018年度DOTA2最佳辅助位选手5号位-完美盛典
2018/12/17 DOTA
Python通过Django实现用户注册和邮箱验证功能代码
2017/12/11 Python
Flask框架WTForm表单用法示例
2018/07/20 Python
python实现写数字文件名的递增保存文件方法
2018/10/25 Python
Python中@property的理解和使用示例
2019/06/11 Python
利用canvas实现图片压缩的示例代码
2018/07/17 HTML / CSS
数据库测试通常都包括哪些方面
2015/11/30 面试题
Java Servlet的主要功能和作用是什么
2014/02/14 面试题
护士的岗位职责
2013/12/04 职场文书
培训专员岗位职责
2014/02/26 职场文书
拾金不昧表扬信
2015/01/16 职场文书
交通安全教育主题班会
2015/08/12 职场文书
研究生学习计划书应该怎么写?
2019/09/10 职场文书
浅谈Python实现opencv之图片色素的数值运算和逻辑运算
2021/06/23 Python
vue实现书本翻页动画效果实例详解
2022/04/08 Vue.js