c# .net

c# - Cómo prevenir la falsificación de DLL en.NET



(2)

Tengo una aplicación .NET que hace referencia a una DLL administrada.

Esta DLL contiene una clase, digamos ScoreKeeper que implementa un método llamado GetHighScore() . La aplicación llama a esto periódicamente.

¿Hay alguna manera de evitar que la aplicación .NET use una DLL "no autorizada" aquí en lugar de la que estoy suministrando?


Mencionas:

Esta DLL contiene una clase, digamos ScoreKeeper que implementa un método llamado GetHighScore (). La aplicación llama a esto periódicamente.

Y entonces:

¿Hay alguna manera de evitar que la aplicación .NET use una DLL "no autorizada" aquí en lugar de la que estoy suministrando?

Suponiendo que desea evitar que alguien intercambie el conjunto que ha proporcionado con un conjunto propio que tiene el mismo nombre y tipo (que está en el mismo espacio de nombres), puede aplicar un nombre ScoreKeeper al conjunto que contiene el ScoreKeeper Clase y haz que tus consumidores hagan referencia a eso.

Sin embargo, veremos que hay problemas que hacen que esto no sea 100% confiable. Los nombres fuertes lo ayudan a proteger a los usuarios inconscientes del reemplazo de su DLL con una copia falsificada malintencionada. Pero si el usuario es cómplice en la falsificación (que sería el caso si está intentando hacer trampa), la firma del código no será más que un golpe de velocidad y no ofrece una protección real. Ciertamente, los nombres fuertes no proporcionan una protección comparable a, por ejemplo, PunkBuster.

Uso de un nombre seguro para verificar la identidad de un editor de ensamblajes

Cuando agrega un nombre seguro a un ensamblaje, está usando una clave privada (parte de un par de claves pública / privada asimétrica, más sobre esto más adelante) para generar un hash criptográfico y la clave pública se incluye en el nombre del ensamblaje (junto con el hash).

Usando el hash público y la clave pública, el CLR puede verificar que la firma del ensamblaje de hecho proviene de la clave privada.

Por supuesto, esto significa que debe proteger la clave (interna y externamente); Si alguien más tiene su clave, entonces pueden suplantarlo y publicar asambleas en las que la gente confía que sea suya.

Luego, cuando agrega una referencia a su ensamblaje firmado, si alguien intenta colocar un ensamblaje diferente con el mismo nombre de ensamblaje (no el que está completamente calificado, solo el nombre sin versión, hash y clave pública) y el mismo nombre de tipo, el El relleno de CLR falla al intentar cargar el tipo, lo que indica que no pudo encontrarlo; el tipo se resuelve utilizando el nombre de ensamblaje completo, junto con el espacio de nombres y el nombre de tipo.

¿Por qué los nombres fuertes no son 100% seguros (hay algo?)

1) Hash Collisions

Todavía es un hash que está siendo verificado. Mientras que el hash es bastante grande (160 bits para el algoritmo de hash predeterminado, SHA-1), cualquier hash que tenga un número finito de valores está sujeto a una colisión. Si bien es extremadamente improbable, es posible (imposible vs. improbable). Además, solo los últimos 8 bytes son usados ​​por defecto. Combinado con la investigación que indica que SHA-1 es relativamente débil, esta es una buena razón para usar SHA-256 Enhanced Strong Naming como se describe en MSDN .

2) Eliminación del nombre fuerte

El nombre fuerte puede ser eliminado. Sin embargo, en este caso, debido a que su ensamblaje hace referencia a la versión con nombre seguro del ensamblado al que se hace referencia , cuando su ensamblaje intenta usar la versión comprometida, fallará en el tiempo de ejecución, suponiendo que haya habilitado correctamente la verificación (ver más abajo).

3) Acceso físico a los ensamblajes significa todos los ensamblajes

