MySQL 基础13 JBDC数据库注入漏洞问题以及解决方法

1.1注入漏洞

  在早期互联网上SQL注入漏洞普遍存在。有一个网站,用户需要进行注册,用户注册以后根据用户名和密码完成登录。假设现在用户名已经被其他人知道了,但是其他人不知道你的密码,也可以登录到网站上进行相应的操作。

1.2 漏洞代码

1.2.1 编写用户登录

public boolean login(String username,String password){
        
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        // 定义一个变量:
        boolean flag = false;
        try{
            // 获得连接:
            conn = JDBCUtils.getConnection();
            // 完成登录功能:
            // 创建执行SQL语句的对象:
            stmt = conn.createStatement();
            // 编写SQL语句:
            String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
            // 执行SQL:
            rs = stmt.executeQuery(sql);
            if(rs.next()){
                // 说明根据用户名和密码可以查询到这条记录
                flag = true;
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            JDBCUtils.release(rs, stmt, conn);
        }
        return flag;
    }

1.2.2 演示SQL注入漏洞

  • 输入用户名
    • aa’ or ‘1=1 密码随意
    • aaa’ -- +空格 密码随意
/**
 * SQL注入的漏洞
 * @author jt
 *
 */
public class JDBCDemo4 {

    @Test
    /**
     * SQL注入漏洞的演示
     */
    public void demo1(){
        UserDao userDao = new UserDao();
//      boolean flag = userDao.login("aaa", "123");
//      boolean flag = userDao.login("aaa' or '1=1", "asdfjklsd");
        boolean flag = userDao.login("aaa' -- ", "qweqwersdfsd");
        if(flag){
            System.out.println("登录成功!");
        }else{
            System.out.println("登录失败!");
        }
    }
}

1.3 漏洞解决

1.3.1 原理分析

// 编写SQL语句:
String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
  • 输入的用户名
    • aa' or '1=1 密码随意
    • aaa' -- 密码随意
  • 原因
    • 在变量中存在SQL的关键字
      • or
      • -- :表示后面语句都是注释
    • 这些都是SQL中的关键字
select * from user where username = 'aa' or '1=1' and password = '22d' 
select * from user where username = 'aa' -- and password = '22d' 

1.3.2 注入漏洞解决

  需要采用PreparedStatement对象解决SQL注入漏洞。这个对象将SQL预先进行编译,使用?作为占位符。?所代表内容是SQL所固定。再次传入变量(包含SQL的关键字)。这个时候也不会识别这些关键字。

public class UserDao {
    
    public boolean login(String username,String password){
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        // 定义一个变量:
        boolean flag = false;
        try{
            // 获得连接:
            conn = JDBCUtils.getConnection();
            // 编写SQL语句:
            String sql = "select * from user where username = ? and password = ?";
            // 预编译SQL
            pstmt = conn.prepareStatement(sql);
            // 设置参数:
            pstmt.setString(1, username);
            pstmt.setString(2, password);
            // 执行SQL语句:
            rs = pstmt.executeQuery();
            if(rs.next()){
                // 说明根据用户名和密码可以查询到这条记录
                flag = true;
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            JDBCUtils.release(rs, pstmt, conn);
        }
        return flag;
    }

你可能感兴趣的:(MySQL 基础13 JBDC数据库注入漏洞问题以及解决方法)