Problema de inyección de SQL: análisis y solución del modelo de inicio de sesión simple

La inyección SQL significa que la aplicación web no juzga la legitimidad de los datos ingresados ​​por el usuario o el filtrado no es estricto. El atacante puede agregar declaraciones SQL adicionales al final de la declaración de consulta predefinida en la aplicación web. Para engañar el servidor de base de datos para realizar consultas arbitrarias no autorizadas, la información de datos correspondiente se puede obtener más.

1. Análisis de problemas: modelo simple

El siguiente es un sistema de inicio de sesión simple que escribí. La forma de conectarse a la base de datos se ha encapsulado en la clase de herramienta JDBCUtils. La instrucción sql se completa ingresando el número de cuenta y la contraseña a través del teclado. Después de ejecutar la instrucción sql de la consulta , se juzga si el conjunto de resultados tiene contenido.

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

public class JdbcDemo3 {
    
    
    public static void main(String[] args) {
    
    
        //键盘录入,接收用户名和密码
        Scanner scanner = new Scanner(System.in);
        String username = scanner.nextLine();
        String password = scanner.nextLine();
        //调用方法
        boolean flag = new JdbcDemo3().login(username,password);
        //判断结果,输出不同语句
        if(flag){
    
    
            System.out.println("登录成功");
        }else {
    
    
            System.out.println("登录失败");
        }
    }

    /**
     * 登录方法
     * @param username
     * @param password
     * @return
     */
    public boolean login(String username,String password){
    
    
        if(username == null || password == null){
    
    
            return false;
        }
        Connection connection = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
    
    
            //连接数据库判断是否登录成功
            connection = JDBCUtils.getConnection();
            //定义sql
            String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
            //打印sql语句
            System.out.println(sql);
            //获取执行sql的对象
            stmt = connection.createStatement();
            //执行查询
            rs = stmt.executeQuery(sql);
            //判断
            return rs.next();

        } catch (SQLException exception) {
    
    
            exception.printStackTrace();
        }finally {
    
    
            JDBCUtils.close(rs,stmt,connection);
        }
        return false;
    }

}

He aquí un experimento:
entrar

yh
a' o 'a'='a

producción

Inicio de sesión correcto

Aquí hay un problema, puede ver la información en nuestra base de datos y no existe tal.
inserte la descripción de la imagen aquí
Aquí imprimimos la instrucción sql
inserte la descripción de la imagen aquíy podemos ver que al empalmar sql, hay algunas palabras clave de sql involucradas en el empalme de cadenas, lo que causará algunos problemas de seguridad . Aquí se usa un o, y el o va seguido de una identidad, lo que hará que la condición where sea verdadera. En comparación con ninguna restricción, el efecto de esta declaración es exactamente el mismo que el de select * from user, y todos los la información en la base de datos será robada maliciosamente.

2. Solución: Use PreparedStatement

La interfaz PreparedStatement en el paquete java.sql hereda de Statement y se diferencia de ella en dos formas: Se ha argumentado que en las aplicaciones JDBC, si ya es un desarrollador un poco avanzado, siempre debe usar PreparedStatement en lugar de Statement. , no use Declaración en ningún momento.
PreparedStatement proporciona un método precompilado para evitar problemas de inyección de SQL causados ​​por el empalme de SQL.

La instrucción sql original ha cambiado. En PreparedStatement, ? se usa como marcador de posición y el valor se pasa a través de setXxx(posición ?, valor ?).

select * from user where username = ? and password = ?
import java.sql.*;
import java.util.Scanner;

public class JdbcDemo3 {
    
    
    public static void main(String[] args) {
    
    
        //键盘录入,接收用户名和密码
        Scanner scanner = new Scanner(System.in);
        String username = scanner.nextLine();
        String password = scanner.nextLine();
        //调用方法
        boolean flag = new JdbcDemo3().login(username,password);
        //判断结果,输出不同语句
        if(flag){
    
    
            System.out.println("登录成功");
        }else {
    
    
            System.out.println("登录失败");
        }
    }

    /**
     * 登录方法
     * @param username
     * @param password
     * @return
     */
    public boolean login(String username,String password){
    
    
        if(username == null || password == null){
    
    
            return false;
        }
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        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();
            //判断
            return rs.next();

        } catch (SQLException exception) {
    
    
            exception.printStackTrace();
        }finally {
    
    
            JDBCUtils.close(rs,pstmt,conn);
        }
        return false;
    }

}

Ejecute la prueba y está bien aquí.
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_50216270/article/details/117216559
Recomendado
Clasificación