Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
122 views
in Technique[技术] by (71.8m points)

c# - .NET Assembly Plugin Security

I have used the following code in a number of applications to load .DLL assemblies that expose plugins.

However, I previously was always concerned with functionality, rather than security.

I am now planning to use this method on a web application that could be used by groups other than me, and I would like to make sure that the security of the function is up-to-snuff.

private void LoadPlugins(string pluginsDirectory)
{
    List<IPluginFactory> factories = new List<IPluginFactory>();

    foreach (string path in Directory.GetFiles(pluginsDirectory, "*.dll"))
    {
        Assembly assembly = Assembly.LoadFile(path);
        foreach (Type type in assembly.GetTypes())
        {
            IPluginEnumerator instance = null;
            if (type.GetInterface("IPluginEnumerator") != null)
                instance = (IPluginEnumerator)Activator.CreateInstance(type);
            if (instance != null)
            {
                factories.AddRange(instance.EnumerateFactories());
            }
        }
    }

    // Here, I would usually collate the plugins into List<ISpecificPlugin>, etc.
}

The first few concerns I have:

  1. This function reads the entire directory and doesn't care about what assemblies it loads, and instead just loads all of them. Is there a way to detect whether an assembly is a valid, functional .NET assembly before loading it with Assembly.LoadFile()?
  2. What kind of exception handling should be added to the function to prevent initialization of the assembly from halting my code?
  3. If I want to deny the assembly the right to do the following: Read/Write files, Read/Wite the registry, etc, how would I do that?

Are there any other security concerns I should be worried about?

EDIT: Keep in mind that I want anybody to be able to write a plug-in, but I still want to be secure.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

1) strong name the assembly with a certain key.

  • you do not have to put it in the GAC
  • you can re-use a key to sign more than one assembly
  • when you re-use the key, you get the same "public key" on each signed assembly

2) on load, check that the assembly has been strong named with the key you're expecting

  • You can store the public key as a binary file, an embedded resource, or use the existing public key of the executing assembly
  • this last way may not be the best way as you may want to differentiate assemblies signed with the "plugin" key from those signed with a regular key)

Example:

public static StrongName GetStrongName(Assembly assembly)
{
    if(assembly == null)
        throw new ArgumentNullException("assembly");
    AssemblyName assemblyName = assembly.GetName();

    // get the public key blob
    byte[] publicKey = assemblyName.GetPublicKey();
    if(publicKey == null || publicKey.Length == 0)
       throw new InvalidOperationException( String.Format("{0} is not strongly named", assembly));

    StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey);

    // create the StrongName
    return new StrongName(keyBlob, assemblyName.Name, assemblyName.Version);
}


// load the assembly:
Assembly asm = Assembly.LoadFile(path);
StrongName sn = GetStrongName(asm);

// at this point
// A: assembly is loaded
// B: assembly is signed
// C: we're reasonably certain the assembly has not been tampered with
// (the mechanism for this check, and it's weaknesses, are documented elsewhere)

// all that remains is to compare the assembly's public key with 
// a copy you've stored for this purpose, let's use the executing assembly's strong name
StrongName mySn = GetStrongName(Assembly.GetExecutingAssembly());

// if the sn does not match, put this loaded assembly in jail
if (mySn.PublicKey!=sn.PublicKey)
    return false;

note: code has not been tested or compiled, may contain syntax errors.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...