Si alguien tiene acceso a la máquina física y puede modificar el ensamblaje al que hace referencia, entonces su ensamblaje es igual de vulnerable. Si el atacante tiene la capacidad de modificar el nombre seguro de un ensamblado al que hizo referencia, entonces puede modificar su ensamblaje y todos los demás involucrados en la ejecución con la misma facilidad. Para este fin, la única manera de estar 100% seguro de que el ensamblaje físico no se ha pirateado es negar el acceso físico a través de él . Por supuesto, eso trae una serie de diferentes preocupaciones de seguridad.

4) Administrador deshabilitando la verificación de nombre fuerte

El administrador de la computadora simplemente puede omitir la verificación de nombre sn -Vr , usando sn -Vr . Según MSDN :

Registra el ensamblaje para omitir la verificación ... Un ensamblaje malintencionado podría usar el nombre del ensamblaje completamente especificado (nombre del ensamblado, versión, cultura y token de clave pública) del ensamblaje agregado a la lista de verificación de omisión para falsificar su identidad. Esto permitiría que el ensamblaje malicioso también omita la verificación.

5) La comprobación de nombres sólidos debe habilitarse explícitamente después de .NET 3.5 SP 1

A partir de .NET 3.5 SP 1, el simple hecho de tener un nombre seguro no proporciona ninguna protección :

A partir de .NET Framework versión 3.5 Service Pack 1 (SP1), las firmas de nombre seguro no se validan cuando un conjunto se carga en un objeto de dominio de aplicación de plena confianza, como el dominio de aplicación predeterminado para la zona MyComputer.

Para que .NET verifique el nombre seguro de cada conjunto cargado en su aplicación, querrá insertar el siguiente fragmento de código (proporcionado por MSDN) en su archivo de configuración de la aplicación:

<configuration> <runtime> <bypassTrustedAppStrongNames enabled="false" /> </runtime> </configuration>

Tenga en cuenta, sin embargo, que esto solo protege contra la eliminación del nombre fuerte.

Cuando reemplaza la función de omisión, el nombre seguro se valida solo para que sea correcto; no se comprueba para un StrongNameIdentityPermission . Si desea confirmar un nombre seguro específico, debe realizar esa comprobación por separado.

Si a la luz de las preocupaciones anteriores, aún desea continuar con Strong Naming su asamblea, aquí le explicamos cómo.

Generando un nombre fuerte y firmando su asamblea

Tiene dos opciones para la cual usar la clave al generar un nombre seguro. En Visual Studio, vaya a la pestaña Firma en las propiedades del proyecto y haga clic en "Firmar el ensamblaje":

A partir de ahí, tiene dos opciones para generar la clave pública / privada, para que VS.NET genere las claves para usted, o para apuntar a una existente:

Al seleccionar "Nuevo", Visual Studio le solicitará el nombre del archivo a generar, así como si desea o no usar una contraseña para acceder a él:

En ese momento, la clave se agregará a su proyecto:

Ahora, puede mover esto a un elemento de la solución (si tiene varios proyectos en su solución).

En este caso, Visual Studio simplemente está llamando a la MSDN para generar un par de claves públicas y privadas. Si prefieres hacerlo tú mismo, deberías llamar a sn.exe con la opción de línea de comando -k para generar la clave, de esta manera:

sn -k keyPair.snk

Y luego agregarlo a través del cuadro de diálogo "Examinar" arriba.

Tenga en cuenta que cuando haga esto, insertará la llave en su proyecto. Si no desea hacer esto (ya que copia la clave en todos los proyectos), elimine la clave del proyecto y luego agregue un archivo existente al proyecto, pero vincúlelo . Esto borrará la opción "Elegir un archivo de clave de nombre seguro", pero si lo suelta, verá la ruta completa al archivo de clave vinculado.


Parece que la respuesta más sencilla sería calcular un hash seguro de la DLL que está cargando y luego compararla con un valor dorado que usted haya precalculado. Por supuesto, esto aún será vulnerable a ser roto por un atacante suficientemente determinado, pero elevará significativamente el nivel para las personas que quieren hacer trampa.