Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking an assembly for a strong name

Is it possible to check if a dynamically loaded assembly has been signed with a specific strong name?

Is it enough / secure to compare the values returned from 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;
    }
}

Can't this be spoofed? I am not sure if the SetPublicKey() method has any effect on a built assembly, but even the MSDN documentation shows how you can use this on a dynamically generated assembly (reflection emit) so that would mean you could extract the public key from the host application and inject it into an assembly of your own and run mallicious code if the above was the safe-guard, or am I missing something?

Is there a more correct and secure approach? I know if the reversed situation was the scenario, that is, where I wanted to secure the assembly from only being called by signed hosts then I could tag the assembly with the StrongNameIdentityPermission attribute.

like image 896
TheCodeJunkie Avatar asked Nov 21 '08 13:11

TheCodeJunkie


People also ask

How do you tell if an assembly is strongly named?

To determine if an assembly is strong-typed, use the Strong Name Tool from Microsoft (http://msdn.microsoft.com/en-us/library/k5b5tt23(v=vs.71).aspx) by running the 'sn.exe -v <assembly>' command. You may need to download one of the Windows SDK packages to get access to this tool.

What makes a strong named assembly?

What makes a strong-named assembly? A strong named assembly is generated by using the private key that corresponds to the public key distributed with the assembly, and the assembly itself. The assembly includes the assembly manifest, which contains the names and hashes of all the files that make up the assembly.

How do you ensure class library assembly is strongly named?

Sign an assembly with a strong name by using the compiler Compile your source code file or files with the /keyfile or /delaysign compiler option in C# and Visual Basic, or the /KEYFILE or /DELAYSIGN linker option in C++. After the option name, add a colon and the name of the key file.

Should I strong name my assemblies?

You should strong name your open-source . NET libraries. Strong naming an assembly ensures the most people can use it, and strict assembly loading only affects . NET Framework.


2 Answers

There is no managed way to check the signature of an assembly and checking the public key leaves you vulnerable to spoofing. You will have to use P/Invoke and call the StrongNameSignatureVerificationEx function to check the signature

[DllImport("mscoree.dll", CharSet=CharSet.Unicode)]
static extern bool StrongNameSignatureVerificationEx(string wszFilePath, bool fForceVerification, ref bool  pfWasVerified);
like image 116
TheCodeJunkie Avatar answered Sep 22 '22 07:09

TheCodeJunkie


There's little point in testing the strong name after the assembly got loaded. An attacker could simply inject a module constructor in the assembly and execute any code desired. The .NET 3.5 SP1 version of the framework followed suit and is no longer verifying the strong name of assemblies that get loaded from trusted locations. Startup times improve by about 40%.

The key point is: once an attacker compromises the machine to a point where he is able to inject an assembly in the probing path of your application, he won't bother doing it the hard way. He'd just replace your EXE file.

like image 25
Hans Passant Avatar answered Sep 23 '22 07:09

Hans Passant