| 本單元內容 | |
| 目標 | |
| 適用於 | |
| 如何使用本單元 | |
| 潛在威脅及因應對策 | |
| 設計考量 | |
| 輸入驗證 | |
| SQL 注入 | |
| 驗證 | |
| 授權 | |
| 設定管理 | |
| 機密資料 | |
| 例外管理 | |
| 建立安全的資料存取元件 | |
| 程式碼存取安全性考量 | |
| 部署考量 | |
| 總結 | |
| 其他資源 |
資料存取是使用幾個可用的 ADO.NET 資料提供者之一從 ASP.NET Web 應用程式存取資料庫的過程。
此資料庫是應用程式層級攻擊的首要目標。應用程式層級攻擊是用來利用資料存取程式碼中的弱點,使其未經授權即可存取資料庫。如果所有其他攻擊向量都已關閉,則應用程式的前門 (連接埠 80) 會成為攻擊者偷竊、操作和破壞資料的選擇路徑。
本單元說明如何建立安全的資料存取程式碼,以避免一般弱點及陷阱。本單元呈現一系列因應對策及防禦技術,可在資料存取程式碼中用來減輕有關資料存取的頭號潛在威脅。
透過本單元即可:
| • | 設計、建立和部署安全的資料存取程式碼。 |
| • | 使用程式碼存取安全性及角色安全性,來限制未授權的呼叫者或程式碼的存取。 |
| • | 安全地驗證使用者。 |
| • | 防止 SQL 注入攻擊。 |
| • | 保障資料庫連接字串的安全。 |
| • | 使用加密來保護資料庫中儲存的資料。 |
| • | 保障透過網路在資料庫來回傳送的資料。 |
| • | 將密碼安全地 (具利用 Salt 的雜湊) 儲存在資料庫中。 |
| • | 執行安全的例外狀況處理。 |
| • | 學習如何使用程式碼存取安全性,允許中等信任的 Web 應用程式使用 OLE DB、Oracle 及 ODBC 資料提供者 (它們都要求完全信任)。 |
| • | 瞭解要套用何種因應對策來解決常見的資料存取潛在威脅,包括 SQL 注入、公開設定資料、公開機密的應用程式資料、公開資料庫結構描述及連線細節、未授權存取及網路竊聽。 |
本單元適用於下列產品及技術:
| • | Microsoft® Windows® 2000 Server 及 Microsoft Windows Server 2003 |
| • | Microsoft .NET Framework 1.1 及 ASP.NET 1.1 |
| • | Microsoft SQL Server |
若要深入瞭解本單元,請閱讀在本單元之前或關聯本單元的下列單元:
| • | 閱讀單元 2 <潛在威脅及因應對策> 。此單元可讓您更廣泛而深入瞭解 Web 應用程式所面對的潛在威脅及因應對策。 |
| • | 閱讀單元 4 <設計安全 Web 應用程式的指導方針> 。在本單元中,您將學習建立安全解決方案的架構、設計挑戰及指導方針。 |
| • | 閱讀單元 18 <保障資料庫伺服器的安全> 。閱讀單元 18 以瞭解如何保障資料庫伺服器的安全。 |
| • | 閱讀單元 7 <建置安全的組件> 。單元 17 中用來建置安全的組件及開發安全的 Managed 程式碼的指導方針及建議,也可以使用存取單元套用到資料存取程式碼中。 |
| • | 使用評估單元。若要在產品週期不同階段中檢視資料存取的安全性,請參閱下列單元的 Web 服務章節:單元 5<安全性的架構及設計檢閱>;單元 21<程式碼的檢閱>;以及單元 22<部署過程的檢閱>。 |
| • | 使用檢查清單。 本指南<檢查清單>一節中的<檢查清單:保障資料存取的安全>包含方便參考的檢查清單。使用這項以工作為主的檢查清單,作為本單元的建議總結。 |
請注意,在目前的 .NET Framework (1.1) 版本中,只有 ADO.NET SQL Server 資料存取提供者支援部分信任呼叫者,而且可安全地用於部分信任的 Web 應用程式中。OLE DB、Oracle 及 ODBC ADO.NET 資料提供者要求完全信任。
若要建立安全的資料存取程式碼,瞭解有何潛在威脅、資料存取程式碼中如何產生一般弱點及如何使用正確的因應對策以降低風險。
資料存取程式碼的頭號潛在威脅是:
| • | SQL 注入 |
| • | 公開設定資料 |
| • | 公開機密的應用程式資料 |
| • | 公開資料庫結構描述及連線細節 |
| • | 未授權存取 |
| • | 網路竊聽 |
[圖 14.1] 說明了這些頭號潛在威脅。

