| 本單元內容 | |
| 目標 | |
| 適用於 | |
| 如何使用本單元 | |
| FxCop | |
| 執行文字搜尋 | |
| 跨網站指令碼 (XSS) | |
| SQL 注入 | |
| 緩衝區溢位 | |
| Managed 程式碼 | |
| 程式碼存取安全性 | |
| Unmanaged 程式碼 | |
| ASP.NET 網頁及控制項 | |
| Web 服務 | |
| 服務元件 | |
| 遠端服務 | |
| 資料存取程式碼 | |
| 總結 | |
| 其他資源 |
安全性程式碼的檢閱重點在於識別可能造成安全性問題與事件的程式設計技巧和弱點。即使需要很多時間,但是程式碼的檢閱卻是專案開發週期中必須定期採取的步驟,因為在開發的期間修正安全性瑕疵所需的成本和人力,比以後在專案開發或維護的期間再修正要少很多。
本單元將協助您檢閱利用 Microsoft .NET Framework 建置的 Managed ASP.NET Web 應用程式碼。本單元的組織是以功能區域劃分,其中各節包含廣泛的問題清單,來提供您程式碼的檢閱程序之方法和架構。
透過本單元即可:
| • | 針對執行程式碼的檢閱以及 ASP.NET 安全性稽核,建立一套方法和架構。 |
| • | 在程式碼中找出跨網站指令碼的弱點。 |
| • | 在程式碼中找出 SQL 注入攻擊的弱點。 |
| • | 在程式碼中找出潛在緩衝區溢位的弱點。 |
| • | 透過一系列廣泛的安全性問答,快速找出安全性的漏洞。 |
| • | 評估特定 .NET Framework 技術的安全性問題。 |
| • | 識別出讓惡意的使用者能發動攻擊的不良程式設計技巧。 |
| • | 瞭解如何使用 FxCop、文字搜尋,以及 ILDASM,來分析原始程式碼和可用的 .NET 組件。 |
本單元適用於下列產品及技術:
| • | Microsoft Windows Server 2000 及 2003 |
| • | Microsoft .NET Framework 1.1 及 ASP.NET 1.1 |
| • | Microsoft SQL Server 2000 |
使用本單元來建立或擴充現有程式碼的檢閱程序。您必須確保程式碼的檢閱為開發週期整體的一部份,並瞭解其效率只能與所配置資源和預算的數量成比例。
檢閱的目標是要在部署程式碼之前,盡可能識別出所有潛在的安全性弱點,因為在開發的期間修正安全性瑕疵所需的成本和人力,比以後在產品開發週期再修正要少很多。
若要充分瞭解本單元:
| • | 請使用本單元 Part III 中同系列的安全保護單元。參考這些單元即可獲得其他關於本單元所略述之檢閱問題的詳細資訊。
| ||||||||||||||||||
| • | 使用同系列的檢查清單:
|
透過 FxCop 分析工具來執行已編譯的組件,是啟動檢閱程序的理想方式。該工具能分析二進位的組件 (並非原始程式碼),來確保它們符合 .NET Framework 設計指南,它可以從 MSDN 取得。它還會檢查組件是否擁有增強名稱,這些名稱能夠防止竄改以及提供其他的安全性優勢。該工具原本就有一組預先定義好的規則,但是您可以自訂和延伸它們。
有關其他詳細資訊,請參閱下列資源:
| • | 若要下載 FxCop 工具,請參閱 http://www.gotdotnet.com/team/libraries/default.aspx。 |
| • | 若要取得該工具的輔助與支援,請參閱 http://www.gotdotnet.com/community/messageboard/MessageBoard.aspx?ID=234。 |
| • | 如需 FxCop 所檢查之安全性規則的清單,請參閱 http://www.gotdotnet.com/team/libraries/FxCopRules/SecurityRules.aspx。 |
| • | 如需 .NET Framework 設計指南,請參閱 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconnetframeworkdesignguidelines.asp。 |
為了使檢閱的程序更有效率,請熟悉可用來在檔案中找出字串的文字搜尋工具。此類型的工具可以讓您快速找出有弱點的程式碼。本單元後面所提出的許多檢閱問題都表示在尋找特定的弱點時,要搜尋的最佳字串。
您可能已擁有偏好的搜尋工具。如果沒有的話,您可以使用 Visual Studio .NET 中的檔案中尋找功能,或是 Findstr 命令列工具,它包含在 Microsoft Windows 作業系統中。
注意 如果在 Windows Explorer 使用 Windows XP 的 [搜尋] 工具,並使用 [在檔案中的單字或片語] 選項,請檢查是否安裝了最新的 Windows XP Service Pack,不然搜尋的工作就會失敗。如需詳細資訊,請參閱 Microsoft 知識庫文件 309173《Using the "A Word or Phrase in the File" Search Criterion May Not Work (英文)》。
在對原始程式碼執行詳細的逐列分析之前,請對整個程式碼基礎進行快速的搜尋,來識別固定寫在程式碼中的密碼、帳戶名稱,以及資料庫連線字串。掃描程式碼,並搜尋常見的字串模式,例如下列:key、secret、password、pwd,以及 connectionstring。
例如,若要在應用程式的 Web 目錄中搜尋「password」字串,請在命令提示號下使用 Findstr 工具,如下所示:
findstr /S /M /I /d:c:\projects\yourweb "password" *.*
Findstr 使用下列命命列參數:
| • | /S 包含子目錄。 |
| • | /M 僅列出檔案名稱。 |
| • | /I 使用不區分大小寫的搜尋。 |
| • | /D:dir 搜尋用分號分隔的目錄清單。如果您想要搜尋的檔案路徑包含空白,請將路徑包括在雙引號內。 |
您可以用常見的搜尋字串來建立文字檔案。Findstr 然後就可以從文字檔案中讀取欲搜尋的字串,如下所示。在包含 .aspx 檔案的目錄中執行下列命令。
findstr /N /G:SearchStrings.txt *.aspx
/N 當找到符合處時,會印出對應的行號。/G 顯示包含搜尋字串的檔案。在本範例中,對所有 ASP.NET 網頁 (*.aspx) 都會進行搜尋包含在 SearchStrings.txt 內的字串。
您還可以使用 Findstr 命令連同 ildasm.exe 公用程式,來針對二進位的組件搜尋固定寫在程式碼中的字串。下列命令使用 ildasm.exe 來搜尋 ldstr 中間語言敘述,而它能夠識別字串常數。請注意下面所示的輸出是如何暴露固定寫在程式碼中的資料庫連線,以及眾所皆知的 sa 帳戶的密碼。
Ildasm.exe secureapp.dll /text | findstr ldstr IL_000c: ldstr "RegisterUser" IL_0027: ldstr "@userName" IL_0046: ldstr "@passwordHash" IL_0065: ldstr "@salt" IL_008b: ldstr "Exception adding account. " IL_000e: ldstr "LookupUser" IL_0027: ldstr "@userName" IL_007d: ldstr "SHA1" IL_0097: ldstr "Exeception verifying password. " IL_0009: ldstr "SHA1" IL_003e: ldstr "Logon successful: User is authenticated" IL_0050: ldstr "Invalid username or password" IL_0001: ldstr "Server=AppServer;database=users; username='sa' password=password"
注意 Ildasm.exe 位於 \Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin 資料夾中。如需所支援之命令列引數的詳細資訊,請執行 ildasm.exe /?。
當程式碼在傳回用戶端的輸出 HTML 串流中使用輸入參數時,它就容易遭受跨網站指令碼 (Cross-Site Scripting,XSS,也稱為 CSS) 的攻擊。進行程式碼的檢閱之前,您可以先執行一項簡單的測試,來檢查應用程式是否易遭 XSS 的攻擊。搜尋會將使用者輸入資訊傳回瀏覽器的網頁。
XSS 漏洞是由於對使用者輸入的資料付予太高信任度而造成的。例如,應用程式可能希望使用者輸入價格,但是攻擊者卻包括了價格以及一些 HTML 和 JavaScript。因此,您一定要確定來自不可信任之來源的資料會經過驗證。在檢閱程式碼時,一定要問:「此資料是否已驗證過?」在 ASP.NET 應用程式中保存一份所有進入點的清單,例如,HTTP 標頭、查詢字串、表單資料等等,並確定所有輸入已在某個點上檢查其正確性。請勿測試是否有不正確的輸入值,因為該方法係假設您已知道所有潛在的危險輸入。在 ASP.NET 應用程式中,檢查該項資料是否正確的最常用方法,是使用規則運算式。
您可以在表單欄位中鍵入如「XYZ」的文字並測試其輸出,來執行簡單的測試。如果瀏覽器顯示了「XYZ」,或者如果在檢視 HTML 的原始程式碼時看到了「XYZ」,那麼 Web 應用程式就容易遭受 XSS 的攻擊。如果想要看到更動態的資訊,請注入 <script>alert('hello');</script>。此種技巧可能無法在所有情況下都正常運作,因為它決定於如何使用輸入來產生輸出。
下列程序能協助您識別常見的 XSS 弱點:
| • | 識別會將輸入輸出的程式碼。 |
| • | 識別有潛在危險的 HTML 標籤和屬性。 |
| • | 識別會處理 URL 的程式碼。 |
| • | 檢查輸出是否有編碼。 |
| • | 檢查是否執行正確的字元編碼。 |
| • | 檢查 validateRequest 屬性。 |
| • | 檢查 HttpOnly Cookie 選項。 |
| • | 檢查 <frame> 安全性屬性。 |
| • | 檢查 innerText 和 innerHTML 屬性的使用。 |
在瀏覽器中檢視網頁輸出的原始程式碼,來瞭解程式碼是否置於屬性內。如果是的話,請注入下列程式碼,並重新測試來檢視其輸出。
"onmouseover= alert('hello');"
開發人員常用的一項技術是篩選 < 和 > 字元。如果您檢閱的程式碼會篩選這些字元,那麼請改用下列程式碼來測試:
&{alert('hello');}
如果程式碼不會篩選這些字元,那麼您可以利用下列指令碼來測試程式碼:
<script>alert(document.cookie);</script>;
在使用此指令碼之前,您可能必須先關閉一個標籤,如下所示。
"></a><script>alert(document.cookie);</script>
在整個 .aspx 原始程式碼中,以及您已為應用程式開發的其他任何組件所包含的程式碼中,搜尋「.Write」字串。此舉會找出有 Response.Write 的位置,以及可能透過回應物件變數 (例如下面所示的程式碼) 產生輸出的任何內部常式。
public void WriteOutput(Response respObj)
{
respObj.Write(Request.Form["someField"]);
}
您還應該在 .aspx 原始程式碼中搜尋「<%=」字串,此程式碼還可以用來寫入輸出,如下所示:
<%=myVariable %>
下表顯示一些常見的狀況,其中 Response.Write 是與輸入欄位一起使用。
[表 21.1] 輸入的可能來源
| 輸入來源 | 範例 |
表單欄位 | Response.Write(name.Text); Response.Write(Request.Form["name"]); |
QueryString | Response.Write(Request.QueryString["name"]); |
Cookies | Response.Write( Request.Cookies["name"].Values["name"]); |
工作階段和應用程式變數 | Response.Write(Session["name"]); Response.Write(Application["name"]); |
資料庫和資料儲存區 | SqlDataReader reader = cmd.ExecuteReader(); Response.Write(reader.GetString(1)); |
雖然並不詳盡,但是下列常用的 HTML 標籤可以讓惡意使用者注入指令碼:
| • | <applet> |
| • | <body> |
| • | <embed> |
| • | <frame> |
| • | <script> |
| • | <frameset> |
| • | <html> |
| • | <iframe> |
| • | <img> |
| • | <style> |
| • | <layer> |
| • | <ilayer> |
| • | <meta> |
| • | <object> |
HTML 屬性 (例如,src、lowsrc、style,以及href) 可以連同上述標籤一起使用,來造成 XSS 攻擊。
例如,<img> 標籤的 src 屬性可能是注入的來源,如下列範例所示。
<IMG SRC="javascript:alert('hello');">
<IMG SRC="java
script:alert('hello');">
<IMG SRC="java
script:alert('hello');">
藉由變更 MIME 類型,<style> 標籤也可能是注入的來源,如下所示。
<style TYPE="text/javascript">
alert('hello');
</style>
檢查程式碼是否有進行輸入的安全性過濾,以找出某些已知危險的字元。請勿僅依賴此種方法,因為惡意的使用者通常可以找到另一種表示法,來通過您的檢驗。您的程式碼應該驗證輸入是否為已知的安全輸入。下表顯示用來表示一些常見字元的各種方式:
[表 21.2] 字元表示法
| 字元 | 十進位 | 十六進位 | HTML 字元集 | Unicode |
" (雙引號) |
" | " | " | \u0022 |
' (單引號) | ' | ' | ' | \u0027 |
& (ampersand) | & | & | & | \u0026 |
< (小於) | < | < | < | \u003c |
> (大於) | > | > | > | \u003e |
會處理 URL 的程式碼可能會有安全性弱點。檢閱程式碼看它是否有弱點,而容易遭受下列常見的攻擊:
| • | 如果 Web 伺服器未用最新的安全性補充程式更新,那麼它就可能容易遭受目錄周遊和雙斜線的攻擊,例如: http://www.YourWebServer.com/..%255%../winnt http://www.YourWebServer.com/..%255%..//somedirectory |
| • | 如果您的程式碼會篩選「/」,攻擊者就可以利用同一字元的另一種表示法,來輕易地略過該篩選器。例如,/ 之過長的 UTF8 表示法是 %c0f%af,而且它可以在下列 URL 中使用: http://www.YourWebServer.com/..%c0f%af../winnt |
| • | 如果程式碼能處理查詢字串的輸入,請檢查它是否會限制輸入的資料,並執行界限檢查。如果攻擊者透過查詢字串參數,來傳遞極大量的資料,請檢查程式碼是否會有安全性弱點。 http://www.YourWebServer.com/test.aspx?var=InjectHugeAmountOfDataHere |
雖然這不能取代檢查輸入的格式是否完整且正確,但是您應該檢查是否用 HtmlEncode 來為所有包含輸入之 HTML 的輸出編碼。此外,還要檢查 UrlEncode 是否用來將 URL 字串編碼。輸入資料可能得自查詢字串、表單欄位、Cookie、HTTP 標頭,以及從資料庫讀取的輸入 (特別是當資料庫是與其他應用程式共用時)。透過將資料編碼,您就能防止瀏覽器將 HTML 視為可執行的指令碼。
若要協助防止攻擊者利用標準與多位元組的逸出序列來欺騙輸入的驗證常式,請檢查字元編碼是否已正確設定,來限制輸入表示的方式。
請檢查應用程式的 Web.config 檔案是否已將 <globalization> 元素設定的 requestEncoding 和 responseEncoding 屬性,設定為如下所示。
<configuration> <system.web> <globalization requestEncoding="ISO-8859-1" responseEncoding="ISO-8859-1"/> </system.web> </configuration>
字元編碼也可以在網頁的層級,利用 <meta> 標籤或 ResponseEncoding 網頁層級的屬性來設定,如下所示。
<% @ Page ResponseEncoding="ISO-8859-1" %>
如需詳細資訊,請參閱單元 10<建置安全的 ASP.NET 網頁和控制項>。
利用 .NET Framework 1.1 版建置的 Web 應用程式,會執行輸入篩選來消除有潛在惡意的輸入,例如內嵌式指令碼。請勿依賴此項功能,但可使用它來執行深入的防護。檢查設定檔案中的 <pages> 元素,來確認已將 validateRequest 屬性設定為 true。此屬性也可以設定為網頁層級的屬性。掃描 .aspx 原始檔案找出 validateRequest,並對任何網頁檢查它並未設定為 false。
Internet Explorer 6 SP 1 能夠支援新的 HttpOnly Cookie 屬性,它能防止用戶端的指令碼存取 document.cookie 屬性中的 Cookie。反之,會傳回空的字串。每當使用者瀏覽至目前網域中的網站時,這個 Cookie 仍會傳送至伺服器。如需詳細資訊,請參閱單元 10<建置安全的 ASP.NET 網頁和控制項>中的「跨網站指令碼」一節。
Internet Explorer 6 與更新的版本在 <frame> 和 <iframe> 元素上,能支援新的 security 屬性。您可以使用 security 屬性,對個別的 frame 或 iframe 套用使用者的受限制網站 Internet Explorer 安全性區域設定。如需詳細資訊,請參閱單元 10<建置安全的 ASP.NET 網頁和控制項>中的「跨網站指令碼」一節。
如果建立了具不可信任輸入的網頁,請確認您使用的是 innerText 屬性而不是 innerHTML。innerText 屬性可以安全地呈現內容,並確保指令碼不會執行。
如需有關 XSS 的詳細資訊,請參閱下列文章:
| • | 《CSS Quick Start: What Customers Can Do to Protect Themselves from Cross-Site Scripting (英文)》,網址為:http://www.microsoft.com/technet/security/news/crsstQS.asp |
| • | 《CSS Overview (英文)》,網址為:http://www.microsoft.com/technet/security/news/csoverv.asp。 |
| • | Microsoft 知識庫文件 252985《How To: Prevent Cross-Site Scripting Security Issues (英文)》。 |
| • | 《CERT Advisory CA200002, Malicious HTML Tags Embedded in Client Web Requests (英文)》,放在 CERT/CC 網站上,網址為:http://www.cert.org/advisories/CA-2000-02.html |
| • | 《Understanding Malicious Content Mitigation for Web Developers (英文)》,放在 CERT/CC 網站上,網址為:http://www.cert.org/tech_tips/malicious_code_mitigation.html |
當程式碼使用輸入參數來建構 SQL 敘述時,它就容易遭受 SQL 注入攻擊。就如 XSS 漏洞一樣,SQL 注入攻擊是由於對使用者輸入的資料付予太高信任度且沒有驗證輸入是否正確與且格式完整而造成的。
下列程序能協助您找出容易遭受 SQL 注入攻擊的弱點:
1. | 尋找存取資料庫的程式碼。 |
2. | 檢查程式碼是否使用參數化的預存程序。
SqlDataAdapter myCommand = new SqlDataAdapter("spLogin", conn);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
SqlParameter parm = myCommand.SelectCommand.Parameters.Add(
"@userName", SqlDbType.VarChar,12);
parm.Value=txtUid.Text;
具型別的 SQL 參數會檢查輸入的型別和長度,並確定將 userName 輸入值視為文字值,而不是資料庫中的可執行程式碼。 |
3. | 檢查程式碼是否在 SQL 敘述中使用參數。 select status from Users where UserName=@userName 檢查使用下列是否並未使用,其中輸入是利用字串連接來直接建構可執行的 SQL 敘述。 string sql = "select status from Users where UserName='" + txtUserName.Text + "'"; |
4. | 檢查程式碼是否會嘗試篩選輸入。 |
在檢閱程式碼以找出緩衝區溢位時,請將檢閱工作專注於透過 P/Invoke 或 COM interop 層,來呼叫 Unmanaged 程式碼的程式碼。Managed 程式碼本身顯然比較不易遭受緩衝區溢位的攻擊,因為在存取陣列時,會自動檢查陣列的界限。一旦呼叫 Win32 DLL 或 COM 物件之後,您就應該詳細地檢查該 API 呼叫。
下列程序能協助您找出容易遭受緩衝區溢位攻擊的弱點:
1. | 找出對 Unmanaged 程式碼的呼叫。
|
2. | 檢查傳遞至 Unmanaged API 的字串參數。 void SomeFunction( char *pszInput )
{
char szBuffer[10];
// 小心,沒有長度檢查。輸入會直接複製到緩衝區
// 應該要檢查長度或使用 strncpy。
strcpy(szBuffer, pszInput);
. . .
}
注意 如果使用了 strncpy,緩衝區溢位仍然可能發生,因為它並不會檢查目的地字串中是否有足夠的空間,而且只會限制要複製的字元數目。 如果因為未擁有 Unmanaged 程式碼而不能加以檢查,請傳進很長的輸入字串與無效的引數,來嚴格測試該 API。 |
3. | 檢查檔案路徑長度。 |
4. | 檢查輸出字串。 |
5. | 檢查陣列的界限。 |
6. | 檢查 Unmanaged 程式碼是否有用 /GS 選項編譯。 |
請使用這一節中的檢閱問題,來分析整個 Managed 原始程式碼基礎。不論組件的類型為何,檢閱的問題都能適用。這一節將協助您識別 Managed 程式碼常見的弱點。如需有關這一節所提出各項問題的詳細資訊,以及解說安全性弱點的程式碼範例,請參閱單元 7<建置安全的組件>。
如果 Managed 程式碼使用了明確的程式碼存取安全性的功能,請參閱本單元後面的<程式碼存取安全性>,來瞭解其他的檢閱點。下列檢閱的問題能協助您識別 Managed 程式碼的弱點:
| • | 您的類別設計是否安全? |
| • | 您是否有建立執行緒? |
| • | 您是否有使用序列化? |
| • | 您是否有使用反射? |
| • | 您是否有處理例外? |
| • | 您是否有使用密碼編譯? |
| • | 您是否有儲存機密? |
| • | 您是否有使用委派? |
組件只能與其所包含的類別和其他類型一樣地安全。下列問題能協助您檢閱類別設計的安全性:
| • | 是否限制類型和成員的可見度? |
| • | 非基底的類別是否已密封? 對於公開的基底類別,您可以使用程式碼存取安全性的繼承需求,來限制可從該類別繼承過來的程式碼。這多少都是一種良好的防護。 |
| • | 您是否有使用屬性來公開欄位? |
| • | 您是否有使用唯讀屬性? |
| • | 您是否有使用虛擬的內部方法? |
| • | 您是否有實作 IDisposable? |
多重執行緒程式碼容易有精細的與時間相關錯誤或賽跑情況,這些都可能造成安全性弱點。若要找出多重執行緒程式碼,請對原始程式碼搜尋文字 Thread,來識別建立新的 Thread 物件的位置,如下列程式碼片段所示:
Thread t = new Thread(new ThreadStart(someObject.SomeThreadStartMethod));
下列檢閱的問題能協助您識別執行緒的潛在弱點:
| • | 程式碼是否快取安全性檢查的結果? |
| • | 程式碼是否會模擬? |
| • | 程式碼是否包含靜態的類別建構函式? |
| • | 您是否有將 Dispose 方法同步? |
支援序列化的類別是標示為 SerializableAttribute,或是從 ISerializable 推演得到。若要找出支援序列化的類別,請執行文字搜尋,找出 Serializable 字串。然後針對下列問題來檢閱程式碼:
| • | 類別是否包含機密資料? 如果類別需要序列化機密資料,請檢閱如何保護該資料。請考慮先加密該資料。 |
| • | 類別是否會實作 ISerializable? |
| • | 類別是否會驗證資料串流? |
若要協助找出會使用反射的程式碼,請搜尋 System.Reflection 。這是包含反射類型的命名空間。如果確實使用了反射,請檢閱下列問題來協助識別潛在的弱點:
| • | 您是否有動態地載入組件? |
| • | 在程式執行時期是否動態地建立程式碼? |
| • | 您是否有對其他類型使用反射? |
安全的例外處理對堅強的程式碼是必要的,它能夠確保會記錄足夠的例外詳細資訊,來協助進行問題診斷,並協助防止將內部的系統詳細資訊透露給用戶端。請檢閱下列問題,來協助識別潛在的例外處理的弱點:
| • | 您的程式碼是否會儘早失敗? |
| • | 如何處理例外? |
| • | 您是否有記錄例外的詳細資訊? |
| • | 您是否有使用例外篩選器? 如需例外篩選器弱點的範例,請參閱單元 7<建置安全的組件>中的「例外管理」。 |
如果是的話,請檢查程式碼是否並未實作其密碼編譯常式。反之,程式碼應該使用 System.Security.Cryptography 命名空間,或者使用 Win32 加密,例如資料保護應用程式設計介面 (DPAPI)。請檢閱下列問題,來協助識別潛在的密碼編譯相關的弱點:
| • | 您是否有使用對稱式加密? |
| • | 您是否有使用最大的金鑰長度? |
| • | 您是否有使用雜湊? |
| • | 您是否有為了密碼編譯的目的而產生隨機數字? |
如果組件儲存了機密,請檢閱其設計,來檢查是否有絕對的必須儲存該機密。如果必須儲存機密,請檢閱下列問提以便盡可能安全地執行:
| • | 您是否有將機密存放在記憶體中? |
| • | 您是否有將純文字密碼或 SQL 連線字串儲存在 Web.config 或 Machine.config 中? |
| • | 如何加密機密? |
| • | 您是否有將機密儲存在登錄中? |
| • | 您是否有關心還原工程? 注意 請勿依賴模糊化工具來隱藏機密資料。模糊化工具能使識別機密資料更困難,但卻不能解決此問題。 |
任何程式碼都可以將方法與委派建立起關聯。這種情況包括在比您的程式碼更低的信任層級上執行,且具潛在惡意的程式碼。
| • | 您是否有從不可信任的來源接受委派? |
| • | 在呼叫委派之前是否使用宣告? |
所有 Managed 程式碼都有程式碼存取安全性權限的要求。當程式碼是在部分信任的環境裡使用時,以及當程式碼存取安全性原則並未將完全的信任授予您的程式碼或呼叫程式碼時,許多問題才會變得很明顯。
如需有關這一節所提出各項問題的詳細資訊,請參閱單元 8<程式碼存取安全性實務>。
請使用下列檢閱點,來檢查是否適當地且安全地使用程式碼存取安全性:
| • | 您是否有支援部分信任的呼叫者? |
| • | 您是否有限制存取公開類型和成員? |
| • | 您是否有使用宣告的安全性? |
| • | 您是否有呼叫 Assert? |
| • | 在應該使用權限要求時,是否使用它? |
| • | 您是否有使用連結要求? |
| • | 您是使用 Deny 還是 PermitOnly? |
| • | 您是否有使用特別危險的權限? |
| • | 您是否有用 /unsafe 選項來編譯? |
如果程式碼能支援部分信任的呼叫者,它就更有可能遭受攻擊,結果執行廣泛且徹底之程式碼的檢視就更為重要。檢閱 Web 應用程式中 <trust> 層級的組態設定,來瞭解它是否是在部分信任的層級執行。如果是的話,為應用程式開發的組件就必須能夠支援部分信任的呼叫者。
下列問題能協助您識別具潛在弱點的區域:
| • | 組件是否以強式命名? 注意 ASP.NET 應用程式所呼叫以強式命名的組件必須安裝在「全域組件快取」中。 |
| • | 您是否有使用 APTCA? |
| • | 您是否有交出物件的參考? |
您可以使用程式碼存取安全性識別身份的要求,來限制存取到公開的類型和成員。這是減少組件的攻擊面的一種很有用的方式。
| • | 您是否有利用識別身份要求來限制呼叫者? |
| • | 您是否有使用繼承要求來限制梓類別? |
宣告的安全性屬性可以用如 Permview.exe 等工具來顯示。此舉能大幅地協助組件的消費者和管理員瞭解程式碼的安全性需求。
| • | 您是否有要求最小的權限? |
| • | 您是否有要求可選擇或者拒絕權限? |
| • | 您是否有使用強制的安全性而不使用宣告的安全性? |
| • | 您是否有將類別與成員層級的屬性混合? |
掃描程式碼找出 Assert 呼叫。此舉可能找到 Debug.Assert 的例項。尋找程式碼在何處對 CodeAccessPermission 物件呼叫 Assert。在宣告程式碼存取的權限時,您會將程式碼存取安全性權限要求的堆疊巡迴切短,此舉是一種危險的行為。您的程式碼會採取哪些步驟確保惡意的呼叫者不會利用宣告,來存取保護安全的資源或具特殊權限的作業?請檢閱下列問題:
| • | 您是否有使用要求、宣告模式? |
| • | 您是否有將 Assert 呼叫與 RevertAssert 配合? |
| • | 您是否有減少宣告的期間? |
程式碼永遠會在 .NET Framework 類別庫中,遭受權限要求的檢查,但是如果程式碼使用了明顯的權限要求,請檢查此動作是否已恰當地完成。對程式碼搜尋 .Demand 字串,來識別宣告的和強制的權限要求,然後再檢閱下列問題:
| • | 您是否有快取資料? |
| • | 您是否有公開自訂資源或特殊權限操作? |
| • | 您是否有要求得夠快? |
| • | 您是否有發出多餘的要求? |
連結要求與一般的要求不同,只會檢查立即的呼叫者。它們並不會執行完整的堆疊巡迴,結果使用連結要求的程式碼就會遭受誘惑攻擊。如需有關誘惑攻擊的詳細資訊,請參閱單元 8<程式碼存取安全性實務>中的「連結要求」。
對程式碼搜尋 .LinkDemand 字串,來識別使用連結要求的位置。只能宣告性地使用它們。一個範例如下列程式碼片斷所示:
[StrongNameIdentityPermission(SecurityAction.LinkDemand,
PublicKey="00240000048...97e85d098615")]
public static void SomeOperation() {}
如需有關這一節所提出各項問題的詳細資訊,請參閱單元 8<程式碼存取安全性實務>中的「連結要求」。下列問題能協助您檢閱在程式碼中使用連結要求:
| • | 為何使用連結要求? |
| • | 您是否有信任您的呼叫者? |
| • | 您是否有呼叫用連結要求保護的程式碼? |
| • | 在方法和類別的層級是否曾使用連結要求? |
| • | 您是否有對未密封的類別使用連結要求? |
| • | 您是否有使用連結要求來保護結構? |
| • | 您是否有使用明顯的介面? |
請檢查下列權限類型是否僅授與給高度信任的程式碼。大部份程式碼沒有自己專用的權限類型,而使用一般的 SecurityPermission 類型。因此您應該仔細檢查會使用這些類型的程式碼,以確保風險降到最低。此外,您一定要有很好的理由才能使用這些權限。
[表 21.3] 危險的權限
| 權限 | 說明 |
SecurityPermission.UnmanagedCode | 程式碼可以 呼叫 Unmanaged 程式碼。 |
SecurityPermission.SkipVerification | 不再需要驗證此組件中的程式碼是否為安全類型。 |
SecurityPermission.ControlEvidence | 該程式碼可以為它自己提供證據,以供安全性原則評估之用。 |
SecurityPermission.ControlPolicy | 程式碼可以檢視及更改原則。 |
SecurityPermission.SerializationFormatter | 程式碼可以使用序列化。 |
SecurityPermission.ControlPrincipal | 程式碼可以操作用於授權的主體物件。 |
ReflectionPermission.MemberAccess | 程式碼可以透過反射來叫用某類型的私用成員。 |
SecurityPermission.ControlAppDomain | 程式碼可以建立新的應用程式網域。 |
SecurityPermission.ControlDomainPolicy | 程式碼可以變更網域原則。 |
請使用 Visual Studio .NET 來檢查專案屬性,以查看 Allow Unsafe Code Blocks 是否已設定為 true。這會設定編譯器旗標 /unsafe ,以告訴編譯器程式碼中含有危險的區塊和要求,而且最小的使用權限 SkipVerification 已放在該組件中。
如果您編譯時使用了 /unsafe,請再次檢閱您為何需要這麼做。如果理由正當,請多花一些時間來檢閱原始碼,以找出可能的弱點。
由於安全性風險增大,請特別注意會呼叫 Unmanaged 程式碼的程式碼,包括 Win32 DLL 和 COM 物件。Unmanaged 程式碼不是確實安全的類型,而且可能會引起緩衝區溢位。從 Unmanaged 程式碼存取資源時,並不會受到程式碼存取安全性的檢查。這是屬於 Managed 包裝函式類別的職責。.
一般來說,您不應該讓 Unmanaged 程式碼直接開放給部份信任的呼叫者。有關這一節所提出各項問題的詳細資訊,請參閱單元 7<建置安全的組件>中的「Unmanaged 程式碼」一節,以及單元 8<程式碼存取安全性實務>。
請使用下列檢閱性問題來檢驗 Unmanaged 程式碼之使用:
| • | 您是否有宣告 Unmanaged 程式碼的使用權限? 如果是,請在呼叫 Assert 方法之前,先檢查程式碼所要求的權限是否適當,以確保所有的呼叫者已獲授權存取資源或 Unmanaged 程式碼所開放的操作。例如,下列程式碼片段顯示如何要求一個自訂的「加密」權限,然後宣告 Unmanaged 程式碼的權限: // 要求自訂 EncryptionPermission。 (new EncryptionPermission( EncryptionPermissionFlag.Encrypt, storeFlag)).Demand(); // 宣告 Unmanaged 程式碼權限。 (new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert(); // 現在使用 P/Invoke 來呼叫 Unmanaged DPAPI 函數。 若要取得更多詳細資訊,請參閱單元 8<程式碼存取安全性實務>中的「Assert 與 RevertAssert」。 | ||||||||||||
| • | 您是否有使用 SuppressUnmanagedCodeAttribute? 注意 新增 SupressUnmanagedCodeSecurityAttribute 會把對 interop 階層發出的 UnmanagedCode 權限之隱含需求轉變為 LinkDemand。您的程式碼將容易受到誘惑攻擊。 | ||||||||||||
| • | Unmanaged 進入點公開可見嗎? | ||||||||||||
| • | 您是否有加以保護以防止緩衝區溢位? 注意 所有套用到 C 及 C++ 之程式碼的檢閱規則和原則,都會套用到 Unmanaged 程式碼。 | ||||||||||||
| • | 您是否有對列舉型別進行範圍檢查? | ||||||||||||
| • | 您是否有對 Unmanaged 程式碼方法使用命名慣例? | ||||||||||||
| • | 您是否有呼叫具有潛在危險的 API?
|
請使用這一節所述的檢閱性問題來檢閱 ASP.NET 網頁和控制項。有關這一節所提出各項問題的詳細資訊,請參閱單元 10<建置安全的 ASP.NET 網頁和控制項>。
| • | 您是否有停用詳細的錯誤訊息? |
| • | 您是否有停用追蹤? |
| • | 您是否有驗證表單欄位的輸入? |
| • | 您是否有遭受 XSS 攻擊? |
| • | 您是否有驗證查詢字串及 Cookie 輸入? |
| • | 您是否有依賴 HTTP 標頭來保障安全? |
| • | 您是否有保障檢視狀態的安全? |
| • | 您是否有防止 XSS? |
| • | 您的 Global.asax 事件處理常式是否安全? |
| • | 您是否有提供適當的授權? |
如果允許例外傳播超越應用程式界線,ASP.NET 便會傳回給呼叫者詳細的資訊。這些資訊包括完整的堆疊追蹤和其他有助於攻擊者的資訊。請檢查 <customErrors> 元素,並確認模式屬性已設定為 On 或 RemoteOnly。
<customErrors mode="On" defaultRedirect="YourErrorPage.htm" />
追蹤資訊對攻擊者也是非常有幫助的。請檢查 <trace> 元素以確認已停用追蹤。
<trace enabled="false" localOnly="true" pageOutput="false" requestLimit="10" traceMode="SortByTime"/>
攻擊者可以透過公佈的表單欄位,將惡意的輸入傳遞至您的網頁和控制項。請檢查您是否已驗證所有表單欄位的輸入,包括隱藏的表單欄位。然後驗證欄位的類型、範圍、格式和長度。最後,使用下列問題來檢閱您 ASP.NET 的輸入處理情形:
| • | 您的輸入包括檔案名稱或檔案路徑? 如果您接受檔案名稱和路徑作為輸入,您的程式碼就容易受到正規化漏洞的攻擊。如果您必須接受使用者輸入的路徑,那麼請檢查是否已經過驗證為安全路徑而且正規化。請檢查程式碼是否已使用 System.IO.Path.GetFullPath。 |
| • | 您是否有呼叫 MapPath? try
{
string mappedPath = Request.MapPath( inputPath.Text,
Request.ApplicationPath, false);
}
catch (HttpException)
{
// 嘗試跨應用程式對應。
}如需詳細資訊,請參閱單元 10<建置安全的 ASP.NET 網頁和控制項>中的「使用 MapPath」一節。 |
| • | 如何驗證資料型別? |
| • | 如何驗證字串型別? |
| • | 您是否有使用驗證控制項? |
| • | 您是否有依賴用戶端驗證? |
請務必檢閱網頁是否有 XSS 弱點。如需詳細資訊,請參閱本單元前面的<跨網站指令碼 (Cross-Site Scripting,XSS)>。
請檢查程式碼是否驗證由 URL 查詢字串所傳遞的輸入欄位,以及從 Cookie 擷取的輸入欄位。若要找到易受攻擊的程式碼,請搜尋下列文字字串:
| • | "Request.QueryString" |
| • | "Request.Cookies" |
請使用具型別的物件來檢查輸入的型別、範圍、格式及長度是否已驗證過,就像對表單欄位使用規則運算式一樣 (請參閱先前的<您是否有驗證表單欄位的輸入?>一節)。此外,也需考慮源自使用者輸入的任何輸出之 HTML 或 URL 編碼,因為這會使任何可能引起 XSS 漏洞攻擊的無效結構反而變成有效。
如果應用程式使用檢視狀態,那麼它可防止竄改嗎?請檢閱下列問題:
| • | 您是否有在應用程式層級啟用檢視狀態保護? <pages enableViewState="true" enableViewStateMac="true" /> |
| • | 是否以每頁為基礎來覆寫檢視狀態保護? |
| • | 您是否有在程式碼中覆寫檢視狀態保護? |
Global.asax 檔案包含應用程式層級之事件的事件處理程式碼,該事件是由 ASP.NET 和 HTTP 模組產生的。請檢閱下列事件處理常式,以確保程式碼並未包含任何弱點:
| • | Application_Start。此處的程式碼會在 ASP.NET 處理序帳戶 (而非模擬的使用者) 的安全性內容下執行。 |
| • | Application_BeginRequest。此處的程式碼會在 ASP.NET 處理序帳戶 (或模擬的使用者) 的安全性內容下執行。 |
| • | Application_EndRequest。如果需要修改外送 Cookie 的內容,例如,設定 Secure 位元或網域,請在Application_EndRequest 處進行設定。 |
| • | Application_AuthenticateRequest。這會執行使用者驗證。 |
| • | Application_Error。當此事件處理常式被呼叫,安全性內容會對 Windows 事件記錄檔之寫入有所影響。安全性內容可能是處理序帳戶或模擬的使用者。 |
| • | protected void Session_End。此事件是在不確定的情況下被觸發,而且只有同處理序 (In-process) 的工作階段狀態模式會這樣。 |
請檢閱下列問題以確認您的授權方法:
| • | 您是否有在限制和公用存取區域之間分割您的網站? |
| • | 如何保護受限制網頁的存取? 您是否已設定 <authorization> 元素,來指定哪些使用者和使用者群組可存取特定的網頁? |
| • | 如何保護網頁類別的存取? |
| • | 您是否有使用 Server.Transfer? Server.Transfer 會使用不同的模組來處理該網頁,而不會從伺服器另外提出要求,以強制執行授權。如果安全是目標網頁上的一項考量,就請不要使用 Server.Transfer ;而改用 HttpResponse.Redirect 。 |
ASP.NET Web 服務分享許多與 ASP.NET Web 應用程式相同的功能。在您提出下列與 Web 服務相關的問題之前,請先以<ASP.NET 網頁及控制項>一節所列的問題來檢查您的 Web 服務。有關這一節所提出各項問題的詳細資訊,請參閱單元 12<建置安全的 Web 服務>。
| • | 您是否有公開限制的操作或資料? |
| • | 如何授權呼叫者? |
| • | 您是否有限制特殊權限操作? |
| • | 您是否有使用自訂驗證? |
| • | 您是否有驗證所有輸入? |
| • | 您是否有驗證 SOAP 標頭? |
如果 Web 服務公開了受限制的操作或資料,請檢查該服務是否驗證呼叫者。您可以使用平台驗證機制,如 NTLM、Kerberos、基本驗證或用戶端 X.509 憑證,或者您可以傳遞 SOAP 標頭中的驗證權杖。
如果您要傳遞驗證權杖,那麼可以利用「Web 服務增強功能」(Web Services Enhancements,WSE),以符合新興 WS-Security 標準的方式來使用 SOAP 標頭。
請選擇適當的授權方案,這些方案可由 .NET Framework (例如,URL 授權、檔案授權和「.NET 角色」) 或平台選項 (如「檔案 ACL」) 提供。
程式碼存取安全性原則的信任等級,可決定 Web 服務可存取的資源類型。請檢查 Machine.config 或 Web.config 中 <trust> 元素的設定。
請使用「Web 服務增強功能」(WSE) 所提供的功能,而不要建立自己的驗證方式。
如果接收到的輸入來自於目前信任界線之外的來源,請先檢查公開展示的所有 Web 方法是否驗證其輸入參數,然後才可以使用它們或將它們傳遞到下游元件或資料庫。
如果您在應用程式中使用自訂的 SOAP 標頭,請檢查資訊是否未被竄改或未被重新執行。以數位方式簽署標頭資訊可確保資訊未被竄改。您可以使用 WSE 以標準的方式來簽署 Web 服務郵件。
請檢查 SoapException 和 SoapHeaderException 物件是否用來適當地處理錯誤,及提供用戶端基本的必要資訊。請確認例外是否被正確地記錄,以供疑難排解之用。
這一節會指出您應該考慮的檢閱要點,來檢閱 Enterprise Services 應用程式內所用的服務元件。有關這一節所提出各項問題的詳細資訊,請參閱單元 11<建置安全的服務元件>。
| • | 您是否有使用組件層級中繼資料? |
| • | 您是否有防止匿名存取? |
| • | 您是否有使用限制的模擬層級? |
| • | 您是否有使用角色為基礎的安全性? |
| • | 您是否有使用方法層級授權? |
| • | 您是否有使用物件建構函式字串? |
| • | 您是否有在中介層 (Middle Tier) 進行稽核? |
請檢查是否使用組件層級中繼資料,來定義 Enterprise Services 安全性設定。使用 assemblyinfo.cs 檔案,然後使用屬性來定義驗證和授權設定。這樣可確保已在系統管理時正確地建立這些設定。雖然系統管理員可以覆寫這些設定,但是組件層級中繼資料提供了系統管理員一個清楚的定義,以進行設定。
請檢查程式碼是否使用 ApplicationAccessControl 屬性來指定驗證層次。接著,搜尋 AuthenticationOption 字串來尋找相關的屬性。然後,檢查是否使用最小呼叫層級的驗證,以確認呼叫每個元件都經過驗證。
[assembly: ApplicationAccessControl( Authentication = AuthenticationOption.Call)]
您定義的服務元件模擬層級,會決定您通訊之對方遠端伺服器的模擬能力。請搜尋 ImpersonationLevel 字串來檢查程式碼設定的層級。
[assembly: ApplicationAccessControl( ImpersonationLevel=ImpersonationLevelOption.Identify)]
請檢查是否設定遠端伺服器必需的最大限制層級。例如,如果伺服器基於驗證目的,必須識別您的身分,則可使用以上所示的識別身份層級,而不必用模擬的方式。在 Windows 2000 上,請小心地使用委派層級模擬,因為安全性內容可以不限次數地在電腦間傳遞。Windows Server 2003 則介紹了限制的委派。
注意 在 Windows Server 2003 及 Windows 2000 Service Pack 4 和更新版本中,並沒有授與所有使用者模擬的權限。
如果元件是在伺服器應用程式中,則以上所示的組件層級屬性向 Enterprise Services 登錄後,就會控制元件的起始設定。
如果元件是在程式庫應用程式中,則用戶端處理序會決定模擬層級。如果用戶端是 ASP.NET Web 應用程式,請檢查 Machine.config 檔案中 <processModel> 元素上comImpersonationLevel 的設定。
請藉由檢閱下列問題,來檢查程式碼是否正確地使用角色為基礎的安全性,以防止未獲授權的存取:
| • | 您是否有啟用角色為基礎的安全性? [assembly: ApplicationAccessControl(true)] |
| • | 您是否有使用元件層級存取檢查? [assembly: ApplicationAccessControl(AccessChecksLevel= AccessChecksLevelOption.ApplicationComponent)] 此外,也請檢查各個類別是否使用 ComponentAccessControl 屬性來加註,如下所示: [ComponentAccessControl(true)]
public class YourServicedComponent : ServicedComponent
{
} |
| • | 您是否有在程式碼中執行角色檢查? |
在程式碼中搜尋 ConstructionEnabled,以尋找使用物件結構字串的類別。
[ConstructionEnabled(Default="")] public class YourServicedComponent : ServicedComponent, ISomeInterface
如果使用物件結構函式字串,請檢閱下列問題:
| • | 您是否有將敏感性資料儲存在結構函式字串中? |
| • | 您是否有提供預設的結構字串? |
您應該跨分散式應用程式進行稽核。請檢查服務元件是否記錄了操作和異動。透過 SecurityCallContext 物件可以使用原始呼叫者識別身份。如果已使用下列屬性,針對處理序和元件層級檢查而設定應用程式的安全性層級,那麼就可在中介層進行稽核。
[assembly: ApplicationAccessControl(AccessChecksLevel= AccessChecksLevelOption.ApplicationComponent)]
這一節會指出您應該考慮的檢閱要點,來檢閱使用 .NET 遠端服務的程式碼。有關這一節所提出各項問題的詳細資訊,請參閱單元 13<建置安全的遠端元件>。
| • | 您是否有將物件當做參數傳遞? |
| • | 您是否有使用自訂驗證和主體物件? |
| • | 如何設定 Proxy 憑證? |
如果您使用 TcpChannel ,而且您的 API 元件接受自訂物件參數,或者如果自訂物件通過呼叫內容來傳遞,那麼您的程式碼會有兩個安全性弱點。
| • | 如果當作參數傳遞的物件源自於 System.MarshalByRefObject,那麼可藉由參考傳遞該物件。這種情況下,物件需要一個 URL 來支援呼叫回應給用戶端。用戶端 URL 也有可能會被欺騙,而導致呼叫回應給替代電腦。 |
| • | 如果當做參數傳遞的物件支援序列化,就能以值傳遞該物件。在這個例子中,當程式碼在伺服器上進行還原序列化時,請檢查它是否驗證每個欄位項目,以防止插入惡意的資料。 |
若要防止自訂物件以參數或值傳遞給遠端的元件,請將伺服器端格式子通道接收上的 TypeFilterLevel 屬性設定為 TypeFilterLevel.Low。
若要尋找呼叫內容中所傳遞的物件,請搜尋 ILogicalThreadAffinative 字串。只有實作這個介面的物件可以在呼叫內容中傳遞。
如果您使用自訂物件,您是否會依賴從用戶端傳來的主體物件?這是具有潛在危險的,因為惡意的程式碼會建立一個主體物件,其內含擴充式角色來提高使用權限。如果您使用這種方式,請檢查您是否只有將它與 Out-of-Band 機制 (如 IPSec 原則) 一起使用,以限制可以連接到您元件的用戶端電腦。
請檢閱您的用戶端程式碼如何設定遠端 Proxy 上的憑證。如果使用明確的憑證,那麼在何處維護這些憑證?這些憑證應該加密並儲存在安全的位置,例如受限制的登錄機碼。而且不應該將它們以固定寫在程式碼中的方式放在純文字中。在理想情況下,用戶端程式碼應該使用該用戶端處理序權杖及預設憑證。
這一節會指出您應該考慮的檢閱要點,來檢閱您的資料存取程式碼。有關這一節所提出各項問題的詳細資訊,請參閱單元 14<建置安全的資料存取>。
| • | 您是否有防止 SQL 注入? |
| • | 您是否有使用 Windows 驗證? |
| • | 您是否有保障資料庫連接字串的安全? |
| • | 如何限制未獲授權的程式碼? |
| • | 如何保障資料庫中敏感資料的安全? |
| • | 您是否有處理 ADO .NET 例外? |
| • | 您是否有關閉資料庫連線? |
請檢查程式碼是否經由驗證輸入來防止 SQL 注入攻擊、使用最小權限帳戶來連接到資料庫,以及使用參數化儲存程序或參數化 SQL 命令。如需詳細資訊,請參閱本單元前面的<SQL 注入>。
藉由使用 Windows 驗證,您不需要跨網路即可將憑證傳遞到資料庫伺服器,而且連接字串不包含使用者名稱和密碼。如以下範例所示,Windows 驗證連接字串會使用 Trusted_Connection='Yes' 或 Integrated Security='SSPI'。
"server='YourServer'; database='YourDatabase' Trusted_Connection='Yes'" "server='YourServer'; database='YourDatabase' Integrated Security='SSPI'"
檢閱程式碼是否正確且安全地使用資料庫連接字串?這些字串不應該以固定寫在程式碼中的方式儲存在純文字的設定檔中,尤其是當連接字串包含使用者名稱和密碼時。
搜尋 Connection 字串來尋找 ADO .NET 連線物件,並檢閱如何設定 ConnectionString 屬性。
| • | 您是否有加密連接字串? |
| • | 您是否有使用空白密碼? |
| • | 您是否有使用 sa 帳戶或其他具有高權限的帳戶? |
| • | 您是否有使用保存安全性資訊 (Persist Security Info)? |
如果您已寫好一個資料存取類別程式庫,那該如何防止未獲授權的程式碼存取您的程式庫,進而存取資料庫?一個方法就是使用 StrongNameIdentityPermission 要求來限制呼叫程式碼,使它只能呼叫以特定增強名稱私密金鑰簽章的程式碼。
如果要將敏感資料 (如信用卡號碼) 儲存在資料庫中,該如何保障資料的安全?您應該檢查資料是否已經過對稱式加密演算法 (如 3DES) 進行加密。
如果使用此方法,那又該如何保障 3DES 加密金鑰的安全?您的程式碼應該使用 DPAPI 來加密 3DES 加密金鑰,然後將加密金鑰儲存在受限制的位置,如登錄。
請根據所使用的 ADO .NET 資料提供者,來檢查所有資料存取程式碼是否放在 try/catch 區塊之內,以及程式碼是否處理 SqlExceptions、OleDbExceptions 或 OdbcExceptions。
請檢查程式碼是否不易受攻擊,即使發生例外,而資料庫連線仍保持開啟狀態。請檢查程式碼是否關閉 finally 區塊之內的所有連線,或連線物件是否在 C# using 陳述式之內建構的,如下所示。This automatically ensures that it is closed.
using ((SqlConnection conn = new SqlConnection(connString)))
{
conn.Open();
// 連線會中斷的情況包括如果產生例外,或控制流程
// 正常地離開 using 陳述式的範圍。
}安全性程式碼的檢閱類似於一般程式碼的檢閱或檢查,但所著重的是如何識別可能造成安全性弱點的程式碼瑕疵。額外的好處是,解決了安全性瑕疵也會使得程式碼更加穩固。
本單元已告訴您如何檢閱 Managed 程式碼,以識別主要的安全性問題,包括 XSS、SQL 注入,以及緩衝區溢位等問題。其中也說明了如何識別其他更細微的瑕疵,這些瑕疵都可能造成安全性弱點,而導致攻擊者得逞。
安全性程式碼的檢閱並不是萬靈丹。但它還是有一定的效果,所以應該作為程式開發週期的一項常態作業。
如需詳細資訊,請參閱 MSDN 上的文章《Secure Coding Guidelines for the .NET Framework (英文)》,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/seccodeguide.asp。