c# - una - ¿Es seguro llamar a Type.GetType con un nombre de tipo que no es de confianza?
no se puede cargar el archivo o ensamblado net standard (3)
Me encontré con lo siguiente en una revisión de código:
Type type = Type.GetType(typeName);
if (type == typeof(SomeKnownType))
DoSomething(...); // does not use type or typeName
typeName
origina a partir de una solicitud AJAX y no se valida. ¿Esto plantea algún problema de seguridad potencial? Por ejemplo, ¿es posible que se ejecute un código inesperado, o que se bloquee toda la aplicación (denegación de servicio), como resultado de la carga de tipos arbitrarios desde conjuntos arbitrarios?
(Supongo que un bromista podría intentar agotar la memoria disponible cargando cada tipo de cada ensamblaje en el GAC. ¿Algo peor?)
Notas:
- Esta es una aplicación ASP.NET que se ejecuta bajo Full Trust.
- El
type
resultante solo se usa como se muestra arriba. No se hace ningún intento de instanciar el tipo.
No hay peligro hereditario al referirse al tipo en sí. La confianza en .NET está en el nivel de ensamblaje. Si no hay ningún ensamblaje disponible que contenga el tipo especificado, su llamada solo devolverá un nulo. En consecuencia, alguien tiene que hacer que el ensamblaje esté disponible para el código; los ensamblajes no aparecen simplemente de la nada.
No, esto no es seguro en absoluto. Type.GetType cargará un ensamblaje si no se ha cargado antes:
GetType provoca la carga del ensamblado especificado en typeName.
Entonces, ¿qué hay de malo en cargar un conjunto? Además de usar memoria adicional como señala Daniel, los ensamblados .NET pueden ejecutar código cuando se cargan, aunque esta funcionalidad no está expuesta a compiladores normales como C # y VB.NET. Estos se llaman inicializadores de módulo .
El método de inicialización del módulo se ejecuta en, o en algún momento antes, el primer acceso a cualquier tipo, método o datos definidos en el módulo.
El solo hecho de que esté cargando un ensamblaje y examinando sus tipos es suficiente para ejecutar el inicializador del módulo.
Alguien con un ensamblaje escrito de manera inteligente (por ejemplo, usando ilasm y escribiendo MSIL sin formato) puede ejecutar el código simplemente cargando el ensamblaje y usted examinando los tipos. Es por eso que tenemos Assembly.ReflectionOnlyLoad , para que podamos cargar el ensamblaje de forma segura en un entorno no ejecutable.
Pensé un poco más en esto y pensé en algunos casos más.
Tenga en cuenta que su grupo de aplicaciones está configurado para ejecutarse en 64 bits. Ahora imagine que su atacante usa el servicio AJAX para intentar cargar un ensamblaje que es estrictamente solo para la arquitectura x86. Por ejemplo, hay una en mi GAC llamada Microsoft.SqlServer.Replication que es solo x86, no hay contraparte AMD64. Si le pido a su servicio que cargue ese ensamblaje, obtendría una BadImageFormatException
. Dependiendo de las cláusulas de protección que tenga en su lugar para cargar el ensamblaje, las excepciones no manejadas podrían derribar completamente su AppPool .
Podría consumir memoria potencialmente si las bibliotecas no están en la memoria.
Tendría un Dictionary<string, Type>
como una lista permitida.
var whitelist = new Dictionary<string, Type>;
whitelist.Add("MyType", typeof(MyType));