3

我有一个 C# 应用程序,它将包含计算的源文件执行一些运行时编译到动态程序集中。显然,这提出了一个严重的安全问题。

根据以下“公式”,将生成以下代码,并创建一个动态程序集:

公式:

Int32 _index = value.LastIndexOf('.');
String _retVal = value.Substring(_index + 1);
return _retVal;

生成的代码:

using System;
namespace Dynamics
{
  public class Evaluator
  {
    public Object Evaluate(String value)
    {
      // Begin external code
      Int32 _index = value.LastIndexOf('.');
      String _retVal = value.Substring(_index + 1);
      return _retVal;
      // End external code
    }
  }
}

然后加载动态程序集并通过反射执行 Evaluate 方法。这很好用。

问题是恶意代码注入的可能性很大,所以我想在“沙盒”线程中运行 Evaluate 方法(没有任何非托管 API 调用)。出于测试目的,我使用了内置的匿名 Windows 用户,并提供了以下代码:

Thread tSandbox = new Thread(
    new ParameterizedThreadStart(this.DoSandboxedEvaluation));
WindowsIdentity tIdentity = WindowsIdentity.GetAnonymous();
WindowsPrincipal tPrincipal = new WindowsPrincipal(i);

这给了我匿名用户的身份和主体。如何将其应用于线程 tSandbox,以便该线程上的代码在指定的安全上下文中运行,而不使用非托管 API 调用?

谢谢!

4

2 回答 2

5

AFAIK 模拟另一个用户的唯一方法是通过非托管的 win32 api(例如,LogonUser())...您可以通过互操作调用它们。

这里有一个代码示例

于 2009-04-08T14:14:57.653 回答
1

如果您只需要匿名帐户,您可能非常接近 - 您只需将原则分配给线程(您可以通过设置 System.Threading.CurrentPrinciple 来更改要更改的线程中运行的代码)

但是,如果您需要对 Windows 用户进行身份验证并将该身份分配给线程,我认为您将不得不对 LogonUser() 进行非托管调用。我看不出有什么办法。

这是一些适用于匿名用户的代码(它假设一个 ASP.Net Web ApplicationProject,您在表单上有一个名为“identityLabel”的标记,并且您已分配 onInit="IdentityLabelInit")(请注意,代码运行方式不同,具体取决于不管你是在IIS还是Cassini下运行——在IIS下,初始身份是匿名用户,在Cassini下,初始身份是我。


        protected void IdentityLabelInit(object sender, EventArgs e)
        {
            System.Threading.Thread testThread = new Thread(ReportIdentity);
            testThread.Start();
            testThread.Join();
        }

        private void ReportIdentity()
        {
            identityLabel.InnerText = "Initialized: " + System.Threading.Thread.CurrentPrincipal.Identity.Name;
            System.Security.Principal.IPrincipal currentPrincipal = System.Threading.Thread.CurrentPrincipal;
            SetAnonymousIdentity();
            System.Security.Principal.IPrincipal newPrincipal = System.Threading.Thread.CurrentPrincipal;
            if (newPrincipal.Equals(currentPrincipal))
                identityLabel.InnerText += ("no change");
            else
                identityLabel.InnerText += " | new name: " + System.Threading.Thread.CurrentPrincipal.Identity.Name;
        }

        private void SetAnonymousIdentity()
        {
            WindowsIdentity tIdentity = WindowsIdentity.GetAnonymous();
            WindowsPrincipal tPrincipal = new WindowsPrincipal(tIdentity);
            System.Threading.Thread.CurrentPrincipal = tPrincipal;
        }

于 2009-04-08T16:40:46.180 回答