Wednesday, March 16, 2011

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? 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 revered situation was the scenario, i.e where I wanted to secure the assembly from only being called by signed hosts then i could tag the assembly with the StrongNameIdentityPermission attribute

Thanks

From stackoverflow
  • 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. Improving startup times by about 40%.

    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 app, he won't bother doing it the hard way. He'd just replace your .exe

    TheCodeJunkie : Actually this is a situation where extensions (in the form of assemblies) can be added to the application i.e they are loaded from a directory using Assembly.LoadFile and I only want to be able to load extensions which have been signed with the same strong name as the host application.
    TheCodeJunkie : So this isn't a case of safe-guarding an entire system or application, but restricting whom is able to write extensions to the application itself. No strong name, sorry your extension will not be loaded
  • I'll answer my own question. 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);
    
    Mehrdad Afshari : Whatever you do can leave you to spoofing as the attacker can easily circumvent the check in your assembly and reassemble the modified IL and resign the assembly with his own key.

0 comments:

Post a Comment