JavaWeb | 揭开SQL注入问题的神秘面纱

时间:2023-01-27 16:52:00

本专栏主要是记录学习完JavaSE后学习JavaWeb部分的一些知识点总结以及遇到的一些问题等,如果刚开始学习Java的小伙伴可以点击下方连接查看专栏
本专栏地址:????JDBC
Java入门篇: ????Java基础学习篇
Java进阶学习篇(持续更新中):????Java进阶学习篇

JavaWeb | 揭开SQL注入问题的神秘面纱

一、前言

本文主要是讲解JDBC中的SQL注入问题,也会有模拟注入的实例。同时也会介绍如何使用PreparedStatement来解决这个问题,以此来保证数据库安全性。

本文中所有的资料来源是黑马程序员,大家可以在他们的官方小程序获取资源,本文主要是以个人理解来讲述这个知识点

二、模拟SQL注入

1.修改application.properties文件

在下载完相关资料以后,首先找到 day03-JDBC\资料\2. sql注入演示 中的application.properties 文件,然后修改 其中的用户名和密码(自己数据库的用户名和设置的密码)

2.创建数据库

由于资料包中是新建一个在 test 数据库下的 user 表,所以导入表之前需要先新建test数据库。可以直接创建,也可以在 navicat 中使用下面这条命令来创建

CREATE DATABASE test;

3.运行jar包

这里要特别注意:运行的jar包要和application.properties文件在同一个路径下,如果要移动文件的话一定要将这三个文件一起移动,这样才能保证jar包正常运行
JavaWeb | 揭开SQL注入问题的神秘面纱

我妈打开PowerShell,可以直接在左下角搜索,为了防止权限不够等问题,所以我点击了“以管理员身份运行”,进入到页面后 要进入jar包所存放的路径(可以用:cd 路径的方法来进入子目录)

JavaWeb | 揭开SQL注入问题的神秘面纱
如果能够运行成功的话应该是下面这个页面,是一个简单的spring项目,为了验证是否成功可以在网页上登录网址或者重启navicattest数据库中是否有表格来验证(见下文讲解)
JavaWeb | 揭开SQL注入问题的神秘面纱

4.验证环境

1️⃣浏览器

首先打开一个浏览器,在网址栏输入localhost:8080/login.html后看是否有跳转网页,如果打开是一片空白或者报错,那就是搭建环境失败;下图是正确的式样

程序来源:黑马程序员

JavaWeb | 揭开SQL注入问题的神秘面纱

2️⃣数据库

如果直接刷新的话是没有用的(至少作者本人刷新没有用。。。)所以我们需要重启这个软件,可以关闭navicat再打开,然后就会发现在test数据库下有两张表格:product user
JavaWeb | 揭开SQL注入问题的神秘面纱

5.模拟注入

在表格中给出了用户名和密码,也就是说只有用到对应的用户名和密码才能登录成功,否则就登陆失败,但是!随便写一个用户名(不在表中的也行)后只要写一串特殊的字符又能够成功登录上去,这就是SQL注入问题
JavaWeb | 揭开SQL注入问题的神秘面纱

我们的密码只要写' or '1' ='1即可登录,下面来验证一下
JavaWeb | 揭开SQL注入问题的神秘面纱
JavaWeb | 揭开SQL注入问题的神秘面纱
成功登录!

6.揭秘注入

由于我们要判断用户是否输入了正确的用户名和密码,所以我们要从网页上获取用户输入的用户名和密码,再去数据库中查找用户输入的name和pwd,并判断是否在数据库中,所以部分代码如下

由于目前没学到如何从网页捕获用户输入内容,所以代码中就直接定义变量名并赋值来充当接收的数据


	//获取连接
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "123456";
    Connection c = DriverManager.getConnection(url, username, password);

    // 接收用户输入 用户名和密码
    String name = "fyfgvul8gyu218pyug";
    String pwd = "' or '1' = '1";
    String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";
    
    // 获取stmt对象
    Statement stmt = c.createStatement();
    
    // 执行sql
    ResultSet result = stmt.executeQuery(sql);
    
    // 判断登录是否成功
    if(rs.next()){
        System.out.println("登录成功~");
    }else{
        System.out.println("登录失败~");
    }

这里的查询语句是

select * from tb_user where username = '"+name+"' and password = '"+pwd+"';

所以当我们把用户名和密码填进去就变成了

select * from tb_user where username = 'fyfgvul8gyu218pyug' and password = '' or '1' = '1';

这里我们解读一下:password = ''显然不对,也就是0,'1' = '1'恒成立,也就是1,0 or 1是或运算,当所有为0时,结果才为0;所以有一个恒成立的条件的话,结果永远为1,即密码是正确的,能够登陆进去

三、结语

知道了SQL注入的原理,接下来将讲述一种可以防止注入的一种方法:预编译,也就是 PreparedStatement 对象