CA2117: Los tipos APTCA solo amplían tipos base APTCA

Elemento Valor
RuleId CA2117
Category Microsoft.Security
Cambio importante Problemático

Causa

Un tipo público o protegido en un ensamblado con el atributo System.Security.AllowPartiallyTrustedCallersAttribute hereda de un tipo declarado en un ensamblado que no tiene el atributo.

Nota

Esta regla está en desuso. Para más información, consulte Reglas en desuso.

Descripción de la regla

De forma predeterminada, los tipos públicos o protegidos en ensamblados con nombres seguros están protegidos implícitamente por un elemento InheritanceDemand para plena confianza. Los ensamblados con nombre seguro marcados con el atributo AllowPartiallyTrustedCallersAttribute (APTCA) no tienen esta protección. El atributo deshabilita la demanda de herencia. Los tipos expuestos declarados en un ensamblado sin una demanda de herencia son heredables por tipos que no tienen plena confianza.

Si está presente el atributo APTCA en un ensamblado de plena confianza y un tipo del ensamblado se hereda de otro que permite llamadores parcialmente confiables, se puede producir un ataque de seguridad. Si dos tipos T1 y T2 cumplen las siguientes condiciones, los autores de llamadas malintencionados pueden usar el tipo T1 para omitir la petición implícita de herencia de plena confianza que protege T2:

  • T1 es un tipo público declarado en un ensamblado de plena confianza que tiene el atributo APTCA.

  • T1 hereda de un tipo T2 fuera de su ensamblado.

  • El ensamblado de T2 no tiene el atributo APTCA y, por lo tanto, los tipos de ensamblados de confianza parcial no deben heredarlo.

Un tipo X de confianza parcial puede heredar de T1, lo que le da acceso a los miembros heredados declarados en T2. Dado que T2 no tiene el atributo APTCA, su tipo derivado inmediato (T1) debe satisfacer una demanda de herencia de plena confianza; T1 tiene plena confianza y, por lo tanto, cumple este requisito. El riesgo de seguridad se debe a que X no participa a la hora de satisfacer la petición de herencia que protege T2 de las subclases que no son de confianza. Por este motivo, los tipos con el atributo APTCA no deben extender los tipos que no tienen el atributo.

Otro problema de seguridad, y quizás uno más común, es que el tipo derivado (T1) puede, a través del error del programador, exponer miembros protegidos del tipo que requiere plena confianza (T2). Cuando se produce esta exposición, los autores de llamadas que no son de confianza obtienen acceso a la información que solo debe estar disponible para tipos de plena confianza.

Cómo corregir infracciones

Si el tipo notificado por la infracción está en un ensamblado que no requiere el atributo APTCA, quítelo.

Si se requiere el atributo APTCA, agregue al tipo una demanda de herencia para plena confianza. La demanda de herencia protege contra la herencia por tipos que no son de confianza.

Es posible corregir una infracción agregando el atributo APTCA a los ensamblados de los tipos base notificados por la infracción. No haga esto sin realizar primero una revisión de seguridad intensiva de todo el código de los ensamblados y todo el código que depende de los ensamblados.

Cuándo suprimir las advertencias

Para suprimir de forma segura una advertencia de esta regla, debe asegurarse de que los miembros protegidos expuestos por el tipo no permitan directa ni indirectamente a los autores de llamadas que no son de confianza acceder a información, operaciones o recursos confidenciales que se puedan usar de forma destructiva.

Ejemplo

En el ejemplo siguiente se usan dos ensamblados y una aplicación de prueba para ilustrar la vulnerabilidad de seguridad detectada por esta regla. El primer ensamblado no tiene el atributo APTCA y no debe ser heredable por los tipos de confianza parcial (representados por T2 en el análisis anterior).

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. 

namespace AptcaTestLibrary
{
   public class ClassRequiringFullTrustWhenInherited
   {
      // This field should be overridable by fully trusted derived types.
      protected static string location = "shady glen";
     
      // A trusted type can see the data, but cannot change it.
      public virtual string TrustedLocation 
      {
         get 
         {
            return location;
         }
      }
   }
}

El segundo ensamblado, representado por T1 en el análisis anterior, es de confianza parcial y permite autores de llamadas de confianza parcial.

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

// This class is compiled into an assembly that executes with full 
// trust and allows partially trusted callers. 

// Violates rule: AptcaTypesShouldOnlyExtendAptcaBaseTypes.

namespace AptcaTestLibrary
{
   public class InheritAClassRequiringFullTrust: 
      ClassRequiringFullTrustWhenInherited
   {
      private DateTime meetingDay = DateTime.Parse("February 22 2003");

      public override string ToString() 
      {
         // Another error:
         // This method gives untrusted callers the value 
         // of TrustedLocation. This information should 
         // only be seen by trusted callers.
         string s = String.Format(
            "Meet at the {0} {1}!", 
            this.TrustedLocation, meetingDay.ToString());
         return s;
      }
   }
}

El tipo de prueba, representado por X en el análisis anterior, se encuentra en un ensamblado de confianza parcial.

using System;
using AptcaTestLibrary;

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

namespace TestSecLibrary
{
    class InheritFromAFullTrustDecendent : ClassRequiringFullTrust
    {
        public InheritFromAFullTrustDecendent()
        {
            // This constructor maliciously overwrites the protected 
            // static member in the fully trusted class.
            // Trusted types will now get the wrong information from 
            // the TrustedLocation property.
            InheritFromAFullTrustDecendent.location = "sunny meadow";
        }

        public override string ToString()
        {
            return InheritFromAFullTrustDecendent.location;
        }
    }

    class TestApctaInheritRule
    {
        public static void Main()
        {
            ClassRequiringFullTrust iclass =
               new ClassRequiringFullTrust();
            Console.WriteLine(iclass.ToString());

            // You cannot create a type that inherits from the full trust type
            // directly, but you can create a type that inherits from 
            // the APTCA type which in turn inherits from the full trust type.

            InheritFromAFullTrustDecendent inherit =
               new InheritFromAFullTrustDecendent();
            //Show the inherited protected member has changed.
            Console.WriteLine("From Test: {0}", inherit.ToString());

            // Trusted types now get the wrong information from 
            // the TrustedLocation property.
            Console.WriteLine(iclass.ToString());
        }
    }
}

Este ejemplo produce el siguiente resultado:

Meet at the shady glen 2/22/2003 12:00:00 AM!
From Test: sunny meadow
Meet at the sunny meadow 2/22/2003 12:00:00 AM!

CA2116: Los métodos APTCA deben llamar solo a métodos APTCA

Consulte también