CA2107: Deny と PermitOnly の用法を再確認します
TypeName |
ReviewDenyAndPermitOnlyUsage |
CheckId |
CA2107 |
[カテゴリ] |
Microsoft.Security |
互換性に影響する変更点 |
あり |
原因
メソッドに、PermitOnly または Deny のセキュリティ アクションを指定したセキュリティ チェックが含まれます。
規則の説明
PermitOnly メソッドの使用 と CodeAccessPermission.Deny のセキュリティ アクションは、.NET Framework のセキュリティについて高度な知識を持っているユーザー以外は使用しないでください。コードにこのセキュリティ アクションを使用する場合、セキュリティを再確認する必要があります。
Deny によって、セキュリティ要求に応答して発生するスタック ウォークの既定の動作は変更されます。これによって、コール スタックの呼び出し元が持つ実際のアクセス許可にかかわらず、拒否するメソッドが存続する間、認めることができないというアクセス許可を指定できるようになります。スタック ウォークが Deny で保護されたメソッドを検出した場合、および要求されたアクセス許可が拒否されたアクセス許可に含まれる場合、スタック ウォークは失敗します。PermitOnly でも、スタック ウォークの既定の動作は変更されます。これで、呼び出し元のアクセス許可にかかわらず、付与することができるアクセス許可のみを指定できるようになります。スタック ウォークが PermitOnly で保護されたメソッドを検出した場合、および要求されたアクセス許可が PermitOnly で指定されたアクセス許可に含まれていない場合、スタック ウォークは失敗します。
コードがこれらのアクションに依存している場合、実用性が制限され、動作がわかりづらくなるため、セキュリティ上の脆弱性を慎重に検査する必要があります。次に例を示します。
リンク確認要求は、Deny または PermitOnly に影響を受けません。
Deny または PermitOnly が、スタック ウォークを実行する要求と同じスタック フレームで発生した場合、セキュリティのアクションによる影響はありません。
通常、パスに基づくアクセス許可を構築するときに使用する値を指定するには、複数の方法があります。あるフォームのパスに対するアクセスを拒否することで、すべてのフォームに対するアクセスが拒否されることはありません。たとえば、ファイル共有 \\Server\Share がネットワーク ドライブ X: にマップされている場合、その共有上にあるファイルへのアクセスを拒否するには、\\Server\Share\File、X:\File など、そのファイルにアクセスするすべてのパスに拒否を設定する必要があります。
スタック ウォークが Deny または PermitOnly が検出される前に、CodeAccessPermission.Assert でスタック ウォークを停止できます。
Deny による影響がある場合、つまり、呼び出し元が持つアクセス許可が Deny でブロックされる場合、呼び出し元は、Deny を経由せずに、保護されたリソースに直接アクセスできます。同様に、呼び出し元が拒否されたアクセス許可を持っていない場合、スタック ウォークは Deny がなくても失敗します。
違反の修正方法
これらのセキュリティ アクションのいずれかを使用すると、違反になります。違反を修正するには、これらのセキュリティ アクションを使用しないでください。
警告を抑制する状況
必ずセキュリティの再確認を完了してから、この規則による警告を抑制してください。
使用例
次の例では、Deny の制限について表しています。
次のライブラリには、2 つのメソッドを持つクラスが含まれています。これらのメソッドは、保護のセキュリティ要求がある点以外は同じです。
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);
}
}
}
}
この例を実行すると、次の出力が生成されます。
参照
関連項目
CodeAccessPermission.PermitOnly