[圖 14.1]
資料存取程式碼的潛在威脅及攻擊
SQL 注入攻擊會利用有弱點的資料存取程式碼,而允許攻擊者在資料庫中執行任何命令。如果應用程式在資料庫中使用未受限制的帳戶,會有較大的潛在威脅,因為它會提供攻擊者更大的自由執行查詢及命令。
弱點
使資料存取程式碼易受 SQL 注入攻擊的常見弱點包括:
| • | 安全性不足的輸入驗證 |
| • | 不使用型別安全的參數動態建構 SQL 陳述式 |
| • | 使用權限過高的資料庫登入身份 |
因應對策
若要對付 SQL 注入攻擊,請務必:
| • | 限制及安全性過濾輸入資料。 |
| • | 使用型別安全的 SQL 參數來執行資料存取。這些參數可以搭配預存程序或動態建構的 SQL 命令字串使用。這些參數執行類型及長度檢查,還可確保將注入的程式碼視為文字資料,而不是資料庫中可執行的陳述式。 |
| • | 使用在資料庫中權限有限的帳戶。理想情況下,您應該只授與執行權限給資料庫中選定的預存程序,而且不應提供資料表。 |
資料存取程式碼所用的最機密設定資料就是資料庫連接字串。如果洩漏的連接字串包含使用者名稱及密碼,其後果可能還要更嚴重。
弱點
下列弱點會增加有關公開設定資料的安全性風險:
| • | 使用 SQL 驗證,這需要在連接字串中指定憑證 |
| • | 將連接字串內嵌在程式碼中 |
| • | 在設定檔案中純文字的連接字串 |
| • | 未加密連接字串 |
因應對策
若要防止公開設定資料:
| • | 使用 Windows 驗證,讓連接字串不包含憑證。 |
| • | 加密連接字串並限制存取已加密的資料。 |
許多應用程式都會儲存機密資料,例如客戶信用卡號碼。保護這種資料的隱私性及完整性是不可或缺的。
弱點
會導致公開機密應用程式資料的程式碼編碼實例包括:
| • | 儲存資料時不加密 |
| • | 安全性不足的授權 |
| • | 安全性不足的加密 |
因應對策
若要防止公開機密應用程式資料:
| • | 使用增強式加密來保障資料的安全。 |
| • | 在執行資料存取之前授權每個呼叫者,讓使用者只能看到他們自己的資料。 |
如果程式碼將例外狀況細節傳回用戶端,惡意使用者就可以使用此資訊來攻擊伺服器。資料存取程式碼中的例外狀況會公開機密資訊,例如資料庫結構描述細節、資料存放區的本質及 SQL 程式碼片段。
弱點
下列弱點會導致公開資訊:
| • | 例外狀況處理不當 |
| • | 安全性不足的 ASP.NET 設定會讓未處理的例外狀況細節傳回到用戶端 |
因應對策
若要防止這類公開:
| • | 擷取、記錄及處理資料存取程式碼中的資料存取例外狀況。 |
| • | 將一般錯誤訊息傳回給呼叫者。這需要正確設定 Web.config 或 Machine.config 設定檔中 <customErrors> 元素的設定。 |
由於不當授權,使用者可能會看到另一位使用者的資料,因而可以存取其他受限制的資料。
弱點
允許未授權存取的實例包括:
| • | 資料存取程式碼中缺乏授權而提供無限制的存取 |
| • | 權限過高的資料庫帳戶 |
因應對策
若要防止未授權存取:
| • | 使用主體權限要求來授權呼叫的使用者。 |
| • | 使用程式碼存取安全性要求來授權呼叫的程式碼。 |
| • | 使用有限的權限來限制應用程式登入資料庫,以防止直接存取資料表。 |
大多數應用程式的部署架構,都會將資料庫伺服器與資料存取程式碼做實體的分隔。結果是,如應用程式專用資料或資料庫登入憑證等機密資料都需要加以保護以免遭到網路竊聽。
弱點
下列實例會增加網路竊聽的弱點:
| • | 在 SQL 驗證期間透過網路傳遞純文字憑證 |
| • | 在資料庫伺服器來回傳送未加密的機密應用程式資料 |
因應對策
若要限制網路竊聽的弱點:
| • | 使用 Windows 驗證以避免透過網路傳送憑證。 |
| • | 在資料庫伺服器上安裝伺服器憑證。如此會自動加密網路上的 SQL 憑證。 |
| • | 在 Web 伺服器和資料庫伺服器之間使用 SSL 連線,來保護機密的應用程式資料。這需要資料庫伺服器憑證。 |
| • | 在 Web 伺服器與資料庫伺服器之間使用 IPSec 加密通道。 |
在開始撰寫程式碼之前,有一些重要問題在設計時期需要考量。主要考量如下:
| • | 使用 Windows 驗證。 |
| • | 使用最小權限的帳戶。 |
| • | 使用預存程序。 |
| • | 保護儲存中的機密資料。 |
| • | 使用個別資料存取組件。 |
理想情況下,您的設計應該使用 Windows 驗證以獲得附加的安全性優點。利用 Windows 驗證,您不必使用內嵌的憑證來儲存資料庫連接字串、憑證不會透過網路傳遞,而且您可受益於安全的帳戶及密碼管理原則。不過,您需要仔細考量要使用哪個帳戶來連接使用 Windows 驗證的 SQL Server。
如需詳細資訊,請參閱本單元稍後的「驗證」。
您的應用程式應該使用最小權限的帳戶,使其在資料庫中的權限受到限制。確定登入資料庫的應用程式有正確的授權和限制。如需詳細資訊,請參閱本單元稍後的「授權」。
如果您的帳戶遭到入侵或注入惡意程式碼,使用最小權限的帳戶可降低風險並限制潛在的損害。在 SQL 注入的狀況下,命令會在應用程式登入所定義的安全性內容之下執行,而且受制於此登入在資料庫中所擁有的相關權限。如果使用權限過高的帳戶 (例如 SQL Server sysadmin 角色的成員) 來連線,攻擊者就可以在伺服器的任何資料庫中執行任何作業。其中包括插入、更新及刪除資料;丟棄資料表;以及執行作業系統命令。
重要 請勿使用 sa 帳戶或屬於 SQL Server sysadmin 或 db_owner 角色成員的任何帳戶來連線 SQL Server。
預存程序提供效能、維護及安全性等優點。儘可能使用參數化的預存程序來存取資料。安全性的好處包括:
| • | 您可以限制應用程式資料庫登入,使其只具有執行特定預存程序的權限。不必要授與直接存取資料表。如此有助於減輕 SQL 注入攻擊所造成的風險。 |
| • | 在所有輸入資料傳遞到預存程序時執行長度及型別檢查。另外,不可將參數視為可執行的程式碼。如此同樣可減輕 SQL 注入的風險。 |
若您因故不能使用參數化的預存程序而需要動態建構 SQL 陳述式,可以使用型別參數及參數預留位置來確保輸入資料已經過的長度及型別檢查。
識別需要保證隱私性及完整性的預存資料。若您將密碼儲存在資料庫中單純只是為了驗證用途,請考慮使用單向雜湊。如果密碼表遭入侵,就無法使用這些雜湊來取得純文字密碼。
若是儲存使用者提供的機密資料,例如信用卡號碼,請使用增強式對稱加密演算法 (例如 Triple DES (3DES)) 來加密資料。使用 Win32 Data Protection API (DPAPI) 來加密 3DES 加密金鑰,將已加密的金鑰儲存在登錄機碼中,此登錄機碼具有受限制的 ACL,只有系統管理員及應用程式處理序帳戶可以使用該金鑰。
雖然建議使用 DPAPI 來加密連接字串及其他機密,例如當機器故障時可以手動修復和重建的帳戶憑證,但它比較不適用於儲存類似信用卡號碼的資料。這是因為有可復原方面的問題 (如果遺失此金鑰,就無法復原已加密的資料) 及 Web 伺服陣列的問題。您反而應該使用對稱加密演算法 (例如 3DES) 並使用 DPAPI 來加密您的加密金鑰。
使 DPAPI 比較不適用於在資料庫中儲存機密資料的主要問題總結如下:
| • | 如果搭配機器金鑰來使用 DPAPI,而且您將 CRYPTPROTECT_LOCAL_MACHINE 傳遞到 CryptProtectData 及 CryptUnprotectData 函數,則機器帳戶會建立加密金鑰。這表示 Web 伺服陣列中的每個伺服器都有不同的金鑰,可避免另一部伺服器存取某伺服器中的加密資料。而且,如果 Web 伺服器遭到破壞,金鑰就會遺失,而無法從資料庫復原加密的資料。 |
| • | 如果使用機器金鑰,則該電腦上的任何使用者都可以解密資料 (除非您使用額外的加密機制)。 |
| • | 如果搭配使用者金鑰來使用 DPAPI,並使用本機使用者帳戶,則每部 Web 伺服器的每個本機帳戶都有不同的安全性識別元 (SID) 並會建立不同的金鑰,可避免另一部伺服器存取某伺服器中的加密資料。 |
| • | 如果搭配使用者金鑰來使用 DPAPI,並使用橫跨 Web 伺服陣列中所有機器的漫遊使用者設定檔,則所有資料都會共用相同的加密/解密金鑰。不過,如果負責漫遊使用者設定檔帳戶的網域控制站毀損或遭到破壞,就無法重建具有相同 SID 的使用者帳戶,也就不能從資料庫復原已加密的資料。 而且,如果某人設法擷取資料,假設攻擊者可以在特定使用者帳戶下執行程式碼,就可以在網路中任何機器上解密漫遊使用者設定檔。這會增加潛在被攻擊的風險,而且不建議使用。 |
若您有選擇的話,請避免將資料存取邏輯直接放在 ASP.NET 網頁或程式碼後置 (Code-Behind) 檔案中。將資料存取邏輯放入分開的組件中,並執行與應用程式商業及展示邏輯分開的邏輯資料存取層,具有安全性、重複使用及維護等優點。
從安全性方面來看,您可以:
| • | 使用增強名稱作為組件名稱,以提供防竄改功能。 |
| • | 使用沙箱功能來隔離資料存取程式碼,如果程式碼需要支援部分信任呼叫者 (如部分信任 Web 應用程式),這是非常重要的。 |
| • | 使用以程式碼識別身份權限要求來授權呼叫程式碼的程式碼資料存取方法及類別。 |
為了提供深層防禦,請使用商業元件中的主體權限要求來執行以主體為基礎的授權,然後使用程式碼識別身份權限要求來授權呼叫資料存取邏輯的程式碼,如 [圖 14.2] 所示。

