2008-11-21 17 views
16

¿Se puede verificar si un ensamble cargado dinámicamente ha sido firmado con un nombre fuerte específico?Comprobación de un ensamble para un nombre seguro

¿Es suficiente/seguro para comparar los valores devueltos desde AssemblyName.GetPublicKey() method?

Assembly loaded = Assembly.LoadFile(path); 

byte[] evidenceKey = loaded.GetName().GetPublicKey(); 

if (evidenceKey != null) 
{ 
    byte[] internalKey = Assembly.GetExecutingAssembly().GetName().GetPublicKey(); 

    if (evidenceKey.SequenceEqual(internalKey)) 
    { 
     return extension; 
    } 
} 

¿No se puede suplantar? No estoy seguro de si el método SetPublicKey() tiene algún efecto en un ensamblado construido, pero incluso la documentación de MSDN muestra cómo puede usar esto en un ensamblaje generado dinámicamente (emitir reflejo), lo que significa que podría extraer la clave pública del la aplicación de host e inyectarlo en un ensamblado propio y ejecutar un código malicioso si lo anterior fue la protección de seguridad, o ¿me estoy perdiendo algo?

¿Hay un enfoque más correcto y seguro? Sé que si la situación revertida fuera el escenario, es decir, cuando quería asegurar que el ensamblado solo fuera llamado por los hosts firmados, entonces podría etiquetar el ensamblado con el atributo StrongNameIdentityPermission.

Respuesta

14

No hay una forma administrada de verificar la firma de un ensamblaje y verificar la clave pública lo hace vulnerable a la suplantación. Usted tendrá que utilizar P/Invoke y llamar a la StrongNameSignatureVerificationEx función para comprobar la firma

[DllImport("mscoree.dll", CharSet=CharSet.Unicode)] 
static extern bool StrongNameSignatureVerificationEx(string wszFilePath, bool fForceVerification, ref bool pfWasVerified); 
+1

Hagas lo que hagas puede dejarte engañar ya que el atacante puede eludir fácilmente el control en tu ensamblaje y volver a montar el IL modificado y renunciar al ensamblado con el suyo llave. –

+0

Cuando dice que no hay una forma administrada, ¿quiere decir que técnicamente no es posible o que no hay una biblioteca/rutina estándar para hacerlo? – ohw

13

No tiene mucho sentido probar el nombre seguro después de que se cargó el conjunto. Un atacante podría simplemente inyectar un constructor de módulo en el ensamblado y ejecutar cualquier código deseado. La versión .NET 3.5 SP1 del framework hizo lo mismo y ya no está verificando el nombre fuerte de los ensamblados que se cargan desde las ubicaciones de confianza. Los tiempos de inicio mejoran en un 40%.

El punto clave es: una vez que un atacante compromete la máquina hasta el punto de poder inyectar un conjunto en la ruta de prueba de su aplicación, no se molestará en hacerlo de la manera difícil. Él simplemente reemplazaría tu archivo EXE.

+0

En realidad esta es una situación donde las extensiones (en forma de conjuntos) se pueden añadir a la aplicación es decir, que se cargan desde un directorio utilizando Assembly.LoadFile y solo quiero poder cargar extensiones que hayan sido firmadas con el mismo nombre fuerte que la aplicación de host. – TheCodeJunkie

+0

Por lo tanto, este no es un caso de protección de un sistema o aplicación completa, sino de restringir quién puede escribir extensiones en la aplicación. No hay un nombre fuerte, lo siento, su extensión no se cargará – TheCodeJunkie

+0

@ Hans Passant Creo que probar el nombre fuerte aún es útil. Si el exe A hace referencia a dll B y ambos tienen un nombre fuerte, y la validación de un nombre seguro está habilitada en app.config, entonces un hacker simplemente puede eliminar el nombre fuerte en ambos archivos mediante la sobreescritura de algún nivel de archivo de hacking (byte). Podemos verificar en el inicio del programa que si el ensamblado tiene algún nombre fuerte (es decir, firmado) – Alireza

7

Comprobación de nombre seguro utilizando StrongNameSignatureVerificationEx de mscoree.dll está en desuso bajo .NET 4 según http://msdn.microsoft.com/pl-pl/library/ms232579.aspx.

.NET 4 manera de hacerlo es:

