c# - .NET 程序集插件安全

标签 c# security reflection plugins

我在许多应用程序中使用了以下代码来加载公开插件的 .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.
}

我首先担心的几个问题:

  1. 这个函数读取整个目录而不关心它加载了哪些程序集,而是只加载所有这些程序集。有没有办法在使用 Assembly.LoadFile() 加载程序集之前检测程序集是否是有效的、功能正常的 .NET 程序集?
  2. 应该向函数添加什么样的异常处理以防止程序集的初始化停止我的代码?
  3. 如果我想拒绝程序集执行以下操作的权利:读取/写入文件、读取/写入注册表等,我该怎么做?

还有其他我应该担心的安全问题吗?

编辑:请记住,我希望任何人都能够编写插件,但我仍然希望安全。

最佳答案

1) 用某个键强命名程序集。

  • 不必将其放入 GAC
  • 您可以重复使用一个 key 来签署多个程序集
  • 当您重复使用 key 时,您会在每个已签名的程序集上获得相同的“公钥”

2) 加载时,检查程序集是否已使用您期望的 key 强命名

  • 您可以将公钥存储为二进制文件、嵌入式资源、 或使用执行程序集的现有公钥
  • 这最后一种方法可能不是最好的方法,因为您可能想要区分程序集 使用常规 key 签名的“插件” key 签名)

例子:

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;

注意:代码未经测试或编译,可能包含语法错误。

关于c# - .NET 程序集插件安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/932339/

相关文章:

c# - 在 ReactiveUI 7.2 中手动执行命令

c# - 从 Visual Studio 中的 C# 代码传递到 C 代码

iis - 使用 OpenSSL 的 IIS 上不受信任的证书

c# - 创建一个没有 0 值的 C# 枚举实例

java - Private 就是 Private,那为什么 java 会提供使用反射来访问私有(private)方法的便利呢?

C# Sql 跨页面连接字符串

c# - 检查射线是否击中立方体

apache - 2 Way SSL using Apache - 证书问题

asp.net - 表单例份验证是否可以防止 session 劫持?

dictionary - 如何从 FSharp 中的反射调用 Map.Add?