CA2107:必須檢視 Deny 和 Permit Only 的使用方式
型別名稱 |
ReviewDenyAndPermitOnlyUsage |
CheckId |
CA2107 |
分類 |
Microsoft.Security |
中斷變更 |
中斷 |
方法會包含指定 PermitOnly 或 Deny 安全性動作的安全性檢查。
只有相當了解 .NET Framework 安全性的人員才能執行 使用 PermitOnly 方法 和 CodeAccessPermission.Deny 安全性動作。而使用這些安全性動作的程式碼應該接受安全性檢閱。
Deny 會更改堆疊查核行程為了回應安全性需求而發生的預設行為。不論呼叫堆疊中呼叫端的實際使用權限為何,它可以讓您指定在 Deny 方法期間絕對不能授與的使用權限。如果堆疊查核行程偵測到受到 Deny 保護的方法,以及要求的使用權限已併入拒絕的使用權限中,則堆疊查核行程會失敗。PermitOnly 也會更改堆疊查核行程的預設行為。不論呼叫端的使用權限為何,它可以讓程式碼指定能夠授與的使用權限範圍。如果堆疊查核行程偵測到受到 PermitOnly 保護的方法,以及要求的使用權限未併入 PermitOnly 所指定的使用權限中,則堆疊查核行程會失敗。
您應該仔細評估會依賴這些動作的程式碼,以找出因它有限用處和難以預測之行為所產生的安全性弱點。請考慮下列事項:
連結要求不會受到 Deny 或 PermitOnly 的影響。
如果 Deny 或 PermitOnly 與導致堆疊查核行程的要求會出現在同一堆疊框架 (Stack Frame) 中,則安全性動作不會有任何作用。
用於建構以路徑為基礎之使用權限的值通常可以利用多種方法指定。拒絕存取某一形式的路徑,並不表示會拒絕存取所有形式的路徑。例如,如果檔案共用對應至網路磁碟 X: 的 \\Server\Share,若要拒絕存取共用上的檔案,則您必須拒絕 \\Server\Share\File、X:\File,以及所有會存取檔案的路徑。
CodeAccessPermission.Assert 可以在到達 Deny 或 PermitOnly 之前,終止堆疊查核行程。
如果 Deny 有任何作用,也就是說,當呼叫端具有 Deny 封鎖的使用權限時,呼叫端可以略過 Deny 直接存取受保護的資源。同樣地,如果呼叫端沒有拒絕的使用權限,則堆疊查核行程將會因為沒有 Deny 方法而失敗。
任何使用這些安全性動作都將導致違規。若要修正違規,請勿使用這些安全性動作。
只有在完成安全性檢閱後,才能隱藏這項規則的警告。
下列範例為 Deny 的某些限制。
下列程式庫包含一個類別,其中有兩個相同的方法,但保護它們的安全性要求卻不同。
using System.Security;
using System.Security.Permissions;
using System;
namespace SecurityRulesLibrary
{
public class SomeSecuredMethods
{
// Demand immediate caller has suitable permission
// before revealing sensitive data.
[EnvironmentPermissionAttribute(SecurityAction.LinkDemand,
Read="COMPUTERNAME;USERNAME;USERDOMAIN")]
public static void MethodProtectedByLinkDemand()
{
Console.Write("LinkDemand: ");
}
[EnvironmentPermissionAttribute(SecurityAction.Demand,
Read="COMPUTERNAME;USERNAME;USERDOMAIN")]
public static void MethodProtectedByDemand()
{
Console.Write("Demand: ");
}
}
}
下列應用程式會示範 Deny 對程式庫中受保護之方法所產生的作用。
using System.Security;
using System.Security.Permissions;
using System;
using SecurityRulesLibrary;
namespace TestSecurityLibrary
{
// Violates rule: ReviewDenyAndPermitOnlyUsage.
public class TestPermitAndDeny
{
public static void TestAssertAndDeny()
{
EnvironmentPermission envPermission = new EnvironmentPermission(
EnvironmentPermissionAccess.Read,
"COMPUTERNAME;USERNAME;USERDOMAIN");
envPermission.Assert();
try
{
SomeSecuredMethods.MethodProtectedByDemand();
Console.WriteLine(
"Caller's Deny has no effect on Demand " +
"with the asserted permission.");
SomeSecuredMethods.MethodProtectedByLinkDemand();
Console.WriteLine(
"Caller's Deny has no effect on LinkDemand " +
"with the asserted permission.");
}
catch (SecurityException e)
{
Console.WriteLine(
"Caller's Deny protected the library.{0}", e);
}
}
public static void TestDenyAndLinkDemand()
{
try
{
SomeSecuredMethods.MethodProtectedByLinkDemand();
Console.WriteLine(
"Caller's Deny has no effect with " +
"LinkDemand-protected code.");
}
catch (SecurityException e)
{
Console.WriteLine(
"Caller's Deny protected the library.{0}",e);
}
}
public static void Main()
{
EnvironmentPermission envPermission = new EnvironmentPermission(
EnvironmentPermissionAccess.Read,
"COMPUTERNAME;USERNAME;USERDOMAIN");
envPermission.Deny();
//Test Deny and Assert interaction for LinkDemands and Demands.
TestAssertAndDeny();
//Test Deny's effects on code in different stack frame.
TestDenyAndLinkDemand();
//Test Deny's effect on code in same frame as deny.
try
{
SomeSecuredMethods.MethodProtectedByLinkDemand();
Console.WriteLine(
"This Deny has no effect with LinkDemand-protected code.");
}
catch (SecurityException e)
{
Console.WriteLine("This Deny protected the library.{0}",e);
}
}
}
}
這個範例產生下列輸出。