我在许多应用程序中使用以下代码来加载暴露插件的.DLL程序集.
然而,我以前一直关心功能,而不是安全性.
我现在打算在一个web应用程序上使用这个方法,可以由除我以外的其他组织使用,我想确保该功能的安全性是最新的.
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. }
我有以下几个关切:
>这个函数读取整个目录,并不关心它加载的程序集,而是加载它们.在使用Assembly.LoadFile()加载程序集之前,有没有办法检测程序集是否是一个有效的.NET程序集?
>什么样的异常处理应该添加到函数中以防止程序集的初始化停止我的代码?
>如果我想拒绝汇编有权执行以下操作:读/写文件,读/注册注册表等,我该怎么做?
有什么其他安全问题我应该担心吗?
编辑:请记住,我希望任何人能够编写一个插件,但我仍然希望安全.
解决方法
1)用一个特定的键命名装配体.
>你不必把它放在GAC里
>您可以重新使用键来签署多个程序集
>当您重新使用密钥时,您将在每个签名的程序集上获得相同的“公钥”
2)加载时,请使用您期望的密钥检查程序集是否被强命名
>您可以将公钥存储为二进制文件,嵌入式资源,
或使用执行程序集的现有公钥
>最后一个方法可能不是最好的方法,你可能想要区分程序集
使用常规键签名的“插件”键签名)
例:
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;