.NET Framework 4 中的安全性變更
.NET Framework 4 版具有兩個主要安全性變更。 雖然已經排除電腦範圍的安全性原則,不過使用權限系統仍維持原狀,而且安全性透明度已經成為預設強制執行機制。 (如需詳細資訊,請參閱安全性透明的程式碼,層級 2)。此外,某些可能會呈現安全性弱點的使用權限作業已經變成過時了。
![]() |
---|
程式碼存取安全性 (CAS) 並未消除,安全性原則已從 CAS 中消除,但是辨識項和權限仍有效。少數權限已消除,而且透明度使強制執行安全性更簡單。如需變更的簡短概觀,請參閱程式碼存取安全性中的變更摘要。 |
您應該注意下列重點:
透明度會分隔當做應用程式一部分執行的程式碼與當做基礎結構一部分執行的程式碼。 它是 .NET Framework 2.0 版引入的,而且已經強化成為程式碼存取安全性強制執行機制。 與安全性原則不同的是,層級 2 透明度規則是在執行階段而非組件載入階段中強制執行。 這些規則一定會生效,即使預設以完全信任執行的組件也一樣。 不過,層級 2 透明度不會影響沒有加上附註的完全信任程式碼,例如桌面應用程式。 使用 SecurityTransparentAttribute 標記而且呼叫使用 SecurityCriticalAttribute 標記之方法的組件 (包括桌面組件) 會收到 MethodAccessException。 您可以套用 SecurityRulesAttribute 並且將 SecurityRulesAttribute.RuleSet 屬性設定為 Level1,藉以變更這個行為。不過,您應該僅針對回溯相容性進行此作業。您必須明確將桌面應用程式標記為安全性透明,才能為它套用透明度限制。
除了執行階段中的編譯器警告以外,呼叫安全性原則 API 的程式碼會收到 NotSupportedException。 您可以使用 <NetFx40_LegacySecurityPolicy> 組態項目來重新啟用原則。 啟用原則時,安全性透明度仍然有效。 安全性原則是在組件載入階段中套用,而且完全不會影響由執行階段強制執行的透明度。
過時的要求使用權限 (RequestMinimum、RequestOptional 和 RequestRefuse) 會收到編譯器警告而且不會在 .NET Framework 4 中運作,但是它們不會導致系統擲回例外狀況。 Deny 要求會導致系統在執行階段中擲回 NotSupportedException。
雖然 LinkDemand 安全性動作沒有過時,不過它不應該用於驗證使用權限。 而是,請針對需要完全信任的型別和方法,使用 SecurityCriticalAttribute,或是針對需要個別使用權限的型別和方法,使用 Demand 方法。
如果您的應用程式是使用 Visual Studio 2010 建置的,您就可以透過在 Visual Studio 專案設定中指定 .NET Framework 4 之前的目標 .NET Framework 版本,執行不含上述變更的應用程式。 不過,您將無法使用新的 .NET Framework 4 型別和成員。 您也可以在應用程式組態檔的啟始設定結構描述中使用 <supportedRuntime> 項目,藉以指定舊版 .NET Framework。
下列章節將討論 .NET Framework 4 中的上述變更和其他變更:
安全性原則簡化
安全性透明度層級 2
過時的使用權限要求
條件式 APTCA
辨識項物件
辨識項集合
安全性原則簡化
從 .NET Framework 4 開始,Common Language Runtime (CLR) 不會為電腦提供安全性原則。 以往,.NET Framework 會提供程式碼存取安全性 (CAS) 原則當做嚴格控制和設定 Managed 程式碼功能的機制。 雖然 CAS 原則的功能很強大,不過它可能很複雜而且限制較多。 此外,CAS 原則不適用於原生應用程式,因此其安全性保證會受到限制。 在 Windows 7 和 Windows Server 2008 R2 上,系統管理員應該尋求 Windows 軟體限制原則 (SRP) (英文) 或 AppLocker (英文) 等作業系統層級解決方案當做 CAS 原則的取代項目。 SRP 和 AppLocker 原則會提供同時適用於 Managed 程式碼和機器碼的簡單信任機制。 就安全性原則解決方案而言,SRP 和 AppLocker 會比 CAS 更簡單而且提供較佳的安全性保證。
在 .NET Framework 4 中,電腦範圍的安全性原則預設為關閉的。 非裝載的應用程式 (亦即,透過 [Windows 檔案總管] 或從命令提示字元執行的應用程式) 現在會以完全信任執行。 這包括位於區域網路之共用上的所有應用程式。 裝載或沙箱應用程式會繼續使用其主機 (例如 Internet Explorer、ClickOnce 或 ASP.NET) 所決定的信任原則來執行。 在沙箱中執行的應用程式或控制項會被視為部分信任的。
為了簡化安全性原則,.NET Framework 已經套用了透明度模型。 使用沙箱所授與之有限使用權限集合在主機或沙箱中執行的應用程式和控制項會被視為透明的。 透明度是指當您正在執行部分信任的應用程式時,不需要顧慮檢查 CAS 原則。 透明應用程式只會使用其授權集來執行。 身為程式設計人員,您的唯一顧慮應該是,應用程式會以其沙箱的授權集為目標,而且它們不會呼叫需要完全信任的程式碼 (安全性關鍵程式碼)。
![]() |
---|
基於上述安全性原則變更,如果您以明確或隱含方式 (透過其他型別和成員) 呼叫過時的 CAS 原則型別與成員,可能會遇到編譯警告與執行階段例外狀況。如需過時型別和成員及其取代項目的清單,請參閱程式碼存取安全性原則相容性和移轉。 您可以透過執行階段設定結構描述中的 <NetFx40_LegacySecurityPolicy> 組態項目選擇使用舊版的 CAS 原則行為,藉以避免警告與錯誤。不過,除非移轉至 .NET Framework 4,否則指定使用舊版的安全性原則不會包括適用於該版本的任何自訂 CAS 原則。 您也可以將 Visual Studio 專案的目標 .NET Framework 版本設定為 .NET Framework 4 之前的版本,藉以啟用舊版的 CAS 原則。這樣就會啟用舊版的 CAS 原則並且包括您針對該版本所指定的任何自訂 CAS 原則。不過,您將無法使用新的 .NET Framework 4 型別和成員。您也可以在啟始設定結構描述中使用 <supportedRuntime> 項目,藉以指定舊版 .NET Framework。 |
回到頁首
安全性透明度層級 2
雖然安全性透明度是 .NET Framework 2.0 版引入的,不過它受到很多限制,而且主要是用來改善程式碼驗證效率。 在 .NET Framework 4 中,透明度是一種強制執行機制,可分隔當做應用程式一部分執行的程式碼與當做基礎結構一部分執行的程式碼。 透明度在可以執行授權事項 (例如呼叫機器碼) 的程式碼 (關鍵程式碼) 和不能執行授權事項的程式碼 (透明程式碼) 之間畫出了一條界線。 透明程式碼可以在其運作範圍的使用權限集合界限內執行命令,但是無法執行、呼叫、衍生自或包含關鍵程式碼。
透明度強制執行的主要目標就是提供一種簡單且有效的機制,以便根據權限隔離不同的程式碼群組。 在沙箱化模型中,這些權限群組為完全信任 (亦即,不受限制) 或部分信任 (亦即,限制為授與沙箱的使用權限集合)。
桌面應用程式會以完全信任執行。因此,它們不會受到透明度模型所影響。 如需安全性透明度變更的詳細資訊,請參閱安全性透明的程式碼,層級 2。
回到頁首
過時的使用權限要求
已經移除強制執行 Deny、RequestMinimum、RequestOptional 和 RequestRefuse 使用權限要求的執行階段支援。 一般而言,這些要求不易理解,而且如果使用不當,就可能會呈現安全性弱點:
Deny 動作可輕易地由 Assert 動作覆寫。 如果某個使用權限位於組件的授權集內,組件中的程式碼就能夠針對該使用權限執行 Assert 動作。 Assert 會防止 Deny 顯示在堆疊上,因而讓它失效。
RequestMinimum 無法在應用程式範圍外部有效地使用。 如果 RequestMinimum 出現在可執行檔 (.exe) 上,而且不符合授權集,則該檔案的使用者就會收到未處理的 FileLoadException 例外狀況,其中不包含如何更正問題的相關資訊。 您無法針對程式庫 (.dll 檔案) 使用單一最低要求集合,因為組件中的不同型別和成員通常具有不同的使用權限需求。
RequestOptional 會造成混淆而且通常使用方式不正確,而產生非預期的結果。 開發人員可輕易地在清單中省略使用權限,卻不了解這樣做表示隱含地拒絕了省略的使用權限。
RequestRefuse 不會提供有效的最低權限模型,因為它會要求您明確識別不想要的使用權限,而非識別所需的使用權限。 此外,如果新的使用權限變成可用,它們就不會包括在清單中。 甚至,對於所有使用權限而言,拒絕沒有意義。 例如,您可能會拒絕 IsolatedStoragePermission 中的 UserQuota 屬性值。
最後,如果您無法識別所有可能有害的使用權限,單獨指定不想要的使用權限可能會產生安全性弱點。
RequestOptional 和 RequestRefuse 可讓開發人員在定義域內部建立多個使用權限集合,藉以中斷同質性定義域。
.NET Framework 4 移除了這些列舉值的執行階段強制執行。 如果組件包含使用這些 SecurityAction 值的屬性,就會繼續載入。不過,CLR 將不會根據使用權限集合拒絕載入參考的組件或修改其授權集。
回到頁首
條件式 APTCA
AllowPartiallyTrustedCallersAttribute (APTCA) 屬性的條件式用法可讓主機識別在載入主機內容的組件中,它們想要對部分信任的呼叫端公開哪些組件。 候選的組件必須已經包含部分信任的設計;也就是說,它們必須是 APTCA (在透明度模型中屬於安全性安全關鍵) 或完全透明的組件。 AllowPartiallyTrustedCallersAttribute 的新建構函式可讓主機在建構函式呼叫中使用 PartialTrustVisibilityLevel 列舉,藉以指定 APTCA 組件的可視性層級。
回到頁首
辨識項物件
在 .NET Framework 4 之前,幾乎所有物件都可以當做辨識項物件使用 (如果裝載程式碼想要將它當做辨識項套用的話)。 例如,某些 .NET Framework 程式碼會將 System.Uri 物件辨識為辨識項。 執行階段會將辨識項物件視為 System.Object 參考,而且不會為它們套用任何型別安全。
因為 .NET Framework 針對可當做辨識項物件使用的型別加諸了隱含的限制,所以這會產生問題。 具體而言,任何當做辨識項使用的物件都必須是可序列化的,而且不得為 null。 如果沒有符合這些需求,每當執行需要其中一項假設的作業時,CLR 就會擲回例外狀況。
為了針對可當做辨識項使用的物件型別啟用條件約束,並且提供將新功能和需求加入至所有辨識項物件的能力,.NET Framework 4 引入了新基底類別 System.Security.Policy.EvidenceBase,而所有辨識項物件都必須衍生自此類別。 一旦執行個體化之後,EvidenceBase 類別就可確保辨識項物件是可序列化的。 此外,未來可以將新的預設實作加入至此基底類別,藉以建立新的辨識項需求。
回溯相容性
由 CLR 當做辨識項物件使用的所有型別都已經在 .NET Framework 4 中更新為衍生自 EvidenceBase。 不過,協力廠商應用程式所使用的自訂辨識項型別是未知的而且無法更新。因此,這些辨識項型別無法搭配預期辨識項衍生自 EvidenceBase 的新成員使用。
回到頁首
辨識項集合
在 .NET Framework 4 之前,當載入組件時,CLR 就會產生套用至此組件的完整辨識項物件集合。 這些物件會儲存在清單中,然後消費者就會逐一查看此清單來尋找特定物件。 因此,不論是否要使用,所有辨識項都是可用的。 對於大部分辨識項物件而言,這個行為不是問題。不過,對於 System.Security.Policy.Publisher (需要 Authenticode 驗證) 等辨識項物件而言,這個行為沒有效率。
為了改善這個行為,.NET Framework 4 已經重新設計了與辨識項集合互動的方式。 辨識項集合現在的行為方式如同字典,而非清單。 消費者現在可以要求特定的辨識項型別,然後集合就會傳回辨識項 (如果找到的話),而非逐一查看辨識項集合來查看所需的辨識項物件是否存在。 例如,如果 StrongName 物件存在,StrongName name = evidence.GetHostEvidence<StrongName>(); 呼叫就會傳回此物件,否則它會傳回 null。
這個字典模型會延遲產生辨識項物件,直到系統要求它們為止。 在 Publisher 辨識項範例中,驗證組件之 Authenticode 簽章的效能額外負荷會延遲到需要該項資訊為止。 在最常見的情況中,若為不需要 Publisher 辨識項的完全信任應用程式,就會完全避免驗證程序。
回到頁首