var clrStrongName = (IClrStrongName)RuntimeEnvironment.GetRuntimeInterfaceAsObject(new Guid("B79B0ACD-F5CD-409b-B5A5-A16244610B92"), new Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D")); 
bool verificationForced; 
int result = clrStrongName.StrongNameSignatureVerificationEx(@"PATH\TO\ASSEMBLY.DLL", true, out verificationForced); 
if (result == 0) 
{ 
    Console.WriteLine("Valid."); 
} 



[ComConversionLoss, Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), SecurityCritical] 
[ComImport] 
internal interface IClrStrongName 
{ 
    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int GetHashFromAssemblyFile([MarshalAs(UnmanagedType.LPStr)] [In] string pszFilePath, [MarshalAs(UnmanagedType.U4)] [In] [Out] ref int piHashAlg, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] [Out] byte[] pbHash, [MarshalAs(UnmanagedType.U4)] [In] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int GetHashFromAssemblyFileW([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzFilePath, [MarshalAs(UnmanagedType.U4)] [In] [Out] ref int piHashAlg, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] [Out] byte[] pbHash, [MarshalAs(UnmanagedType.U4)] [In] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int GetHashFromBlob([In] IntPtr pbBlob, [MarshalAs(UnmanagedType.U4)] [In] int cchBlob, [MarshalAs(UnmanagedType.U4)] [In] [Out] ref int piHashAlg, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] [Out] byte[] pbHash, [MarshalAs(UnmanagedType.U4)] [In] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int GetHashFromFile([MarshalAs(UnmanagedType.LPStr)] [In] string pszFilePath, [MarshalAs(UnmanagedType.U4)] [In] [Out] ref int piHashAlg, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] [Out] byte[] pbHash, [MarshalAs(UnmanagedType.U4)] [In] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int GetHashFromFileW([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzFilePath, [MarshalAs(UnmanagedType.U4)] [In] [Out] ref int piHashAlg, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] [Out] byte[] pbHash, [MarshalAs(UnmanagedType.U4)] [In] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int GetHashFromHandle([In] IntPtr hFile, [MarshalAs(UnmanagedType.U4)] [In] [Out] ref int piHashAlg, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] [Out] byte[] pbHash, [MarshalAs(UnmanagedType.U4)] [In] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    [return: MarshalAs(UnmanagedType.U4)] 
    int StrongNameCompareAssemblies([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzAssembly1, [MarshalAs(UnmanagedType.LPWStr)] [In] string pwzAssembly2, [MarshalAs(UnmanagedType.U4)] out int dwResult); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameFreeBuffer([In] IntPtr pbMemory); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameGetBlob([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzFilePath, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] [Out] byte[] pbBlob, [MarshalAs(UnmanagedType.U4)] [In] [Out] ref int pcbBlob); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameGetBlobFromImage([In] IntPtr pbBase, [MarshalAs(UnmanagedType.U4)] [In] int dwLength, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] [Out] byte[] pbBlob, [MarshalAs(UnmanagedType.U4)] [In] [Out] ref int pcbBlob); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameGetPublicKey([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzKeyContainer, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] [In] byte[] pbKeyBlob, [MarshalAs(UnmanagedType.U4)] [In] int cbKeyBlob, out IntPtr ppbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbPublicKeyBlob); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    [return: MarshalAs(UnmanagedType.U4)] 
    int StrongNameHashSize([MarshalAs(UnmanagedType.U4)] [In] int ulHashAlg, [MarshalAs(UnmanagedType.U4)] out int cbSize); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameKeyDelete([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzKeyContainer); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameKeyGen([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzKeyContainer, [MarshalAs(UnmanagedType.U4)] [In] int dwFlags, out IntPtr ppbKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbKeyBlob); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameKeyGenEx([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzKeyContainer, [MarshalAs(UnmanagedType.U4)] [In] int dwFlags, [MarshalAs(UnmanagedType.U4)] [In] int dwKeySize, out IntPtr ppbKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbKeyBlob); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameKeyInstall([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzKeyContainer, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] [In] byte[] pbKeyBlob, [MarshalAs(UnmanagedType.U4)] [In] int cbKeyBlob); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameSignatureGeneration([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzFilePath, [MarshalAs(UnmanagedType.LPWStr)] [In] string pwzKeyContainer, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] [In] byte[] pbKeyBlob, [MarshalAs(UnmanagedType.U4)] [In] int cbKeyBlob, [In] [Out] IntPtr ppbSignatureBlob, [MarshalAs(UnmanagedType.U4)] out int pcbSignatureBlob); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameSignatureGenerationEx([MarshalAs(UnmanagedType.LPWStr)] [In] string wszFilePath, [MarshalAs(UnmanagedType.LPWStr)] [In] string wszKeyContainer, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] [In] byte[] pbKeyBlob, [MarshalAs(UnmanagedType.U4)] [In] int cbKeyBlob, [In] [Out] IntPtr ppbSignatureBlob, [MarshalAs(UnmanagedType.U4)] out int pcbSignatureBlob, [MarshalAs(UnmanagedType.U4)] [In] int dwFlags); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameSignatureSize([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] [In] byte[] pbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] [In] int cbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbSize); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    [return: MarshalAs(UnmanagedType.U4)] 
    int StrongNameSignatureVerification([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzFilePath, [MarshalAs(UnmanagedType.U4)] [In] int dwInFlags, [MarshalAs(UnmanagedType.U4)] out int dwOutFlags); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    [return: MarshalAs(UnmanagedType.U4)] 
    int StrongNameSignatureVerificationEx([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzFilePath, [MarshalAs(UnmanagedType.I1)] [In] bool fForceVerification, [MarshalAs(UnmanagedType.I1)] out bool fWasVerified); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    [return: MarshalAs(UnmanagedType.U4)] 
    int StrongNameSignatureVerificationFromImage([In] IntPtr pbBase, [MarshalAs(UnmanagedType.U4)] [In] int dwLength, [MarshalAs(UnmanagedType.U4)] [In] int dwInFlags, [MarshalAs(UnmanagedType.U4)] out int dwOutFlags); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameTokenFromAssembly([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzFilePath, out IntPtr ppbStrongNameToken, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameTokenFromAssemblyEx([MarshalAs(UnmanagedType.LPWStr)] [In] string pwzFilePath, out IntPtr ppbStrongNameToken, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken, out IntPtr ppbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbPublicKeyBlob); 

    [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] 
    int StrongNameTokenFromPublicKey([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] [In] byte[] pbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] [In] int cbPublicKeyBlob, out IntPtr ppbStrongNameToken, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken); 
} 
+0

Fantástica ayuda. Funciona bien para mí. Muchas gracias – bgx

Cuestiones relacionadas