Crear una evidencia de seguridad personalizada

La seguridad del framework esta basada en evidencias de seguridad que le dicen al engine de seguridad como procesar los permisos disponibles dentro del dominio del ensamblado. Hay dos niveles de evidencias de seguridad dentro del framework, a nivel del dominio de aplicación que se puede consultar con la propiedad AppDomain.Evidence que esta en System.AppDomain.CurrentDomain.Evidence y a través de cada uno de los ensamblados que hay cargardos, en System.Reflection.Assembly.Evidence.

Hay una serie de clases que vienen con el framework que se utilizan como evidencias:

  • Application directory, el directorio donde esta la aplicación
  • Hash, un hash criptografico de SH1
  • Publisher, certificado de la entidad que publica el software
  • Site, sitiode origen del sitio como http://www.luisguerrero.net/
  • Strong name, nombre seguro utilizado.
  • Url, url de origen
  • Zone, zona de origen.

Si se hiciera un símil con la vida real, la evidencia de seguridad es algo así como de donde venidos y quien somos o como vamos vestidos. Imaginemos por un momento que queremos entrar a un bar, si hiciéramos un símil con el sistema de seguridad, el bar es el recurso al cual nosotros queremos acceder, el portero es el engine de seguridad y nosotros somos el método que queremos acceder a ese recurso. El portero tiene una política de seguridad por la cual si se encuentra con una función (persona) que intenta acceder al sistema (bar) pero está vestido con zapatillas (evidencia) no le permita el acceso, lo deniegue (Deny). Las políticas de seguridad asocian evidencias de seguridad con permisos específicos, o grupos de permisos.

Imaginemos por un momento que queremos estamos definiendo el sistema de seguridad de nuestra aplicación y vamos a cargar una serie de ensamblados de terceros, que representan un sistema de plugins para nuestra aplicación. Nosotros queremos controlar el acceso a los recursos en base a unas determinadas evidencias de seguridad que los ensamblados que cargamos llevan implícitas. Las evidencias que el framework nos proporciona no son suficientes para definir esta seguridad personaliza así que necesitamos definir nuestras propias evidencias de seguridad.

Creando evidencias personalizadas

