Может ли поток выполняться как другой пользователь? (.NET 2.0 / 3.5) - PullRequest
2 голосов
/ 08 апреля 2009

У меня есть приложение 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 выполняется с помощью Reflection. Это прекрасно работает.

Проблема в том, что вероятность внедрения вредоносного кода огромна, поэтому я хочу запустить метод Evaluate в потоке «песочницы» (без каких-либо неуправляемых вызовов API). В целях тестирования я использую встроенного анонимного пользователя Windows и придумала следующий код:

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

Это дает мне личность и принципала анонимных пользователей. Как это можно применить к потоку tSandbox, чтобы код в этом потоке выполнялся в указанном контексте безопасности, без использования неуправляемых вызовов API?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 08 апреля 2009

AFAIK единственный способ выдать себя за другого пользователя - через неуправляемый интерфейс win32 (например, LogonUser ()) ... Вы можете вызвать его через interop.

Вот пример кода этого здесь

1 голос
/ 08 апреля 2009

Если вам нужна только анонимная учетная запись, вы можете быть довольно близки - вам просто нужно назначить принцип для потока (вы делаете это из кода, запущенного в потоке, который вы хотите изменить, установив 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;
        }

...