安全性透明的程式碼不應該參考非公用的安全性關鍵成員
更新:2007 年 11 月
型別名稱 |
SecurityTransparentCodeShouldNotReferenceNonpublicSecurityCriticalCode |
CheckId |
CA2129 |
分類 |
Microsoft.Security |
中斷變更 |
中斷 |
原因
以 SecurityTransparentAttribute 標記的方法會呼叫標記為 SecurityCritical 的非公用成員。SecurityTransparent 是方法的預設指定。
規則描述
.NET Framework 2.0 引入一項名為「透明度」的功能。個別方法、欄位、介面、類別和型別可以是透明或關鍵項目。
不能使用透明程式碼來評估安全性權限。因此,其已授與或要求的任何使用權限都會自動透過程式碼傳遞至呼叫端或主機 AppDomain。權限升級的範例包括 Assert、LinkDemand、SuppressUnmanagedCode 以及 Unsafe 程式碼。
將透明和關鍵程式碼分開的目的是為了簡化安全性稽核程序。為了顧及惡意與未受信任之公開使用的可能性,一般都會對公用進入點 (Entry) 執行稽核。透過將組件 (Assembly) 的較小區段標記為關鍵區段 (Critical Section),安全性稽核即可減少為公用進入點以及提高權限的程式碼安全性關鍵區段。不過,為了確保稽核的正確與完整,必須盡可能強化透明和關鍵程式碼間的界限。另一個方法是允許透明程式碼呼叫內部安全性關鍵程式碼,但透明程式碼必須進行更嚴謹的稽核。
在執行階段,Common Language Runtime Just-in-Time 編譯器 (Compiler) 會檢查透明程式碼是否參考或呼叫非公用安全性關鍵程式碼。如果透明程式碼呼叫了非公用關鍵程式碼,便會擲回例外狀況,例如 MethodAccessException。這種狀況的處理方式與嘗試存取其他類別之私用 (Private) 成員的類別類似。
這個程式碼分析規則會分析混合透明/關鍵之組件中的所有方法和型別。如果從透明程式碼對非公用關鍵程式碼所做的任何呼叫未標記 SecurityTreatAsSafe,這項規則也會將這些呼叫加上標幟。
如何修正違規
若要解決這個問題,請將呼叫非公用 SecurityCritical 程式碼的程式碼標記為 SecurityCritical,或是將目標方法/型別標記為 SecurityTreatAsSafe。如此便可有效地將程式碼視為安全公用項目,並加以稽核,以防範惡意的目的。
隱藏警告的時機
請勿隱藏此規則的訊息。
範例
下列程式碼會因為 SecondSecurityMethod 是私用的且為 SecurityCritical 而失敗。若以安全性問題為例,SecondSecurityMethod 中的 Assert 將會造成有權限的動作和呼叫中的完整要求無法流入 FirstSecurityMethod,而只能進行在呼叫端執行的安全性檢查。
using System;
using System.Security.Permissions;
namespace SecurityTestClassLibrary
{
public class SecurityTestClass
{
// SecurityTransparent
public void FirstSecurityMethod()
{
SecondSecurityMethod();
}
[System.Security.SecurityCritical]
private void SecondSecurityMethod()
{
// Assert permissions
// do privileged actions, such as method call-outs
}
}
}
如果未強制套用透明/關鍵的界限,FirstSecurityMethod 將可在不經安全性檢查的情形下執行所有的 SecondSecurityMethod 動作。
其中一個選擇是檢閱該方法的程式碼,如果認為該方法可安全升級無虞,而且不會遭受惡意攻擊,請將它標記為 SecurityTreatAsSafe。
using System;
using System.Security.Permissions;
namespace SecurityTestClassLibrary
{
public class SecurityTestClass
{
// SecurityTransparent
public void FirstSecurityMethod()
{
SecondSecurityMethod();
}
[System.Security.SecurityTreatAsSafe]
[System.Security.SecurityCritical]
private void SecondSecurityMethod()
{
// Assert permissions
// do privileged actions, such as method call-outs
}
}
}
另外一個選擇是將 Method1 也變成 Critical。這可擴大組件的關鍵核心 (Kernel) 並增加安全性稽核的規模。此外,它也可保證執行的是適當的威脅模型和程式碼流程分析。
using System;
using System.Security.Permissions;
namespace SecurityTestClassLibrary
{
public class SecurityTestClass
{
[System.Security.SecurityCritical]
public void FirstSecurityMethod()
{
SecondSecurityMethod();
}
[System.Security.SecurityCritical]
private void SecondSecurityMethod()
{
// Assert permissions
// do privileged actions, such as method call-outs
}
}
}