简单聊一聊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 Router的安装部署
Apr 24 MySQL
MySQL 使用事件(Events)完成计划任务
May 24 MySQL
修改MySQL的默认密码的四种小方法
May 26 MySQL
浅谈mysql返回Boolean类型的几种情况
Jun 04 MySQL
MySQL为id选择合适的数据类型
Jun 07 MySQL
mysql连接查询中and与where的区别浅析
Jul 01 MySQL
一文搞清楚MySQL count(*)、count(1)、count(col)区别
Mar 03 MySQL
优化Mysql查询的示例
Apr 26 MySQL
MySQL的prepare使用以及遇到的bug
May 11 MySQL
MySQL示例讲解数据库约束以及表的设计
Jun 16 MySQL
数据设计之权限的实现
Aug 05 MySQL
MySQL中LAG()函数和LEAD()函数的使用
Aug 14 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
PHILIPS D1835/D1875的电路分析与打理
2021/03/02 无线电
php遍历目录与文件夹的多种方法详解
2013/11/14 PHP
PHP实现数字补零功能的2个函数介绍
2014/05/12 PHP
PHP定时任务延缓执行的实现
2014/10/08 PHP
Centos PHP 扩展Xchche的安装教程
2016/07/09 PHP
PHP静态方法和静态属性及常量属性的区别与介绍
2019/03/22 PHP
laravel-admin自动生成模块,及相关基础配置方法
2019/10/08 PHP
jQuery Tools tab(幻灯片)
2012/07/14 Javascript
Jquery+asp.net后台数据传到前台js进行解析的方法
2014/05/11 Javascript
创建基于Bootstrap的下拉菜单的DropDownList的JQuery插件
2016/06/02 Javascript
原生JS版和jquery版实现checkbox的全选/全不选/点选/行内点选(Mr.Think)
2016/10/29 Javascript
正则中的回溯定义与用法分析【JS与java实现】
2016/12/27 Javascript
Node.js中如何合并两个复杂对象详解
2016/12/31 Javascript
Iscrool下拉刷新功能实现方法(推荐)
2017/06/26 Javascript
原生js实现form表单序列化的方法
2018/08/02 Javascript
解决webpack dev-server不能匹配post请求的问题
2018/08/24 Javascript
使用JS获取页面上的所有标签
2018/10/18 Javascript
vue-better-scroll 的使用实例代码详解
2018/12/03 Javascript
JavaScript 性能提升之路(推荐)
2019/04/10 Javascript
uni-app 组件里面获取元素宽高的实现
2019/12/27 Javascript
简单了解three.js 着色器材质
2020/08/03 Javascript
ant-design-vue 时间选择器赋值默认时间的操作
2020/10/27 Javascript
[01:18]一目了然!DOTA2DotA快捷操作对比第一弹
2014/07/01 DOTA
[01:35]2014DOTA2西雅图邀请赛 专访狐狸妈青春献给刀塔
2014/07/08 DOTA
[03:59]第二届DOTA2亚洲邀请赛选手传记-VGJ.rOtk
2017/04/03 DOTA
python实现微信自动回复机器人功能
2019/07/11 Python
设置jupyter中DataFrame的显示限制方式
2020/04/12 Python
python模拟实现分发扑克牌
2020/04/22 Python
Django nginx配置实现过程详解
2020/09/10 Python
python批量提取图片信息并保存的实现
2021/02/05 Python
HTML5输入框下拉菜单功能的示例代码
2020/09/08 HTML / CSS
幼儿园的门卫岗位职责
2014/04/10 职场文书
2014年十一国庆向国旗敬礼寄语
2014/04/11 职场文书
五水共治一句话承诺
2014/05/30 职场文书
Java中CyclicBarrier和CountDownLatch的用法与区别
2021/08/23 Java/Android
Debian11 Xfce终端光标的颜色怎么设置?
2022/08/14 数码科技