2008-11-21 7 views
16

Можно ли проверить, была ли подписана динамически загруженная сборка с определенным сильным именем?Проверка сборки на сильное имя

Достаточно ли/безопасно сравнивать значения, возвращаемые с AssemblyName.GetPublicKey() метод?

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; 
    } 
} 

Нельзя ли это подделать? Я не уверен, что метод SetPublicKey() оказывает какое-либо влияние на встроенную сборку, но даже документация MSDN показывает, как вы можете использовать это на динамически сгенерированной сборке (отражение emit), так что это означает, что вы можете извлечь открытый ключ из хост-приложение и вставлять его в собственную сборку и запускать надежный код, если вышеописанное было безопасным, или я чего-то не хватает?

Есть ли более правильный и безопасный подход? Я знаю, была ли ситуация с обратным адресом сценарием, то есть там, где я хотел, чтобы сборка была только вызвана подписанными хостами, я мог бы пометить сборку атрибутом StrongNameIdentityPermission.

ответ

14

Нет управляемого способа проверить подпись сборки, и проверка открытого ключа оставляет вас уязвимым для подмены. Вы должны будете использовать P/Invoke и называть StrongNameSignatureVerificationEx функцию, чтобы проверить подпись

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

Существует мало смысла тестировать сильное имя после того, как сборка была загружена. Злоумышленник может просто вставить конструктор модуля в сборку и выполнить любой желаемый код. Версия платформы .NET 3.5 SP1 последовали этому примеру и больше не проверяют сильное имя сборок, которые загружаются из надежных местоположений. Время запуска увеличивается примерно на 40%.

Ключевым моментом является то, что после того, как злоумышленник скомпрометирует машину до такой степени, что он сможет впрыснуть сборку в пробную дорожку вашего приложения, он не будет беспокоиться об этом. Он просто заменит ваш EXE-файл.

+0

На самом деле это ситуация, когда расширение (в виде сборок) может быть добавлено к приложению, т.е. они загружаются из каталога с помощью Assembly.LoadFile и я хочу только иметь возможность загружать расширения, которые были подписаны с тем же сильным именем, что и хост-приложение. – TheCodeJunkie 2008-11-21 14:18:28

+0

Так что это не случай безопасной защиты всей системы или приложения, но ограничение того, кто может писать расширения для самого приложения. Нет сильного имени, извините, что ваше расширение не будет загружено. – TheCodeJunkie 2008-11-21 14:19:23

+0

@Hans Passant Я думаю, что тестирование сильного имени по-прежнему полезно. Если exe A ссылается на dll B, и обе они имеют сильное имя, а в app.config включена сильная проверка имени, тогда хакер может просто удалить сильное имя в обоих файлах с помощью перезаписывания уровня файла (хайте). Мы можем проверить запуск программы, если сборка имеет какое-либо сильное имя (то есть подписанное) – Alireza 2013-01-04 19:46:37

7

Проверка сильное имя с помощью StrongNameSignatureVerificationEx из mscoree.dll осуждается под .NET 4 по http://msdn.microsoft.com/pl-pl/library/ms232579.aspx.

.NET 4 способа сделать это:

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); 
}