MySQL的SQL注入问题

一、老生常谈的SQL注入如何实现

估计大部分都知道方法:任意内容 ’ or 永真语句 注释符,这种方式实现。通过or表示或,与永为真语句搭配保持前面部分永远真,然后用注释符屏蔽掉后面实现条件永为真的操作。

二、为什么通过占位符方式可以避免SQL注入

打Java操作数据库的例子来说。
Java通过PreparedStatement类执行SQL语句时,SQL语句中变量用?来代替,之后对SQL语句进行预编译。PreparedStatement再调用set方式传入下标和变量进行赋值,再执行SQL语句。这期间,SQL预编译后下次传进来的内容,直接针对这些内容操作就好。比如

select * from user where name = ? and pwd=?

这先把sql语句编译,之后执行。就算传入例如:name:abc‘ or 1=1 #,pwd:111,也会把“abc‘ or 1=1 #”单独当做一个name值进行匹配。结果就是匹配不到,防止了SQL注入。

三、MySQL中的注释符(#和–的区别)

MySQL中注释有两种方式:
①#注释内容
②-- 注释内容(注意–后面与注释内容之间要有空格)
下面用四张sql注入试验结果,表名两种注释加与不加空格结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从上面四幅图看出,sql注入时,#后面加与不加空格都成功了。而在使用–时,–后面必须加空格才生效,不加空格个则会被检查出语法错误。

四、附上此文章中用到的代码和数据库表

代码部分可到main函数去放掉对应方法的注释,另外代码开头部分的数据库也要根据个人数据库进行修改,我的数据库是5.5版本的MySQL,url中test是我存放之后数据库表对应的库名,user和password请根据个人连接数据库用到的名字和密码进行修改的。如果是普通Java项目,还需要到网上下载对应的数据库驱动jar包,并应用到当前项目。

package JdbcDemo;

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

public class jdbcdemo {
    static Connection connection;
    static Statement statement;
    static PreparedStatement preparedStatement;
    private static final String driver = "com.mysql.jdbc.Driver";
    private static final String url = "jdbc:mysql://localhost:3306/test";
    private static final String user = "root";
    private static final String password = "318523";
    //数据库操作练习
    public static void OperateDatabase() {
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, user, password);
            if (!connection.isClosed()) {
                System.out.println("Database connection success.");
//                statement=connection.createStatement();
//                String name="xiaojun";
//                int age=40;
//                String sql = "insert into student(name,age) values('"+name+"','"+age+"') ";
//                int count = statement.executeUpdate(sql);


                String sql = "insert into student values(?,?) ";
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setString(1, "xiaohong");
                preparedStatement.setInt(2, 19);
                int count = preparedStatement.executeUpdate();
                if (count > 0) {
                    System.out.println("insert success.");
                }
            } else {
                System.out.println("Database connection failed.");
                return;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (preparedStatement != null) preparedStatement.close();
                if (statement != null) statement.close();
                if (connection != null) connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //sql注入,Statement类执行测试
    public static void SQLInjectStatement() {
        ResultSet resultSet=null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, user, password);
            if (!connection.isClosed()) {
                System.out.println("Database connection success.");
                Statement statement = connection.createStatement();
                String name;
                String pwd;
                Scanner scanner = new Scanner(System.in);
                System.out.println("input name:");
                name = scanner.nextLine();
                System.out.println("input pwd");
                pwd = scanner.nextLine();
                String sql = "select * from user where name ='"+name+"'and pwd ='"+pwd+"'";
                 resultSet = statement.executeQuery(sql);
                if(resultSet.next()){
                    System.out.println("Login successfully!");
                }else {
                    System.out.println("Login failed.");
                }
            } else {
                System.out.println("Database connection failed.");
                return;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if(resultSet!=null) resultSet.close();
                if (statement != null) statement.close();
                if (connection != null) connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //sql注入,PrepareStatement执行测试
    public static void SQLInjectPrepareStatement() {
        ResultSet resultSet=null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, user, password);
            if (!connection.isClosed()) {
                System.out.println("Database connection success.");
                String sql = "select * from user where name =? and pwd =?";
                preparedStatement = connection.prepareStatement(sql);
                String name;
                String pwd;
                Scanner scanner = new Scanner(System.in);
                System.out.println("input name:");
                name = scanner.nextLine();
                System.out.println("input pwd");
                pwd = scanner.nextLine();
                preparedStatement.setString(1,name);
                preparedStatement.setString(2,pwd);
                resultSet = preparedStatement.executeQuery();
                if(resultSet.next()){
                    System.out.println("Login successfully!");
                }else {
                    System.out.println("Login failed.");
                }
            } else {
                System.out.println("Database connection failed.");
                return;
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if(resultSet!=null) resultSet.close();
                if (statement != null) statement.close();
                if (connection != null) connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        //OperateDatabase();
        //SQLInjectStatement();
        SQLInjectPrepareStatement();
        return;
    }
}

用到的数据库表,为了测试比较简单
student表

Field Type Null Key Default Extra
name varchar(10) YES NULL
age tinyint(4) YES NULL

user表

Field Type Null Key Default Extra
name varchar(10) YES NULL
pwd varchar(10) YES NULL

最后,如果对文章有什么疑问或者问题,欢迎留言

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章