c# - 使用 Roslyn 在服务器端 API 上安全执行代码

标签 c# security roslyn code-injection roslyn-code-analysis

为了给我的用户提供更大的灵活性并让他们编写自己的表达式,我希望允许他们在文本字段中编写非常简单的 C# 语句,这些语句在服务器端执行以执行一些自定义计算。 我正在与 Roslyn 一起存档此内容。
可以找到一个很好的例子来开始我的工作 here .

我让用户在评估函数中注入(inject)代码,如下所示:

        string codeToCompile = @"
        using System;
        using System.Collections.Generic;
        namespace Evaluator
        {
            public class Evaluator
            {
                public string Eval()
                {
                    " + {POTENTIALLY_DANGEROUS_CODE_GOES_HERE} + @"                      
                }
            }
        }";

您可以看到注入(inject)的代码始终位于 Eval-Function 内,并且最终应返回一个字符串。
用户可以决定如何计算该字符串。
我现在正在考虑安全性,因为我无法控制注入(inject)的代码。

实际上我的用户应该只能:

  • 使用数学表达式
  • 原始变量
  • if 语句

因此注入(inject)代码的示例可能如下所示:

int a = 5;
int b = 10;

if(a < b) 
{
   return "a is smaller";
}
else
{
   return "a is bigger or equal";
}

您可以在上面的示例代码中看到,命名空间仅限于“System”和“System.Collections.Generic”,因此很多东西将不再可能(例如从服务器的文件系统中读取某些内容)并将此信息作为字符串输出)

我还替换了所有出现的循环,因此 while、for、foreach 等表达式将从字符串中删除。

但我仍然非常不确定这个解决方案是否安全。

  1. 潜在攻击者现在还能做什么? (特别是使用提供的两个命名空间的选项)
  2. 在这种情况下,我可以采取哪些最佳实践来防止攻击?

最佳答案

根据您的需求,这非常很难做到。很难。 “如果你必须问如何去做,你可能会难以理解”。需要考虑一些有趣的事情:

  1. 仅仅因为您限制文件顶部的命名空间并不意味着某人无法将其代码片段中的某些内容显式限定为不同的命名空间。因此,重要的是您必须遍历整个代码以查看是否使用了任何其他类型。我无法判断您所允许的显式列表是否隐式禁止所有方法调用或对象创建。
  2. 谨慎假设系统中的任何内容都是安全的。考虑 System.Activator,它允许您调用 CreateInstance 并传入另一种类型的字符串名称来创建它。仅此类型就可以让您绕过可能执行的任何其他检查。当我按字母顺序提取系统命名空间中的文档时,这只是第一个跳出来的!
  3. ...当然不只是专门阻止 System.Activator。每当您更新人们编写代码的框架时,都可能会出现有问题的新类型。

还要考虑潜在安全攻击的类型:即使您无法写入文件,您是否仍然可以从服务器泄漏信息(例如用户名或计算机名称),从而可能允许用户以其他方式闯入您的系统。或者他们只是编写一个消耗服务器资源的无限循环。您提到您将删除循环,但不要忘记像 goto 这样的东西,或者只是编写某种导致堆栈溢出的递归函数。

我不会说“只要做 X 就安全了”,因为我什至不相信自己能写出这样的话。但是:

  1. 使用您的操作系统来帮助您隔离:在具有较少权限或没有权限的单独进程中运行它,等等。如果您可以创建单独的虚拟机/容器,那就太好了。您在这里可以隔离的越多越好。
  2. 如果您要进行代码检查,请不要拒绝您知道不好的模式;相反,编写只接受您知道“安全”的模式的代码。这可能会导致大量工作选择愚蠢的事情,但替代方案要求您列举所有不好的事情。

关于c# - 使用 Roslyn 在服务器端 API 上安全执行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66554537/

相关文章:

linux - 在现代 Linux 上永久删除 root 权限

c# - .NET 中的隐式链构造函数

c# - XmlSerializer、GenerateSerializer 和集合

c# - 如何打开以编程方式添加到我的 Windows 应用商店应用程序项目中的文件?

c# - .net 4.6 项目中缺少 XML 文档注释的枚举类

java - 要使用凯撒密码身份验证在 Java 中编写客户端服务器套接字程序,我需要了解什么?

ios 10 应用程序在执行期间在内存中包含敏感数据

c# - 如何使用 Roslyn 格式化代码选择并维护领先的琐事?

c# - 如何检查 .net 5 源生成器中是否启用了可空引用类型

c# - 监控进程对每个 CPU 核心的使用情况