SpringMVC利用攔截器防止SQL注入

引言

隨着互聯網的發展,人們在享受互聯網帶來的便捷的服務的時候,也面臨着個人的隱私泄漏的問題。小到一個擁有用戶系統的小型論壇,大到各個大型的銀行機構,互聯網安全問題都顯得格外重要。而這些網站的背後,則是支撐整個服務的核心數據庫。可以說數據庫就是這些服務的命脈,沒有數據庫,也就無從談起這些服務了。
對於數據庫系統的安全特性,主要包括數據獨立性、數據安全性、數據完整性、併發控制、故障恢復等方面。而這些裏面顯得比較重要的一個方面是數據的安全性。由於開發人員的設計不周到,以及數據庫的某些缺陷,很容易讓黑客發現系統的漏洞,從而造成巨大的損失。
接下來本文將會介紹非常常見的一種攻擊數據庫的方法:SQL注入,以及使用在項目使用Java開發的情況下如何使用SpringMVC的攔截器實現防止SQL注入的功能。

SQL注入SQL注入簡介

通俗的講,SQL注入就是惡意黑客或者競爭對手利用現有的B/S或者C/S架構的系統,將惡意的SQL語句通過表單等傳遞給後臺SQL數據庫引擎執行。比如,一個黑客可以利用網站的漏洞,使用SQL注入的方式取得一個公司網站後臺的所有數據。試想一下,如果開發人員不對用戶傳遞過來的輸入進行過濾處理,那麼遇到惡意用戶的時候,並且系統被發現有漏洞的時候,後果將是令人難以想象的。最糟糕的是攻擊者拿到了數據庫服務器最高級的權限,可以對整個數據庫服務器的數據做任何操作。
通常情況下,SQL注入攻擊一般分爲以下幾個步驟:

  • 判斷WEB環境是否可以注入SQL。對於一個傳統的WEB網頁來說,如果是一個簡單的靜態頁面,比如地址爲http://www.news.com/100.html的網頁,這是一個簡單的靜態頁面,一般不涉及對數據庫的查詢。而如果這個網頁的網址變成了:http://www.news.com/news.asp?id=100 那麼,這就是一個根據主鍵id來查詢數據的動態網頁了。攻擊者往往能夠在 id=100的後面加上一些自己的SQL,用來“欺騙”過應用程序。
  • 尋找SQL注入點。當攻擊者確定某個頁面可以使用SQL注入之後,他一般會尋找可以SQL注入的點。而這些點往往就是網頁或者應用程序中的用於向服務器發送用戶數據的表單了。一般的流程是,客戶端通過這些表單發送一些用戶信息的字段,比如用戶名和密碼,接着服務器就會根據這些字段去查詢數據庫。而如果用戶輸入了一些非法的字符,比如’這個符號,那麼在SQL解析的時候,解析的結果可能並不是應用開發人員想象中那樣。
  • 尋找系統的後臺。這一點就建立在破壞者對整個系統的瞭解程度上面了,如果攻擊者對整個系統瞭如指掌,那麼實現攻擊也就是一件很簡單的事情了。
  • 入侵和破壞。當攻擊者攻破系統之後,整個系統從某種意義上來講已經失去意義了。
SQL注入案例一個簡單的PHP登錄驗證SQL注入

比如一個公司有一個用來管理客戶的客戶管理系統,在進入後臺進行管理的時候需要輸入用戶名和密碼。
假設在客戶端傳給服務器的字段分別爲用戶名username和密碼password,那麼如果用來處理登錄的服務器端代碼對用戶的輸入做以下處理:
PHPsql注入
上面的PHP代碼就是首先獲取客戶端POST過來的填寫在表單裏面的用戶名和密碼,接着要MySQL去執行下面這條SQL語句:

SELECT `id` FROM `users` WHERE `username` = username AND `password` = password;

可以看到上面的代碼沒有對用戶的輸入做任何的過濾,這是非常容易遭到黑客攻擊的。
比如,一個用戶在輸入用戶名的輸入框裏面輸入了

user’;SHOW TABLES;--

那麼就會解析爲下面的SQL:

SELECT `id` FROM `users` WHERE `username` = user’;SHOW TABLES;-- AND `password` = password;

可以看到被解析的SQL被拆分爲了2條有用的SQL:

