1. 程式人生 > >MYSQL—— SQL 注入式錯誤

MYSQL—— SQL 注入式錯誤

sql注入式錯誤(SQL injection)

SQL Injection 就是利用某些資料庫的外部介面將使用者資料插入到實際的資料庫操作語言(SQL)當中,從而達到入侵資料庫乃至作業系統的目的。它的產生主要是由於程式對使用者輸入的資料沒有進行嚴格的過濾,導致非法資料庫查詢語句的執行。
《深入淺出 MySQL》

危害
攻擊者利用它來讀取、修改或者刪除資料庫內的資料,獲得資料庫中使用者資料和密碼等資訊,更嚴重的就是獲得管理員的許可權。

例子

 //注入式錯誤
    public static void test3(String name,String passward){
        Connection connection = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            // 載入JDBC 驅動
            Class.forName("com.mysql.jdbc.Driver");
            // 獲得JDBC 連線
            String url = "jdbc:mysql://localhost:3306/tulun";
            connection = DriverManager.getConnection(url,"root","123456");
            //建立一個查詢語句
            st = connection.createStatement();
            //sql語句
            String sql = "select * from student where name = '"+ name+"' and passward = '"+passward+"'";
            rs = st.executeQuery(sql);

            if(rs.next()){
                System.out.println("登入成功。");
            }else{
                System.out.println("登入失敗。");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
       
        test3("wjm3' or '1 = 1","151515");

    }

資料庫資訊
在這裡插入圖片描述
如上面的程式碼所示,使用者名稱為wjm3’ or '1 = 1,密碼為151515,從資料庫中可以看出我們沒有這樣的使用者,本來應該顯示登入失敗,但是結果卻是登陸成功,因為or '1 = 1 已經不是使用者名稱裡面的內容了,它現在為SQL 語句裡面的內容,不論如何,結果都為true,等於不用輸密碼都可以登入。這裡就產生了安全問題。

解決方法

1. PrepareStatement

 //注入式錯誤
    public static void test3(String name,String passward){
        Connection connection = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            // 載入JDBC 驅動
            Class.forName("com.mysql.jdbc.Driver");
            // 獲得JDBC 連線
            String url = "jdbc:mysql://localhost:3306/tulun";
            connection = DriverManager.getConnection(url,"root","123456");
            //建立一個查詢語句
            String sql1 =  "select * from student where name = ? and passward = ?";
            st = connection.prepareStatement(sql1);
           st.setString(1,name);
           st.setString(2,passward);
            //sql語句
            //String sql = "select * from student where name = '"+ name+"' and passward = '"+passward+"'";
            rs = st.executeQuery();

            if(rs.next()){
                System.out.println("登入成功。");
            }else{
                System.out.println("登入失敗。");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                connection.close();
                st.close();
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
     public static void main(String[] args) {
        test3("wjm3' or '1 = 1","151515");
    }

上面這個程式碼不管name 引數是什麼,它都只是name 引數,不會作為sql語句的一部分來執行,一般來說推薦這個方法,比較安全。
2.自己定義函式進行校驗

  • 整理資料使之變得有效
  • 拒絕已知的非法輸入
  • 只接受已知的合法輸入

所以如果想要獲得最好的安全狀態,目前最好的解決辦法就是對使用者提交或者可能改變的資料進行簡單分類,分別應用正則表示式來對使用者提供的輸入資料進行嚴格的檢測和驗證。
其實只需要過濾非法的符號組合就可以阻止已知形式的攻擊,並且如果發現更新的攻擊符號組合,也可以將這些符號組合增添進來,繼續防範新的攻擊。特別是空格符號和其產生相同作用的分隔關鍵字的符號,例如“/**/”,如果能成功過濾這種符號,那麼有很多注入攻擊將不能發生,並且同時也要過濾它們的十六進位制表示“%XX”。