SQL注入式攻擊方式及防範措施

SQL注入式攻擊方式及防範措施

轉載於 http://hi.baidu.com/xjzxjym/item/8efed742124798ad60d7b916

謹以此文獻給那些網站受害者。。。。。

下面講講,如何網頁掛馬,假如你的大名和形象照出現在哪個人的網站,進行人身攻擊,下面就用到了。

1. 概述
網頁掛馬這個話題想來大家並不陌生。爲什麼有這麼多的網頁上存在着木馬去攻擊普通用戶?不可否認,相當一部分網頁原本就是惡意的:網頁的作者故意在上面放上 木馬,然後通過各種手段引誘用戶去瀏覽。但是絕大多數被掛馬的網頁原本是正常的網頁,例如普通的教育網站,購物網站等等,只是網頁被攻擊者惡意修改後插入 了木馬代碼。

那麼,攻擊者是如何能夠惡意修改一個正常網頁的呢? 換句話說,一個網站是如何被“黑”的?一個最常見的攻擊方法是SQL注入(SQL Injection)攻擊。事實上,就在今年的五月份,爆發了一次大規模的網頁攻擊活動【1

】。據估計,約有12萬個網頁被惡意修改插入木馬代碼,而攻擊者採用的手段就是SQL注入攻擊。

那麼,什麼是SQL注入攻擊?攻擊者是如何利用SQL注入攻擊篡改網頁的?Web開發人員又應該如何防範SQL攻擊?這就是我們這篇文章要闡述的問題。

2.SQL注入攻擊

我們從一個簡單的例子【2】開始。下面這段代碼用來構造SQL查詢命令。
var strUserAccount;
strUserAccount = Request.form ("UserAccount");
var sqlQueryString = "select * from Orders where UserAccount = '" + strUserAccount + "'";
//執行SQL Query …
這段代碼很簡單:給出UserAccount,查詢其對應的訂單信息。
例如,如果輸入UserAccount值爲100,那麼構造的查詢命令就是:
SELECT * FROM Orders WHERE UserAccount = '100'
從功能上說這段代碼非常正確,完全沒有任何問題。但是開發人員往往忽視安全方面的考慮:如果用戶(攻擊者)提供的輸入數據是惡意的, 程序的表現行爲是什麼?

如果是一個不那麼友好的攻擊者,可能輸入UserAccount值爲100' or 1=1 --,構造的查詢命令就是:

SELECT * FROM Orders WHERE UserAccount = '100' or 1=1 --
執行這個查詢命令,就會返回所有用戶的訂單,導致商業機密信息的泄漏。
如果是一個非常不友好的攻擊者,可能輸入UserAccount值爲100’; drop table orders --,構造的查詢命令就是
SELECT * FROM Orders WHERE UserAccount = '100'; drop table orders --
“;”用來分割SQL語句。“--”表明當前行剩餘的內容是註釋。這段SQL語句的語法是完全正確的,那麼一旦執行,就會先執行正常的查詢工作,然後刪除訂單數據庫。後果非常嚴重吧。但這還不是最糟糕的的情況。
如果是一個非常非常不友好的攻擊者,可能輸入UserAccount值爲100’; exec xp_cmdshell(‘fdisk.exe’) --,構造的查詢命令就是
SELECT * * FROM Orders WHERE UserAccount = '100';
exec xp_cmdshell(‘fdisk.exe’) --
在權限允許的情況下,這段SQL語句的執行後果,就非常非常嚴重了。
通過上面的這個例子可以看出,SQL注入攻擊的定義是:
被攻擊系統採用字符串接收用戶輸入,並構造相應的SQL語句來執行數據庫操作。
開發人員沒有對用戶輸入字符串的合法性做足夠驗證。
攻擊者在該字符串中注入的惡意代碼,在數據庫系統(如SQL Server)上執行。
3.      SQL注入攻擊和網頁掛馬

