线程可以作为另一个用户执行吗? (.NET 2.0 / 3.5)

我有一个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 } } } 

然后加载动态assembly,并通过Reflection执行Evaluate方法。 这很棒。

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

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

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

谢谢!

如果您只需要匿名帐户,那么您可能非常接近 – 您只需要将该原则分配给该线程(您可以通过设置System.Threading.CurrentPrinciple从您想要更改的线程中运行的代码执行此操作)

但是,如果您需要对Windows用户进行身份validation并将该身份分配给该线程,我认为您将不得不对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; }
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; } 

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

这里有一个代码示例