(1)SELECT `id` FROM `users` WHERE `username` = user’;
(2)SHOW TABLES;

而後面驗證密碼的部分就被註釋掉了。這樣攻擊者就輕鬆的獲得了這個數據庫裏面的所有表的名字。同樣的道理,如果攻擊者在輸入框裏面輸入:

’;DROP TABLE [table_name];--

那麼,這一張表就被刪除了,可見後果是非常嚴重的。
而用戶如果在用戶名輸入框裏面輸入了:user’or 1=1--
那麼會被解析成:

SELECT `id` FROM `users` WHERE `username` = user
or 1=1-- AND `password` = password;

這裏可以看到1=1永遠爲真,這樣不用輸入用戶名就直接可以登入系統了。

一個ASP新聞動態頁面的id查詢

比如有一個新聞網站的動態頁面是這種格式:

http://www.news.com/news.asp?id=100

那麼當用戶在瀏覽器的地址框裏面輸入

http://www.news.com/news.asp?id=100;and user>0

那麼如果這個網站的數據庫用的是SQL Server的話,那麼SQL Server在解析的時候,由於user是SQL Server的一個內置變量,它的值就是當前連接數據庫的用戶,那麼SQL在執行到這裏的時候會拿一個類型爲nvarchar的和一個int類型的比較。比較過程中就必然涉及類型的轉化,然而不幸的是,轉化過程並不是一帆風順,出錯的時候SQL Server將會給出類似將nvarchar值”aaa”轉爲爲int的列時發生語法錯誤。這個時候攻擊者就輕鬆的獲得了數據庫的用戶名。

SpringMVC攔截器防止SQL注入

爲了有效的減少以及防止SQL注入的攻擊,開發人員在開發的時候一定不要期待用戶的輸入都是合理的,當用戶輸入完畢之後,應該嚴謹的對用戶提交的數據進行格式上的檢查以及過濾,儘可能的減少被注入SQL 的風險。
一般來說,不同的服務器端語言都有不同的解決方案。比如拿中小型企業採用得最多的PHP語言來說,PHP的官方就爲開發者提供了這樣的一些函數,比如mysql_real_escape_string()等。
接下來會詳細介紹如何通過SpringMVC的攔截器實現防止SQL注入的功能。
這裏以我的大數據人才簡歷庫的攔截器爲例。

自定義攔截器類實現HandlerInterceptor接口
package com.data.job.util.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;

/**
 * 防止SQL注入的攔截器
 *
 * @author [email protected]
 * @time 2/13/16 8:22 PM.
 */
public class SqlInjectInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        Enumeration<String> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String[] values = request.getParameterValues(name);
            for (String value : values) {
                value = clearXss(value);
            }
        }
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception {

    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {

    }

    /**
     * 處理字符轉義
     *
     * @param value
     * @return
     */
    private String clearXss(String value) {
        if (value == null || "".equals(value)) {
            return value;
        }
        value = value.replaceAll("<", "<").replaceAll(">", ">");
        value = value.replaceAll("\\(", "(").replace("\\)", ")");
        value = value.replaceAll("'", "'");
        value = value.replaceAll("eval\\((.*)\\)", "");
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']",
                "\"\"");
        value = value.replace("script", "");
        return value;
    }
}
配置攔截器
<!-- 攔截器配置-->
    <mvc:interceptors>
<!-- SQL注入攔截-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.data.job.util.interceptor.SqlInjectInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
SQL注入總結

安全問題從古至今都有着非常高的關注度,如今互聯網高速發達,各種網絡應用層出不窮。不管是現在炙手可熱的雲計算和大數據,還是傳統的B/S或者C/S架構的網絡應用,數據的安全性是至關重要的。從應用層面來講,網絡應用的開發者可以通過完善軟件的架構,儘量減少因爲BUG而導致的數據泄漏的問題。開發者可以不斷的審視與完善自己的系統,站在攻擊者的角度上去開發某些關鍵的安全性要求比較高的環節,如銀行支付部分等,這樣能夠在一定程度上面減少SQL注入等應用層面攻擊數據庫的風險。


鏈接:http://www.imooc.com/article/6137

來源:慕課網

本文我寫這裏一方面便於收藏,另方面收藏各位大神意見

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