當WEB應用需要後臺數據庫支持的時候,系統就存在着SQL注入攻擊的風險。
那麼,攻擊者到底是如何利用SQL注入攻擊來達到網站掛馬的目的?我們就拿開始提到的今年五月份的攻擊舉例:
攻擊者通過自動掃描工具,發現存在SQL注入攻擊安全漏洞的網站。
攻擊者實施SQL注入攻擊,將惡意的腳本代碼插入到SQL數據庫的相應數據中。插入的惡意腳本如:<script src=http://惡意網站/攻擊.js>
惡意的腳本文件(js)試圖利用一系列常用軟件的安全漏洞,如微軟IE的安全漏洞,Adobe Flash的安全漏洞,Real Player的安全漏洞,還有許多流行的國內軟件的安全漏洞,如迅雷下載,暴風影音等等。
這樣,一個原本正常的網站就被掛上了惡意代碼。當用戶瀏覽該網站的時候,網頁的動態構造中往往需要從後臺SQL數據庫取出相應數據並插入到構造的網頁中。在這個過程中,惡意的腳本代碼也作爲數據的一部分**入到網頁

中。
如果普通用戶的機器沒有及時安裝廠商提供的安全補丁,或者攻擊者利用的安全漏洞是0-day安全漏洞,沒有任何安全補丁的話,用戶的機器就會被木馬感染。
4.      Web開發人員如何防範SQL注入攻擊
下面是開發過程中,防範SQL注入攻擊的三個建議。
驗證用戶輸入
使用Stored Procedures和相應的參數傳遞。
數據庫訪問帳號的最小化權限(Least-Privilege)
4.1驗證用戶輸入
既然SQL注入攻擊的原理是通過在用戶輸入的字符串中插入惡意代碼,那麼驗證來自用戶的輸入就是防範攻擊的自然方案。不過,在設計驗證代碼時需要注意下面兩點。
4.1.1在服務器端驗證輸入,而不僅僅是在客戶端驗證。
一個常見的設計誤區是檢驗代碼僅僅放在客戶端上。Web開發中往往通過運作在客戶網頁的JavaScript或VBScript檢查用戶的輸入值。如果校驗錯誤的話就直接通知用戶錯誤信息。客戶端校驗通過後纔會向服務器端法出請求。
在客戶端進行校驗並沒有錯。但是,如果由於客戶端提供了校驗,而在服務器一端設計中認爲來自客戶端的輸入是都是經過(客戶端)驗證的,從而可以直接使用的話,就有問題了。
這是因爲,攻擊者可以完全不需要客戶端程序,而直接向服務器端發出數據提交請求。這種情況下,所有客戶端的檢查都可以被繞過。所以在服務器端的設計過程中,要總是假設來自用戶的輸入可以是惡意的,並提供相應的

驗證措施。
4.1.2驗證輸入的原則是確認輸入的值都是有效字符,而不是試圖拒絕輸入的值中的無效字符。
初看起來,確認輸入的值都是有效字符,和拒絕輸入的值中的無效字符,這兩個方案的是一回事。但是它們其實在實現上,以及對安全的影響上,有着很大的區別。
下面來舉個例子說明。假設需要驗證來自用戶的UserAccount值是否合法,這裏我們可以有兩個選擇。
選擇一,確認UserAccount中的每個字符都是字母和數字。這種設計稱爲“whitelist”,也就是白名單設計。只有滿足白名單條件的值纔是合法的。我們可以採用正則表達式RegEx來驗證。
using System;
using System.Text.RegularExpressions;
//驗證UserAccount是否合法
public bool IsUserAccountValid(string strUserAccount)
{
// 驗證是否字符僅僅是有大小寫字母及數字構成
// 字符長度在1-20
if ( !Regex.IsMatch(userIDTxt.Text, @"^[a-zA-Z0-9]{1,40}$"))
{
return false;
}else {
return true;
}
}

