Aptca methods should only call aptca methods

TypeName

AptcaMethodsShouldOnlyCallAptcaMethods

CheckId

CA2116

Category

Microsoft.Security

Breaking Change

Breaking

Cause

A method in an assembly with the System.Security.AllowPartiallyTrustedCallersAttribute attribute calls a method in an assembly that does not have the attribute.

Rule Description

By default, public or protected methods in assemblies with strong names are implicitly protected by a Link Demands for full trust; only fully trusted callers can access a strong-named assembly. Strong-named assemblies marked with the AllowPartiallyTrustedCallersAttribute (APTCA) attribute do not have this protection. The attribute disables the link demand, making the assembly accessible to callers that do not have full trust, such as code executing from an intranet or the Internet.

When the APTCA attribute is present on a fully trusted assembly, and the assembly executes code in another assembly that does not allow partially trusted callers, a security exploit is possible. If two methods M1 and M2 meet the following conditions, malicious callers can use the method M1 to bypass the implicit full trust link demand that protects M2:

  • M1 is a public method declared in a fully trusted assembly that has the APTCA attribute.

  • M1 calls a method M2 outside M1's assembly.

  • M2's assembly does not have the APTCA attribute and, therefore, should not be executed by or on behalf of callers that are partially trusted.

A partially trusted caller X can call method M1, causing M1 to call M2. Because M2 does not have the APTCA attribute, its immediate caller (M1) must satisfy a link demand for full trust; M1 has full trust and therefore satisfies this check. The security risk is because X does not participate in satisfying the link demand that protects M2 from untrusted callers. Therefore, methods with the APTCA attribute must not call methods that do not have the attribute.

How to Fix Violations

If the APCTA attribute is required, use a Data Access to protect the method that calls into the full trust assembly. The exact permissions you demand will depend on the functionality exposed by your method. If it is possible, protect the method with a demand for full trust to ensure that the underlying functionality is not exposed to partially trusted callers. If this is not possible, select a set of permissions that effectively protects the exposed functionality.

When to Exclude Warnings

To safely exclude a warning from this rule, you must ensure that the functionality exposed by your method does not directly or indirectly allow callers to access sensitive information, operations, or resources that can be used in a destructive manner.

Example

The following example uses two assemblies and a test application to illustrate the security vulnerability detected by this rule. The first assembly does not have the APTCA attribute and should not be accessible to partially trusted callers (represented by M2 in the previous discussion).

using System;
using System.Security;
using System.Security.Permissions;
using System.Reflection;

// This code is compiled into a strong-named
// assembly that requires full trust and does 
// not allow partially trusted callers. 

namespace AptcaTestLibrary
{
   public class ClassRequiringFullTrust
   {
      public static void DoWork()
      {
        Console.WriteLine("ClassRequiringFullTrust.DoWork was called.");
      }
   }
}

The second assembly is fully trusted and allows partially trusted callers (represented by M1 in the previous discussion).

using System;
using System.Security;
using System.Security.Permissions;
using System.Reflection;

// This assembly executes with full trust and 
// allows partially trusted callers. 

[assembly:AllowPartiallyTrustedCallers]  

namespace AptcaTestLibrary
{
   public class AccessAClassRequiringFullTrust
   {
      public static void Access()
      {    
         // This security check fails if the caller 
         // does not have full trust. 
         NamedPermissionSet pset= new NamedPermissionSet("FullTrust");

         // This try-catch block shows the caller's permissions.
         // Correct code would either not catch the exception,
         // or would rethrow it.
         try 
         {
            pset.Demand();
         }
         catch (SecurityException e)
         {
            Console.WriteLine("Demand for full trust:{0}", e.Message);
         }
         // Call the type that requires full trust.
         // Violates rule AptcaMethodsShouldOnlyCallAptcaMethods.
         ClassRequiringFullTrust.DoWork();
     }
   }
}

The test application (represented by X in the previous discussion) is partially trusted.

using System;
using AptcaTestLibrary;

// If this test is run from the local computer, it gets full trust by default.
// Remove full trust.
[assembly:System.Security.Permissions.PermissionSetAttribute(
   System.Security.Permissions.SecurityAction.RequestRefuse, Name="FullTrust")]

namespace TestSecLibrary
{
   class TestApctaMethodRule
   {
      public static void Main()
      {
          // Indirectly calls DoWork in the full-trust class.
          ClassRequiringFullTrust a = new ClassRequiringFullTrust();
          a.Access();
      }
   }
}

This example produces the following output.

Output

Demand for full trust:Request failed.
ClassRequiringFullTrust.DoWork was called.

Aptca types should only extend aptca base types

See Also

Concepts

.NET Framework Assemblies Marked with AllowPartiallyTrustedCallersAttribute
Using Libraries from Partially Trusted Code
Link Demands

Other Resources

Secure Coding Guidelines
Data Access