[圖 14.2]
分開展示、商業及資料存取層
如需有關資料存取程式碼授權的詳細資訊,請參閱本單元稍後的「授權」。
除了確保資料庫維持有效及一致性資料的商業需求之外,還必須在將資料提交到資料庫之前驗證資料,以防止 SQL 注入。如果資料存取程式碼從現行信任範圍內的其他元件接收其輸入,而且您知道資料已經通過驗證 (例如,由 ASP.NET 網頁或商業元件驗證),則您的資料存取程式碼可以忽略延伸資料驗證。不過,請確定您在資料存取程式碼中使用 SQL 參數。這些參數會驗證參數的型別及長度。下一節將討論 SQL 參數的用法。
SQL 注入攻擊可能會發生在當應用程式使用輸入來建構動態 SQL 陳述式以存取資料庫的時候。如果您的程式碼使用的預存程序傳遞含有未篩選之使用者輸入的字串,也可能發生 SQL 注入攻擊。SQL 注入可能導致攻擊者得以使用應用程式登入在資料庫中執行命令。如果應用程式使用權限過高的帳戶來連線資料庫,此問題可能會擴大。
注意 慣用的安全性測量 (例如使用 SSL 及 IPSec) 無法保護您免受 SQL 注入攻擊。
使用下列因應對策來防止 SQL 注入攻擊:
| • | 限制輸入。 |
| • | 使用型別安全的 SQL 參數。 |
驗證輸入的型別、長度、格式和範圍。若您不期望數值,則請勿接受它們。考慮輸入的來源。如果它來自您知道已經執行完整輸入驗證的信任來源,就可以選擇在資料存取程式碼中忽略資料驗證。如果資料來自不可信任的來源或基於深層防禦,則資料存取方法及元件都應該驗證輸入。
SQL 中的 Parameters 集合提供型別檢查及長度驗證。如果使用 Parameters 集合,輸入會被視為文字值,而 SQL 不會將它視為可執行的程式碼。使用 Parameters 集合的額外好處是可以強制型別及長度檢查。範圍以外的值將觸發例外狀況。這是深層防禦的健全範例。
重要 SSL 不會保護您免於 SQL 注入。存取資料庫而沒有適當的輸入驗證及正確的資料存取技術的任何應用程式,都很容易受到 SQL 注入攻擊。
在可能的情況下使用預存程序,然後使用 Parameters 集合來呼叫它們。
下列程式碼片段說明 Parameters 集合的用法:
SqlDataAdapter myCommand = new SqlDataAdapter("AuthorLogin", conn);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
SqlParameter parm = myCommand.SelectCommand.Parameters.Add(
"@au_id", SqlDbType.VarChar, 11);
parm.Value = Login.Text;
在此狀況下,@au_id 參數被視為文字值,而不是可執行的程式碼。而且,會檢查參數的型別及長度。在上述範例中,輸入值不能超過 11 個字元。如果資料不符合參數所定義的型別或長度,就會產生例外狀況。
請注意,使用預存程序未必可防止 SQL 注入。重要的是搭配預存程序來使用參數。若未使用參數,而預存程序是使用未篩選輸入的話,就很容易受到 SQL 注入。例如,下列程式碼片段就很容易受到攻擊:
SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure '" +
Login.Text + "'", conn);
重要 若是使用預存程序,請確定有使用參數。
若未使用預存程序,您仍可使用參數,如下列程式碼片段所示:
SqlDataAdapter myCommand = new SqlDataAdapter(
"SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", conn);
SqlParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id",
SqlDbType.VarChar, 11);
parm.Value = Login.Text;
一般人誤解如果在單一往返中將幾個 SQL 陳述式串連起來將一批陳述式傳送到伺服器,就無法使用參數。不過,如果確定參數名稱並未重複,就可以使用此技術。藉由在 SQL 文字串聯期間加入編號或一些其他唯一值,即可輕易完成此項工作。
用來防護 SQL 注入攻擊的另一種方法是開發篩選器常式,它會將逸出字元加入對 SQL 具有特殊意義的字元中,例如單引號字元。下列程式碼片段說明加入逸出字元的篩選器常式:
private string SafeSqlLiteral(string inputSQL)
{
return inputSQL.Replace("'", "''");
}
擁有這種常式的問題及為何不能完全依賴它們的原因,在於攻擊者可能使用 ASCII 十六進位字元來略過檢查。不過,您應該將篩選輸入作為深層防禦策略的一部份。
注意 請勿依賴篩選輸入。
請注意,如果使用 LIKE 子句,萬用字元仍然需要逸出字元。下列程式碼片段說明此方法:
s = s.Replace("[", "[[]");
s = s.Replace("%", "[%]");
s = s.Replace("_", "[_]");
當您的應用程式連線到 SQL Server 資料庫時,可以選擇使用 Windows 驗證或 SQL 驗證。Windows 驗證比較安全。若您必須使用 SQL 驗證,或許是因為您需要連線到使用許多不同帳戶的的資料庫並想避免呼叫 LogonUser,請採取額外的步驟儘可能減輕額外的風險。
注意 使用 LogonUser 來建立模擬權杖需要具有 Microsoft Windows 2000 中功能強大的「作為作業系統的一部份」權限,因此應該避免使用此方法。
考慮下列建議:
| • | 使用 Windows 驗證。 |
| • | 保護 SQL 驗證的憑證。 |
| • | 使用最小權限的帳戶連線。 |
Windows 驗證不會透過網路傳送憑證。如果在 Web 應用程式使用 Windows 驗證,在多數狀況下,您會使用服務帳戶或處序業帳戶 (例如 ASPNET 帳戶) 來連線到資料庫。Windows 及 SQL Server 必須都可識別您在資料庫伺服器所用的帳戶。此帳戶必須獲得授權登入 SQL Server,此登入需要有相關權限才能存取資料庫。
當您使用 Windows 驗證時,就是使用信任的連線。下列程式碼片段顯示使用 Windows 驗證的典型連接字串。
下列範例使用 ADO.NET 資料提供者作為 SQL Server:
SqlConnection pubsConn = new SqlConnection( "server=dbserver; database=pubs; Integrated Security=SSPI;");
下列範例使用 ADO.NET 資料提供者作為 OLE DB 資料來源:
OleDbConnection pubsConn = new OleDbConnection( "Provider=SQLOLEDB; Data Source=dbserver; Integrated Security=SSPI;" + "Initial Catalog=northwind");
如果必須使用 SQL 驗證,請確定並未透過網路以純文字傳送憑證,並加密資料庫連接字串,因為其中含有憑證。
若要使 SQL Server 自動加密透過網路傳送的憑證,請在資料庫伺服器安裝伺服器憑證。或者,在 Web 伺服器與資料庫伺服器之間使用 IPSec 加密通道,保障資料庫伺服器來回傳送的所有資料傳輸的安全。若要保障連接字串的安全,請使用 DPAPI。如需詳細資訊,請參閱本單元稍後的「設定管理」一節中的「保障連接字串的安全」。
您的應用程式應該使用最小權限的帳戶來連線到資料庫。如果使用 Windows 驗證來連線,則從作業系統觀點來看,Windows 帳戶應該為最小權限,而且存取 Windows 資源的權限及能力應該有限。此外,不論使用 Windows 驗證或 SQL 驗證,對應的 SQL Server 登入應該受限於資料庫的權限。
如需更多有關如何建立最小權限資料庫帳戶及使用 Windows 驗證連接 ASP.NET Web 應用程式到遠端資料庫的選項的詳細資訊,請參閱單元 19<保障 ASP.NET 應用程式及 Web 服務的安全>中的「資料存取」。
如果使用者可以擷取和處理特定資料,就會建立授權處理序。方法可分為兩種:資料存取程式碼可以使用授權來決定是否執行要求的作業,以及資料庫可以執行授權來限制應用程式所用 SQL 登入的功能。
由於不當授權,使用者可能會看到另一位使用者的資料,而且未授權使用者可能可以存取受限制的資料。若要解決這些潛在威脅:
| • | 限制未授權的呼叫者。 |
| • | 限制未授權的程式碼。 |
| • | 限制資料庫中的應用程式。 |
[圖 14.3] 總結應該使用的授權點及技術。

