简单聊一聊SQL注入及防止SQL注入


Posted in MySQL onMarch 23, 2022

SQL注入

SQL注入是通过操作输入来修改事先定义好的SQL语句,对用户输入的字符串进行过滤,转义,限制或处理不严谨,导致用户可以通过输入精心构造的字符串去非法获取到数据库中的数据,以达到执行代码对服务器进行攻击的方法。

现有一个数据库test中的表user,可以通过账号name,密码pass登录,查看id

简单聊一聊SQL注入及防止SQL注入

登录代码

package JDBCtest;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

/*
 * 用户登录
 */
public class Demo4 {

    public static void main(String[] args) throws Exception {
        // 1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 2.创建连接
        String url = "jdbc:mysql:///test";
        String username = "root";
        String password = "1234";
        Connection connection = DriverManager.getConnection(url, username, password);
        // 接收用户名密码
        Scanner sc = new Scanner(System.in);
        String name = sc.next();
        String pass = sc.next();// 3.sql语句
        String sql = "Select * from user where name='" + name + "' and pass ='" + pass + "'";
        // System.out.println(sql);
        // 4.获取sql对象statement
        Statement statement = connection.createStatement();
        // 5.执行sql语句
        ResultSet rs = statement.executeQuery(sql);
                // 6.登录
        if (rs.next()) {
            System.out.println("登录成功");
        } else {
            System.out.println("登录失败");
        }
        // 7.释放资源
        statement.close();
        connection.close();
    }
}

通过表中账号密码登录成功

简单聊一聊SQL注入及防止SQL注入简单聊一聊SQL注入及防止SQL注入

由于账号或密码错误登录失败

简单聊一聊SQL注入及防止SQL注入简单聊一聊SQL注入及防止SQL注入

以上可以正确登录成功或失败

注意!

如果此时我这样输入 【lihua 'or'1'='1】,也成功登录了,但是数据库没根本没有这条数据

简单聊一聊SQL注入及防止SQL注入

这是为什么呢?让我们从代码里找问题!

String sql = "Select * from user where name='" + name + "' and pass ='" + pass + "'";

为了调用数据库,使用字符串拼接SQL语句

让我们打印一下输入 【lihua 'or'1'='1】的sql语句一探究竟

简单聊一聊SQL注入及防止SQL注入

select语句中的where条件可以看做两组并列(注意and在前先执行,or后执行)

简单聊一聊SQL注入及防止SQL注入

由于'1'='1'为TRUE,所以以上语句等价于简单聊一聊SQL注入及防止SQL注入肯定会登录成功!

同理输入【'or'1'='1'# xxx】也能登陆成功

简单聊一聊SQL注入及防止SQL注入

这是由于#在SQL中是注释符号,以上语句等价于简单聊一聊SQL注入及防止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注入内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
MySQL 使用事件(Events)完成计划任务
May 24 MySQL
MySQL中distinct与group by之间的性能进行比较
May 26 MySQL
MySQL通过binlog恢复数据
May 27 MySQL
MySQL系列之一 MariaDB-server安装
Jul 02 MySQL
MySQL 用 limit 为什么会影响性能
Sep 15 MySQL
关于MySQL中的 like操作符详情
Nov 17 MySQL
SQL注入篇学习之盲注/宽字节注入
Mar 03 MySQL
面试提问mysql一张表到底能存多少数据
Mar 13 MySQL
MySQL读取JSON转换的方式
Mar 18 MySQL
mysql的Buffer Pool存储及原理
Apr 02 MySQL
jdbc中自带MySQL 连接池实践示例
Jul 23 MySQL
MySQL深分页问题解决思路
Dec 24 MySQL
浅谈MySQL中的六种日志
Mar 23 #MySQL
WINDOWS 64位 下安装配置mysql8.0.25最详细的教程
实战 快速定位MySQL的慢SQL
关于MySQL临时表为什么可以重名的问题
将MySQL的表数据全量导入clichhouse库中
Mar 21 #MySQL
MySQL分区表管理命令汇总
Mar 21 #MySQL
Linux系统下MySQL配置主从分离的步骤
You might like
PHP版微信公众平台红包API
2015/04/02 PHP
php链式操作的实现方式分析
2019/08/12 PHP
JavaScript之编码规范 推荐
2012/05/23 Javascript
js防止页面被iframe调用的方法
2014/10/30 Javascript
浅谈JavaScript中指针和地址
2015/07/26 Javascript
JS设置cookie、读取cookie
2016/02/24 Javascript
Javascript删除指定元素节点的方法
2016/06/21 Javascript
RGB和YUV 多媒体编程基础详细介绍
2016/11/04 Javascript
BootStrap Table 获取同行不同列元素的方法
2016/12/19 Javascript
NodeJS遍历文件生产文件列表功能示例
2017/01/22 NodeJs
bootstrap daterangepicker双日历时间段选择控件详解
2017/06/15 Javascript
聊聊Vue.js的template编译的问题
2017/10/09 Javascript
详解Vue项目编译后部署在非网站根目录的解决方案
2018/04/26 Javascript
js实现简单的日历显示效果函数示例
2019/11/25 Javascript
Element Rate 评分的使用方法
2020/07/27 Javascript
javascript的hashCode函数实现代码小结
2020/08/11 Javascript
三剑客:offset、client和scroll还傻傻分不清?
2020/12/04 Javascript
如何在vue中使用HTML 5 拖放API
2021/01/14 Vue.js
pymongo为mongodb数据库添加索引的方法
2015/05/11 Python
python实现多线程的两种方式
2016/05/22 Python
python 动态调用函数实例解析
2019/10/21 Python
基于h5py的使用及数据封装代码
2019/12/26 Python
Keras自定义IOU方式
2020/06/10 Python
基于matplotlib中ion()和ioff()的使用详解
2020/06/16 Python
python map比for循环快在哪
2020/09/21 Python
原装进口全世界:天猫国际
2016/08/03 全球购物
如何在.net Winform里面显示PDF文档
2012/09/11 面试题
酒店总经理工作职责
2013/12/13 职场文书
高三英语教学反思
2014/01/13 职场文书
军校本科大学生自我评价
2014/01/14 职场文书
办理收楼委托书范本
2014/10/09 职场文书
2014年志愿者工作总结
2014/11/20 职场文书
2014年小学体育工作总结
2014/12/11 职场文书
灵山大佛导游词
2015/02/04 职场文书
2015年评职称工作总结范文
2015/04/20 职场文书
入党团支部推荐意见
2015/06/02 职场文书