選擇二,確認UserAccount中沒有非法字符。這種設計稱爲“blacklist”,也就是黑名單設計。不在黑名單上的值都是合法的。黑名單設計的問題是:我們需要拒絕那些危險字符?例如,SQL語法中有下面這些字符需要特殊注

意【3】:
特殊字符
SQL語句中的含義
;
查詢分隔符
'
數據分隔符.
--
註釋分隔符.
/* ... */
註釋分隔符.
xp_
指示擴展的stored procedures,例如 xp_cmdshell.
是不是隻要檢查用戶輸入中沒有這些特殊字符就可以了?很可惜,並不是這麼簡單。首先,系統設計和實現的不同往往會導致某一種危險的輸入值在黑名單上被遺漏。而且,攻擊者往往可以通過“改頭換面”的辦法來繞過黑

名單。常見的手段是有采用另一種編碼方式,如採用%0x來編碼等等。
所以在驗證用戶輸入的開發過程中,強烈推薦採用白名單的設計方式來確認用戶的輸入是否是有效的。事實上,設計上採用白名單方式來驗證用戶的輸入,不僅適用於防範SQL注入攻擊,也是安全軟件開發中用以防範其它攻擊

的有效手段。
4.2使用Stored Procedures和相應的參數傳遞
首先,並不是採用Stored Procedure和傳遞參數就能完全防止SQL注入攻擊。例如,如果Stored Procedure設計成:
CREATE PROCEDURE dbo.RunQuery
@var ntext
AS
exec sp_executesql @var
GO
這個Stored Procedure在防範SQL注入攻擊上完全沒有任何作用。然而,合理的設計和使用Stored Procedure及參數類對阻止SQL注入攻擊攻擊是非常有效的。下面這段代碼的功能同樣是需要基於UserAccount來查詢訂單信息,

但使用SqlParameterCollection來將UserAccount的值作爲參數傳遞。
using System.Data;
using System.Data.SqlClient;
public void QueryOrder(string strUserAccount)
{
… …

SqlConnection connection = new SqlConnection(connectionString);

DataSet userDataset = new DataSet();

SqlDataAdapter myCommand = new SqlDataAdapter(
"QueryOrderStoredProcedure", connection);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
myCommand.SelectCommand.Parameters.Add("@UserAccount", SqlDbType.VarChar, 20);
myCommand.SelectCommand.Parameters["@UserAccount"].Value = strUserAccount;
myCommand.Fill(userDataset);
}
這裏,UserAccount的值是作爲字符串參數傳遞給對應的QueryOrderStoredProcedure,而不是簡單的插入到構造的SQL查詢語句中。參數在傳遞過程中會被檢查類型和長度。如果檢驗失敗的話,SqlParameter類會報告異常,從

而有效的防範SQL注入攻擊。
4.3數據庫訪問帳號的最小化權限
最小化權限的設計,同白名單一樣,也是安全軟件開發中的常用的設計原則。應用到SQL注入攻擊環境下,意味着:應用程序用來訪問數據庫的帳號,所擁有的權限應該最小化。
需要強調的一點是,SQL注入攻擊的根源在於Web開發中的不正確的代碼。最小化權限的設計並不能替代修復代碼本身錯誤的工作。它只是作爲深層防禦(Defense In Depth)中的緩解手段,其目的是爲了儘可能降低SQL注入攻

擊的危害性。
例如,如果是通過Windows authentication機制來連接並訪問數據庫的話,用來訪問數據庫的Windows的帳號的權限就應該受到限制。一個非管理員權限的帳號,就可以阻止執行Fdisk類似級別的操作。在【4】給出了一個在

Microsoft Windows 2003服務器,ASP.NET應用,後臺SQLServer情況下,如何最小化ASP.NET應用 運行的Network Service帳號的權限的例子。有興趣的讀者可以參考【4】獲取更詳細的信息。
5.      總結
SQL注入攻擊是最爲常見的網站攻擊的手段之一。開發人員在Web應用的設計和實現過程中需要意識到SQL注入攻擊的危險,並在代碼中採用相應的防範措施。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章