[圖 14.3]
資料存取授權、組件及資料庫
請注意資料存取程式碼能夠如何使用權限要求來授權呼叫使用者或呼叫程式碼。程式碼識別身份要求是 .NET 程式碼存取安全性的一項功能。
若要授權資料庫中的應用程式,請使用最小權限的 SQL Server 登入,它所擁有的權限只能執行選定的預存程序。除非有特殊原因,否則不應該授權應用程式直接在任何資料表上執行建立、擷取、更新、破壞/刪除 (CRUD) 作業。
注意 預存程序是在資料庫系統的安全性內容之下執行。雖然藉由指派權限給特殊預存程序,可以限制應用程式的邏輯作業,但是您不可以限制預存程序所執行作業的結果。預存程序是信任的程式碼。預存程序的介面必須使用資料庫權限來保障其安全。
您的程式碼在連線到資料庫之前,應該根據角色或識別身份來授權使用者。角色檢查通常用於應用程式的商業邏輯中,但是如果在商業及資料存取邏輯之間沒有明確的區分,請使用存取資料庫的方法上的主體權限要求。
下列屬性可確保只有屬於 Manager 角色成員的使用者可以呼叫 DisplayCustomerInfo 方法:
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="Manager")]
public void DisplayCustomerInfo(int CustId)
{
}
如果需要額外的授權細微性,而且需要在資料存取方法中執行角色為基礎的邏輯,請使用必要的主體權限要求或明確的角色檢查,如下列程式碼片段所示:
using System.Security;
using System.Security.Permissions;
public void DisplayCustomerInfo(int CustId)
{
try
{
// 必要的主要權限角色檢查以確認呼叫者
// 是管理員
PrincipalPermission principalPerm = new PrincipalPermission(
null, "Manager");
// 下列程式碼只有當呼叫者是
// Manager 角色的成員時才會執行
}
catch( SecurityException ex )
{
. . .
}
}
下列程式碼片段使用明確的、計劃性的角色檢查來確保呼叫者是 Manager 角色的成員:
public void DisplayCustomerInfo(int CustId)
{
if(!Thread.CurrentPrincipal.IsInRole("Manager"))
{
. . .
}
}
藉由使用 .NET Framework 程式碼存取安全性,尤其是程式碼識別身份要求,您可以限制可存取資料存取類別及方法的組件。
例如,如果您只要讓公司或特定開發組織所撰寫的程式碼使用資料存取元件,請使用 StrongNameIdentityPermission 及具有特殊公開金鑰的增強名稱的呼叫組件的要求,如下列程式碼片段所示:
using System.Security.Permissions;
. . .
[StrongNameIdentityPermission(SecurityAction.LinkDemand,
PublicKey="002...4c6")]
public void GetCustomerInfo(int CustId)
{
}
若要擷取特定組件的公開金鑰的文字表示,請使用下列命令:
sn -Tp assembly.dll
注意 在 Tp 參數中使用大寫字母「T」。
因為 Web 應用程式組件為動態編譯,所以您不能在這些組件中使用增強名稱。這會使它難以限制在特定 Web 應用程式中使用資料存取組件。最佳方法是開發自訂權限,以及從資料存取元件要求該權限。完全信任 Web 應用程式 (或任何完全信任的程式碼) 可呼叫您的元件。不過,只有當部分信任程式碼已經授與自訂權限時,才可以呼叫您的資料存取元件。
如需自訂權限的實作範例,請參閱本指南<How To>一節中的<How To:建立自訂加密權限>。
較好的方法是為應用程式用來連線到資料庫的 Windows 帳戶建立 SQL Server 登入。然後將 SQL Server 登入對應到資料庫中的資料庫使用者。將資料庫使用者放入使用者自訂資料庫角色中,並授與權限給該角色。理想情況下,您應該只授與角色執行應用程式所用預存程序的權限。
如需有關如何設定此方法的詳細資訊,請參閱單元19<保障 ASP.NET 應用程式及 Web 服務的安全>中的「設定 ASP.NET 應用程式的資料存取」一節。
資料庫連接字串是資料存取程式碼主要關心的設定管理。仔細考量這些字串的儲存位置及如何保障其安全,尤其是其中含有憑證時。改善加密管理的安全性:
| • | 使用 Windows 驗證。 |
| • | 保障連接字串的安全。 |
| • | 使用受限制的 ACL 來保障 UDL 檔案的安全。 |
在使用 Windows 驗證時,憑證是由您自行管理,不會透過網路傳送憑證。您也要避免在連接字串中內嵌使用者名稱及密碼。
如果需要使用 SQL 驗證,則您的連線會包含使用者名稱及密碼。如果攻擊者利用 Web 伺服器上的原始程式碼公開弱點,或設法登入伺服器,則攻擊者可以擷取到連接字串。同理,合法登入伺服器的任何人都可以檢視它們。使用加密來保障連接字串的安全。
使用 DPAPI 來加密連接字串。可以使用 DPAPI 加密避免加密金鑰管理問題,因為加密金鑰是由平台管理,而且會租用給特定電腦或 Windows 使用者帳戶。若要使用 DPAPI,您必須透過 P/Invoke 來呼叫 Win32 DPAPI 函數。
如需有關如何建立 Managed 包裝函式類別的詳細資訊,請參閱《Microsoft Patterns & Practices Volume I, 建置安全的 ASP.NET 應用程式: 驗證、授權和安全通訊》中<How To>一節的<How To:建立 DPAPI 程式庫>,此文件位於 http://www.microsoft.com/taiwan/msdn/books/ataglance/secnetlpMSDN.htm。
加密的連接字串可以放在登錄、Web.config 或 Machine.config 中。如果使用 HKEY_LOCAL_MACHINE下的機碼,將下列 ACL 套用到機碼中:
Administrators: Full Control Process Account: Read
注意 處理序帳戶是由執行資料存取組件的處理序來決定。這通常是 ASP.NET 處理序,或者如果您的方案使用 Enterprise Services 中介層,則是 Enterprise Services 伺服器處理序。
或者,您可以考慮使用提供有限存取的 HKEY_CURRENT_USER。如需詳細資訊,請參閱單元 7<建置安全的組件>中的「登錄」一節。
注意 如果使用 Microsoft Visual Studio® .NET 資料庫連線精靈,則連接字串會純文字屬性值儲存在 Web 應用程式程式碼後置檔案或 Web.config 檔案中。這兩種方法都應該避免使用。
雖然比使用受限制的登錄機碼可能還不安全,但是在比較簡單的部署中,您可能會想要將加密字串儲存在 Web.config 中。在此狀況下,請使用自訂的 <appSettings> 名稱-值配對,如下所示:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="connectionString" value="AQA..bIE=" /> </appSettings> <system.web> ... </system.web> </configuration>
若要從 <appSettings> 元素存取密碼文字,請使用 ConfigurationSettings 類別,如下所示:
using System.Configuration;
private static string GetConnectionString()
{
return ConfigurationSettings.AppSettings["connectionString"];
}當您在連接字串中包含 Persist Security Info 屬性時,會使 ConnectionString 屬性在傳回給使用者之前,從連接字串中取出密碼。一旦建立資料庫連線,預設值 false (相當於忽略 Persist Security Info 屬性) 會捨棄此資訊。
如果應用程式搭配 OLE DB 的 ADO.NET Managed 資料提供者使用外部通用資料連結 (UDL) 檔案,請使用 NTFS 使用權限來限制存取。使用下列受限制的 ACL:
Administrators: Full Control Process Account: Read
注意 UDL 檔案並未加密。更安全的方法是使用 DPAPI 加密連接字串,並將它儲存在受限制的登錄機碼中。
許多 Web 應用程式都將表單的機密資料儲存在資料庫中。如果攻擊者設法執行資料庫查詢,就必須適當加密所有機密資料項目,例如信用卡號碼。
| • | 加密需要儲存的機密資料。 |
| • | 保障網路上機密資料的安全。 |
| • | 儲存利用 Salt 的密碼雜湊。 |
儘可能避免儲存機密資料。如果必須儲存機密資料,請將資料加密。
若要在資料庫中儲存機密資料 (例如信用卡號碼),請使用增強式對稱加密演算法,例如 3DES。
| • | 在開發期間啟用 3DES 加密
|
| • | 執行期間將加密資料儲存在資料庫中
|
| • | 執行期間解密已加密的秘密
|
利用此程序,如果用來加密此加密金鑰的 DPAPI 帳戶毀損,則可以從備份位置擷取 3DES 金鑰備份,然後在新帳戶使用 DPAPI 來加密。已加密的新金鑰可以儲存在登錄中,而仍可解密資料庫中的資料。
如需有關建立 Managed DPAPI 程式庫的詳細資訊,請參閱《Microsoft patterns & practices Volume I, 建置安全的 ASP.NET 應用程式: 驗證、授權和安全通訊》中<How To>一節中的<How To:建立 DPAPI 程式庫>,此文件位於 http://www.microsoft.com/taiwan/msdn/books/ataglance/secnetlpMSDN.htm。
跨網路在資料庫伺服器來回傳遞的機密資料,可能包含應用程式專用的資料或資料庫登入憑證。若要確定網路上資料的隱私性及完整性,請使用平台層級的方案 (例如在伺服器之間使用的 IPSec 加密通訊通道的安全資料中心所提供的方案) 或設定您的應用程式以建立資料庫的 SSL 連線。後一個方法要求在資料庫伺服器上安裝伺服器憑證。
如需有關使用 SSL 及 IPSec 的詳細資訊,請參閱《Microsoft patterns & practices Volume I, 建置安全的 ASP.NET 應用程式: 驗證、授權和安全通訊》中<How To>一節中的<How To:使用 IPSec 在兩部伺服器間進行安全通訊>和<How To:使用 SSL 與 SQL Server 2000 進行安全通訊>,此文件位於 http://www.microsoft.com/taiwan/msdn/books/ataglance/secnetlpMSDN.htm。
如果需要執行含有使用者名稱及密碼的使用者存放區,請不要以純文字或以加密格式來儲存密碼。儲存密碼的替代方式,可以利用 Salt 來儲存非可還原的雜湊值,以減輕字典攻擊的風險。
注意 Salt 值是經過密碼編譯的增強式隨機數字。
下列程式碼顯示如何使用 System.Security.Cryptography 名稱區中 RNGCryptoServiceProvider 類別提供的建立隨機數字功能來建立 Salt 值。
public static string CreateSalt(int size)
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}下列程式碼片段顯示如何從提供的密碼及 Salt 值建立雜湊值。
public static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = string.Concat(pwd, salt);
string hashedPwd =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltAndPwd, "SHA1");
return hashedPwd;
}
如需有關執行以 Salt 儲存密碼雜湊的使用者儲存的詳細資訊,請參閱《Microsoft patterns & practices Volume I, 建置安全的 ASP.NET 應用程式: 驗證、授權和安全通訊》中<How To>一節中的<How To:對 SQL Server 2000 使用表單驗證>,此文件位於 http://www.microsoft.com/taiwan/msdn/books/ataglance/secnetlpMSDN.htm。
例外狀況可能肇因於設定錯誤、程式碼中的錯誤或惡意輸入。若無適當的例外狀況管理,這些狀況除了會公開有價值的連線細節之外,還可能會公開有關資料來源的位置及本質等機密資訊。下列建議適用於資料存取程式碼:
| • | 設陷及記錄 ADO.NET 例外狀況。 |
| • | 確定資料庫連線永遠是關閉的。 |
| • | 使用 ASP.NET 應用程式中的一般錯誤頁面。 |
將資料存取程式碼放在 try / catch 區塊中並處理例外狀況。在撰寫 ADO.NET 資料存取程式碼時,ADO.NET 所產生的例外狀況類型乃視資料提供者而定。例如:
| • | SQL Server .NET Framework 資料提供者會產生 SqlExceptions。 |
| • | OLE DB .NET Framework 資料提供者會產生 OleDbExceptions。 |
| • | ODBC .NET Framework 資料提供者會產生 OdbcExceptions。 |
下列程式碼會使用 SQL Server .NET Framework 資料提供者並顯示如何擷取 SqlException 型別的例外狀況。
try
{
// 資料存取程式碼
}
catch (SqlException sqlex) // 更加特定
{
}
catch (Exception ex) // 比較不特定
{
}您還應該記錄 SqlException 類別的細節。此類別會公開含有例外狀況細節的屬性。其中包括描述錯誤的 Message 屬性、唯一識別錯誤類型的 Number 屬性及含有額外資訊的 State 屬性。State 屬性可用來指出發生特定錯誤狀況。例如,如果預存程序在多行產生相同的錯誤,則 State 屬性會指出特定發生的狀況。最後,Errors 集合包含提供詳細的 SQL server 錯誤資訊的 SqlError 物件。
下列程式碼片段顯示如何使用 SQL Server .NET Framework 資料提供者來處理 SQL Server 錯誤狀況:
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
// 資料存取層 (DAL) 元件所公開的方法
public string GetProductName( int ProductID )
{
SqlConnection conn = new SqlConnection(
"server=(local);Integrated Security=SSPI;database=products");
// 在 try 區塊中包含所有的資料存取程式碼
try
{
conn.Open();
SqlCommand cmd = new SqlCommand("LookupProductName", conn );
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@ProductID", ProductID );
SqlParameter paramPN =
cmd.Parameters.Add("@ProductName", SqlDbType.VarChar, 40 );
paramPN.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
// 在此方法傳回之前,最後執行的程式碼
return paramPN.Value.ToString();
}
catch (SqlException sqlex)
{
// 處理資料存取例外狀況
// 記錄特殊例外狀況細節
LogException(sqlex);
// 以更相關的方式包裝目前的例外狀況
// 外部例外狀況及重新擲出新例外狀況
throw new Exception(
"Failed to retrieve product details for product ID: " +
ProductID.ToString(), sqlex );
}
finally
{
conn.Close(); // 確定連線已關閉
}
}
// 將 SqlException 細節記錄至
// 應用程式事件日誌的 Helper 常式
private void LogException( SqlException sqlex )
{
EventLog el = new EventLog();
el.Source = "CustomAppLog";
string strMessage;
strMessage = "Exception Number : " + sqlex.Number +
"(" + sqlex.Message + ") has occurred";
el.WriteEntry( strMessage );
foreach (SqlError sqle in sqlex.Errors)
{
strMessage = "Message: " + sqle.Message +
" Number: " + sqle.Number +
" Procedure: " + sqle.Procedure +
" Server: " + sqle.Server +
" Source: " + sqle.Source +
" State: " + sqle.State +
" Severity: " + sqle.Class +
" LineNumber: " + sqle.LineNumber;
el.WriteEntry( strMessage );
}
}如果發生例外狀況,資料庫連線就必須關閉,然後釋出任何其他受限的資源。使用 finally 區塊或 C# using 陳述式來確定連線已關閉,不論是否發生例外狀況。上述程式碼說明 finally 區塊的用法。您也可以使用 C# using 陳述式,如下所示:
using ((SqlConnection conn = new SqlConnection(connString)))
{
conn.Open();
// 連線會中斷的情況包括如果產生例外,或控制流程
// 正常地離開 using 陳述式的範圍
}如果由 ASP.NET Web 應用程式或 Web 服務來呼叫資料存取程式碼,您應該設定 <customErrors> 元素以避免例外狀況細節送回給使用者。您也可以使用此元素來指定一般錯誤,如下所示。
<customErrors mode="On" defaultRedirect="YourErrorPage.htm" />
在產品伺服器設定 mode="On"。只有在發行之前開發和測試軟體時才使用 mode="Off" 。不如此做將導致大量的錯誤資訊傳回給使用者,如 [圖 14.4] 所示。此資訊可以包含資料庫伺服器名稱、資料庫名稱及連線憑證。