No hay ninguna clase de la que debamos derivar si queremos crear nuestra evidencia personalizada sino que hay que seguir una serie de reglas para que la evidencias sea efectiva.

  • Haz la evidencia sencilla. Las clases que representan la evidencia tiene que ser simples, tienen que representar una pieza de información, algo muy concreto. Cuanto más complejo sea la evidencia más compleja será la manera de usarla.
  • Haz la evidencia liguera. Cuando el runtime carga un ensamblado, carga también las evidencias que contiene el ensamblado y estas están disponibles durante la ejecución de la aplicación o hasta que el dominio de aplicación se descarga (es la única manera de descargar ensamblados), así que es importante hacer la evidencia simple y ligera para que no ralentice la carga del ensamblado.
  • Haz la evidencia serializable. Las evidencias se serializan en binario y se introducen como metadatos dentó del ensamblado, así que si la evidencia es sencilla no necesitarás una seralización personalizada, así que marcarlo con el atributo System.SerializableAttribute, sino habrá que hacer una serialización personalizada a través de la implementación de la interfaz System.Runtime.Serialization.ISerializable.
  • Haz la evidencia sellada (sealed). Si la evidencia no está sellada (sealed in C#), un atacante puede derivar de tu evidencia y modificarla. Todas las evidencias vistas hasta ahora del framework lo están.
  • No asumas valores predeterminados. Cuando definas la evidencia nunca la inicialices con valores predeterminados pues estarás asumiendo unos valores que después se utilizarán en el engine de seguridad del framework lo que puede conllevar un riesgo para la seguridad.
  • Haz la evidencia inmutable. Una vez que se crea la evidencia, de esto es encargado el cargador de ensablamdos, la referencia y los valores de la evidencia no pueden ser modificados porque si lo hicieran estos valores son justamente los que se utilizan para controlar la seguridad.
  • Sobrescribe ToString(). Todas las evidencias tienes que sobrescribir el método ToString para generar un representación de si misma en XML.
  • Genera permisos de identidad. Puedes implementar la interfaz System.Security.Policy.IIdentityPermissionfactory para calcular los permisos que tienes a través de la evidencia de seguridad.

Una vez sabido esto vamos a definir una evidencia personalizada llamada Autor. Esta evidencia personalizada va a contener el nombre del autor que ha generado el ensamblado para después permitir al ensamblado acceder a determinadas partes del sistema.

La definición de la clase sería así

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Security;
   6: using System.Reflection;
   7:  
   8: [assembly: AssemblyKeyFile("Key.snk")]
   9: [assembly: AssemblyVersion("1.0.0.0")]
  10:  
  11: namespace ConsoleApplication1
  12: {
  13:     
  14:  
  15:     [Serializable]
  16:     public sealed class Autor
  17:     {
  18:         private readonly string autorNombre = string.Empty;
  19:  
  20:         public string AutorNombre
  21:         {
  22:             get { return autorNombre; }
  23:         } 
  24:  
  25:         public Autor(string nombre)
  26:         {
  27:             if (string.IsNullOrEmpty(nombre))
  28:             {
  29:                 throw new ArgumentException("Nombre no peude ser nulo o vacio", new NullReferenceException());
  30:             }
  31:             else
  32:             {
  33:                 this.autorNombre = nombre;
  34:             }
  35:         }
  36:         public override string ToString()
  37:         {
  38:             SecurityElement elemt = new SecurityElement(GetType().FullName);
  39:             elemt.AddAttribute("Version", "1");
  40:             if (!string.IsNullOrEmpty(autorNombre))
  41:             {
  42:                 elemt.AddChild(new SecurityElement("Autor", autorNombre));
  43:             }
  44:             return elemt.ToString();
  45:         }
  46:     }
  47: }

Una vez que se tiene definido la evidencia esta hay que usarla dentro de los ensamblados. Para poder usar la evidencia dentro dentro de un ensamblado hay que hacer una serie de pasos previos para poder usar la evidencia.

El proceso para usar la evidencia sería el siguiente:

  • Crear una colección de evidencias.
  • Crear el objeto que se quiere añadir a la colección de evidencias.
  • Añadir las evidencias a la colección de evidencias usando el método AddAssembly
  • Serializar la colección de evidencias con un serializador binario.
  • Compilar el código como un modulo y no como un ensamblado, a través del modificador del compilador /target:module
  • Combinar los modulos y las envidencias dentro de un ensamblado a través de la herramienta al.exe Assembly Linker.

Para poder hacer eso hay que tener en cuenta que en ensamblado donde se referencia la evidencia tiene que ser de confianza total para el sistema, eso se puede conseguir añadiéndolo a la GAC, o a través de los siguiente comandos de caspol.

  • caspol –user –addfulltrust Autor.dll
  • caspol –machine –addfullturst Autor.dll
  • caspol –enterprise –addfulltrust Autor.dll

Una vez hecho esto hay que serializar una instancia de la evidencia para usarla.

   1: static void Main(string[] args)
   2: {
   3:     Evidence evidence = new Evidence();
   4:  
   5:     Autor autor = new Autor("Luis");
   6:  
   7:     evidence.AddAssembly(autor);
   8:  
   9:     string fileName = autor.AutorNombre + ".evidence";
  10:  
  11:     BinaryFormatter bf = new BinaryFormatter();
  12:     FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
  13:     bf.Serialize(fs, evidence);
  14:     fs.Dispose();
  15:  
  16: }

Conseguido esto ahora hay que combinar un modulo de un ensamblado con la evidencia previamente generada. Para ello tenemos que ejecutar esta herramienta intermedia que genere el fichero .evidence que incluiremos en el ensamblado que queremos usar.

Después con la herramienta al.exe hay que combinarlos todos.

   1: al /target:exe /out:ejemplo.exe /main:Ejemplo.Main /evidence:Luis.evidence Ejemplo.netmodule 

 

    Una vez creado esto lo que tenemos que hacer es simplemente crear una politica que utilice esta evidencia de seguridad en nuestro sistema.

     

    Saludos. Luis.

    Deja un comentario

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *