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

最後,如果對文章有什麼疑問或者問題,歡迎留言

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