[圖 14.4]
公開機密資料的詳細例外狀況資訊
[圖 14.4] 還顯示了資料存取程式碼中靠近造成例外狀況那一行的許多弱點。具體來說:
| • | 連接字串是固定的。 |
| • | 使用高特殊權限的 sa 帳戶連線到資料庫。 |
| • | sa 帳戶具有安全性不足的密碼。 |
| • | SQL 命令建構容易受到 SQL 注入攻擊;輸入未經驗證,而且程式碼並未使用參數化的預存程序。 |
下列程式碼顯示用來查詢產品資料庫中庫存數量的 CheckProductStockLevel 方法的實作範例。此程式碼說明本單元稍早介紹的資料存取程式碼許多重要的安全性功能。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using Microsoft.Win32;
using DataProtection;
public static int CheckProductStockLevel(string productCode)
{
int quantity = 0;
// (1) 受到 try/catch 區塊保護的程式碼
try
{
// (2) 使用規則運算式驗證的輸入
// 應該從資源組件擷取錯誤訊息以協助
// 當地語系化。為了簡單起見而忽略了當地語系化程式碼。
if (Regex.IsMatch(productCode, "^[A-Za-z0-9]{12}$") == false)
throw new ArgumentException("Invalid product code" );
//(3) using 陳述式會確保連線已關閉
using (SqlConnection conn = new SqlConnection(GetConnectionString()))
{
// (4) 使用參數化預存程序是
// SQL 注入攻擊的因應對策
SqlCommand cmd = new SqlCommand("spCheckProduct", conn);
cmd.CommandType = CommandType.StoredProcedure;
// 參數已經過型別檢查
SqlParameter parm =
cmd.Parameters.Add("@ProductCode",
SqlDbType.VarChar,12);
parm.Value = productCode;
// 定義輸出參數
SqlParameter retparm = cmd.Parameters.Add("@quantity", SqlDbType.Int);
retparm.Direction = ParameterDirection.Output;
conn.Open();
cmd.ExecuteNonQuery();
quantity = (int)retparm.Value;
}
}
catch (SqlException sqlex)
{
// (5) 記錄完整的例外狀況細節。一般 (安全) 錯誤訊息
// 將根據 SQL 錯誤碼來擲回給呼叫者
// 為清楚起見已忽略日誌及錯誤識別元
throw new Exception("Error Processing Request");
}
catch (Exception ex)
{
// 記錄完整例外狀況細節
throw new Exception("Error Processing Request");
}
return quantity;
}
// (6) 加密的連接字串保存在登錄中
private static string GetConnectionString()
{
// 從登錄擷取密碼文字;處理序帳戶必須
// 由金鑰的 ACL 授與「讀取」權限
string encryptedString = (string)Registry.LocalMachine.OpenSubKey(
@"Software\OrderProcessing\")
.GetValue("ConnectionString");
// 使用 Managed DPAPI Helper 程式庫來解密此字串
DataProtector dp = new DataProtector(DataProtector.Store.USE_MACHINE_STORE);
byte[] dataToDecrypt = Convert.FromBase64String(encryptedString);
return Encoding.ASCII.GetString(dp.Decrypt(dataToDecrypt,null));
}
上述程式碼顯示下列安全性特性 (由註解行的數字指出)。
1. | 資料存取程式碼是放在 try/catch 區塊內。這是必要的,以免在發生例外狀況時將系統層級的資訊傳回給呼叫者。呼叫的 ASP.NET Web 應用程式或 Web 服務可能會處理例外狀況,然後將適當的一般錯誤訊息傳回給用戶端,但是資料存取程式碼並非依賴此方法。 |
2. | 使用規則運算式驗證輸入。檢查提供的產品識別碼以確認其中所含字元在 AZ 及 09 範圍之中,而且不超過 12 個字元。這是一套設計用來防止 SQL 注入攻擊的因應對策的首選。 |
3. | 使用陳述式在 Microsoft Visual C#® 中建立 SqlConnection 物件。如此可確定在此方法中已關閉連線,而不論是否發生例外狀況。這會減輕拒絕服務攻擊的潛在威脅,拒絕服務會嘗試使用資料庫的所有可用連線。您可以使用 finally 區塊來達成類似功能。 |
4. | 使用參數化預存程序來存取資料。這是防止 SQL 注入的另一個因應對策。 |
5. | 詳細的錯誤資訊並未傳回給用戶端。記錄例外狀況細節以協助診斷問題。 |
6. | 已加密的資料庫連接字串儲存在登錄中。儲存資料庫連接字串最安全的方法之一,是使用 DPAPI 來加密字串,然後將已加密的密碼文字儲存在具有受限制的 ACL 的安全登錄機碼中。(例如,使用 Administrators: Full Control 及 ASP.NET 或 Enterprise Services 處理序帳戶: Read,根據哪個處理序主控此元件而定)。 注意 此程式碼說明如何從登錄中擷取連接字串,然後使用 Managed DPAPI Helper 程式庫將它解密。此程式庫提供於《Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication (英文)》中<How To>一節中的<How To: Create a DPAPI Library>。 |
所有資料存取都受制於程式碼存取安全性權限要求。您選擇的 ADO.NET Managed 資料提供者會決定確切的需求。下表顯示必須授與每一個 ADO.NET 資料提供者的資料存取組件的權限。
[表 14.1] ADO.NET 資料提供者所需的程式碼存取安全性權限
| ADO.NET 資料提供者 | 需要的程式碼存取安全性權限 |
SQL Server | SqlClient |
OLE DB | OleDbPermission* |
Oracle | OraclePermission* |
ODBC | OdbcPermission* |
* 在撰寫本文之時,OLE DB、Oracle 及 ODBC 提供者在 .NET Framework 版本 1.0 及 1.1 只支援完全信任呼叫者。若要由部分信任 Web 應用程式使用這些提供者,您必須將資料存取程式碼放入沙箱,因此需要專門的資料存取組件。如需有關顯示如何將資料存取程式碼放入沙箱,以及從中度信任 Web 應用程式使用 OLE DB 資料提供者的範例,請參閱單元 9<配合 ASP.NET 使用程式碼存取安全性>。
如果使用 ADO.NET SQL Server 資料提供者,您的程式碼必須由程式碼存取安全性原則授與 SqlClientPermission。完全及中度信任 Web 應用程式具有此權限。
程式碼是否授有 SqlClientPermission 會決定該程式碼是否可以連線到 SQL Server。您也可以使用此權限來限制使用資料庫連接字串。例如,您可以強制應用程式使用整合式安全性,或者確定如果使用 SQL Server 安全性,則不會接受空白密碼。違反您以 SqlClientPermission 指定的規則將導致執行時期安全性例外狀況。
如需有關如何使用 SqlClientPermission 來限制資料存取的詳細資訊,請參閱單元 8<程式碼存取安全性實務>中的「資料存取」一節。
如果未以安全方式部署,則以安全方式設計及開發的資料存取元件仍可能遭到攻擊。一般的部署慣例是讓資料存取程式碼及資料庫儲存在分開的伺服器中。伺服器通常由內部防火牆隔開,如此會產生額外的部署考量。開發人員及系統管理員意識到下列問題:
| • | 防火牆限制 |
| • | 連接字串管理 |
| • | 登入帳戶設定 |
| • | 登入稽核 |
| • | 網路上的資料隱私性及完整性 |
如果透過防火牆連線到 SQL Server,請設定防火牆、用戶端及伺服器。使用「SQL Server 用戶端網路公用程式」來設定用戶端,並使用「伺服器網路公用程式」來設定資料庫伺服器。在預設狀況下,SQL Server 會監聽 TCP 連接埠 1433,然而您可以變更此連接埠。您必須在防火牆開啟選用的連接埠。
根據您選擇的 SQL Server 驗證模式及應用程式使用的分散式交易,您可能需要在防火牆開啟幾個額外的連接埠:
| • | 如果應用程式使用 Windows 驗證來連線到 SQL Server,必須開啟支援 Kerberos 或 NTLM 驗證的連接埠。 對於不使用 Active Directory 的網路,Windows 驗證通常需要使用 TCP 連接埠 139。如需有關連接埠需求的詳細資訊,請參閱 TechNet 文件《TCP and UDP Port Assignments (英文)》,此文件位於 http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit/tcpip/part4/tcpappc.asp,以及參閱《Security Considerations for Administrative Authority (英文)》,此文件位於 http://www.microsoft.com/technet/security/bestprac/bpent/sec2/seconaa.asp。 |
| • | 如果應用程式使用分散式交易,例如自動化 COM+ 交易,您還需要設定防火牆以允許 DTC 資料傳輸在隔開的 DTC 執行個體之間,以及在 DTC 及資源管理員 (例如 SQL Server) 之間流動。 |
如需完整設定的詳細資訊,請參閱單元 18<保障資料庫伺服器的安全>中的「連接埠」一節。
基於效能原因,許多應用程式都將連接字串儲存在程式碼中。不過,其效能的效益並不顯著,而使用檔案系統快取可協助確定將連接字串儲存在外部檔案中可提供相當的效能。使用外部檔案儲存連接字串對系統管理比較好。
對於增加安全性,建議的方法是使用 DPAPI 來加密連接字串。如果連接字串含有使用者名稱及密碼,此建議尤其重要。然後,決定已加密字串的儲存位置。登錄是安全的位置,尤其是使用 HKEY_CURRENT_USER,因為此存取受限於在相關使用者帳戶之下執行的處理序。較容易部署的替代方式是將已加密字串儲存在 Web.config 檔案中。這兩種方法都在本單元稍早的「設定管理」一節中有所討論。
您的應用程式必須使用最小權限帳戶來連線到資料庫。這是減輕 SQL 注入攻擊潛在威脅的主要技巧之一。
身為開發人員,您必須與系統管理員溝通確切的預存程序及應用程式的登入需要存取的 (可能) 資料表。理想情況下,您應該只允許應用程式的登入在一組與應用程式一起部署之受限制的預存程式上擁有執行權限。
在連線到資料庫的應用程式所用的 SQL 或 Windows 帳戶中使用增強式密碼。
請參閱本單元稍早的「授權」一節,以獲得資料庫中應用程式帳戶的建議授權策略。
您應該設定 SQL Server 記錄失敗的登入嘗試,以及可能成功的登入嘗試。稽核失敗的登入嘗試有助於偵測嘗試找出帳戶密碼的攻擊者。
如需有關如何設定 SQL Server 稽核的詳細資訊,請參閱單元 18<保障資料庫伺服器的安全>。
如果使用 SQL 驗證來連線到 SQL Server,請確定不會透過網路洩露登入憑證。請在資料庫伺服器安裝憑證 (使 SQL Server 加密憑證) 或在使用 IPSec 連接資料庫的加密通道。
建議使用 IPSec 或 SSL 連接資料庫,以保障在資料庫來回傳遞的機密應用程式層級的資料。如需詳細資訊,請參閱單元 18<保障資料庫伺服器的安全>。
本單元說明資料存取程式碼的頭號潛在威脅,並強調常見的弱點。SQL 注入是應該要注意的其中一種主要潛在威脅。除非使用本單元所討論的正確因應對策,否則攻擊者可能會利用您的資料存取程式碼,在資料庫中任意執行命令。傳統的安全性方法 (例如防火牆及 SSL) 無法防禦 SQL 注入攻擊。您應該完全驗證輸入,並使用參數化預存程序作為最基本的防禦。
有關其他詳細資訊,請參閱下列資源:
| • | 如需可列印的檢查清單,請參閱本指南<檢查清單>一節中的<檢查清單:保障資料存取的安全>。 |
| • | 如需保障開發人員工作站安全的詳細資訊,請參閱本指南<How To>一節中的<How To:保障開發人員工作站的安全>。 |
| • | 如需有關搭配使用 SQL Server 與 SSL 的詳細資訊,請參閱《Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication (英文)》中<How To>一節中的<How To:使用 SSL 與 SQL Server 2000 進行安全通訊>,此文件位於 http://www.microsoft.com/taiwan/msdn/books/ataglance/SecNetHT19.htm。 |
| • | 如需有關使用 IPSec 的詳細資訊,請參閱《Microsoft patterns & practices Volume I, 建置安全的 ASP.NET 應用程式: 驗證、授權和安全通訊》中<How To>一節中的<How To:使用 IPSec 在兩部伺服器間進行安全通訊>,此文件位於 http://www.microsoft.com/taiwan/msdn/books/ataglance/SecNetHT18.htm。 |
| • | 如需有關使用 DPAPI 的詳細資訊,請參閱《Microsoft patterns & practices Volume I, 建置安全的 ASP.NET 應用程式:驗證、授權和安全通訊》中<How To>一節中的<How To:建立 DPAPI 程式庫>,此文件位於 http://www.microsoft.com/taiwan/msdn/books/ataglance/SecNetHT07.htm。 |