首頁 > 軟體

簡單聊一聊SQL隱碼攻擊及防止SQL隱碼攻擊

2022-03-23 13:03:18

SQL隱碼攻擊

SQL隱碼攻擊是通過操作輸入來修改事先定義好的SQL語句,對使用者輸入的字串進行過濾,跳脫,限制或處理不嚴謹,導致使用者可以通過輸入精心構造的字串去非法獲取到資料庫中的資料,以達到執行程式碼對伺服器進行攻擊的方法。

現有一個資料庫test中的表user,可以通過賬號name,密碼pass登入,檢視id

登入程式碼

package JDBCtest;

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

/*
 * 使用者登入
 */
public class Demo4 {

    public static void main(String[] args) throws Exception {
        // 1.載入驅動
        Class.forName("com.mysql.jdbc.Driver");
        // 2.建立連線
        String url = "jdbc:mysql:///test";
        String username = "root";
        String password = "1234";
        Connection connection = DriverManager.getConnection(url, username, password);
        // 接收使用者名稱密碼
        Scanner sc = new Scanner(System.in);
        String name = sc.next();
        String pass = sc.next();// 3.sql語句
        String sql = "Select * from user where name='" + name + "' and pass ='" + pass + "'";
        // System.out.println(sql);
        // 4.獲取sql物件statement
        Statement statement = connection.createStatement();
        // 5.執行sql語句
        ResultSet rs = statement.executeQuery(sql);
                // 6.登入
        if (rs.next()) {
            System.out.println("登入成功");
        } else {
            System.out.println("登入失敗");
        }
        // 7.釋放資源
        statement.close();
        connection.close();
    }
}

通過表中賬號密碼登入成功

由於賬號或密碼錯誤登入失敗

以上可以正確登入成功或失敗

注意!

如果此時我這樣輸入 【lihua 'or'1'='1】,也成功登入了,但是資料庫沒根本沒有這條資料

這是為什麼呢?讓我們從程式碼裡找問題!

        String sql = "Select * from user where name='" + name + "' and pass ='" + pass + "'";

為了呼叫資料庫,使用字串拼接SQL語句

讓我們列印一下輸入 【lihua 'or'1'='1】的sql語句一探究竟

select語句中的where條件可以看做兩組並列(注意and在前先執行,or後執行)

由於'1'='1'為TRUE,所以以上語句等價於肯定會登入成功!

同理輸入【'or'1'='1'# xxx】也能登陸成功

這是由於#在SQL中是註釋符號,以上語句等價於,於是就和上述情況一樣了。

附防止sql注入的一些建議

1. 程式碼層防止sql注入攻擊的最佳方案就是sql預編譯

public List<Course> orderList(String studentId){
    String sql = "select id,course_id,student_id,status from course where student_id = ?";
    return jdbcTemplate.query(sql,new Object[]{studentId},new BeanPropertyRowMapper(Course.class));
}

這樣我們傳進來的引數 4 or 1 = 1就會被當作是一個student_id,所以就不會出現sql注入了。

2. 確認每種資料的型別,比如是數位,資料庫則必須使用int型別來儲存

3. 規定資料長度,能在一定程度上防止sql注入

4. 嚴格限制資料庫許可權,能最大程度減少sql注入的危害

5. 避免直接響應一些sql異常資訊,sql發生異常後,自定義異常進行響應

6. 過濾引數中含有的一些資料庫關鍵詞

@Component
public class SqlInjectionFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req=(HttpServletRequest)servletRequest;
        HttpServletRequest res=(HttpServletRequest)servletResponse;
        //獲得所有請求引數名
        Enumeration params = req.getParameterNames();
        String sql = "";
        while (params.hasMoreElements()) {
            // 得到引數名
            String name = params.nextElement().toString();
            // 得到引數對應值
            String[] value = req.getParameterValues(name);
            for (int i = 0; i < value.length; i++) {
                sql = sql + value[i];
            }
        }
        if (sqlValidate(sql)) {
            throw new IOException("您傳送請求中的引數中含有非法字元");
        } else {
            chain.doFilter(servletRequest,servletResponse);
        }
    }

    /**
     * 關鍵詞校驗
     * @param str
     * @return
     */
    protected static boolean sqlValidate(String str) {
        // 統一轉為小寫
        str = str.toLowerCase();
        // 過濾掉的sql關鍵字,可以手動新增
        String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|" +
                "char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
                "table|from|grant|use|group_concat|column_name|" +
                "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
                "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";
        String[] badStrs = badStr.split("\|");
        for (int i = 0; i < badStrs.length; i++) {
            if (str.indexOf(badStrs[i]) >= 0) {
                return true;
            }
        }
        return false;
    }
}

總結

到此這篇關於SQL隱碼攻擊及防止SQL隱碼攻擊的文章就介紹到這了,更多相關防止SQL隱碼攻擊內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com