Подтвердить что ты не робот

Является ли это использование System.Security.Principal.WindowsIdentity разумно безопасным?

Является System.Security.Principal.WindowsIdentity разумно защищенным от взлома, так что экземпляр, который я получаю из Thread.CurrentPrincipal Identity или WindowsIdentity.GetCurrent(), который имеет true для IsAuthenticated, дает мой сборка ложной идентификационной информации? Ничто, конечно, не является полностью защищенным от несанкционированного доступа, но, учитывая приверженность Microsoft и зависимость от .Net, я ожидал бы, что критические API-интерфейсы, подобные этому, будут заблокированы и трудно подделать. Является ли это обоснованным предположением с моей стороны?

Моя цель состоит в том, чтобы предоставить единую универсальную SSO в моей сборке. Если сама ОС Windows сама скомпрометирована, это из-под моего контроля, но если (например) это простой вопрос для приложения, связанного с моей сборкой, чтобы подавать мне ложную информацию, это было бы для меня за то, что я не выполнял должную осмотрительность. Это большая область невежества для меня.

Чтобы быть ясным, я ищу твердую информацию, а не мнение о манжетах. Таким образом, опубликованные эксплойты или продемонстрировали использование конструктора WindowsIdentity таким образом, чтобы обмануть мой код и т.д. Или на стороне "это действительное предположение", твердые статьи, поддерживающие его, известные применения, полагающиеся на него, и т.д. Мне не повезло найти их, но я включил то, что я нашел ниже под разделителем.

Вот как я намерен использовать WindowsIdentity:

using System.Security.Principal;
using System.Threading;
// ...

// I only want Windows-authenticated users
WindowsIdentity identity = Thread.CurrentPrincipal == null
    ? null
    : Thread.CurrentPrincipal.Identity as WindowsIdentity;
SecurityIdentifier sid;

// I can't imagine how an authenticated account would be anonymous, but...
if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) {
    // SSO success from thread identity
    sid = identity.User;
    // ...check that that SID is allowed to use our system...
} else {
    identity = WindowsIdentity.GetCurrent();
    if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) {
        // SSO success from current Windows user
        sid = identity.User;
        // ...check that that SID is allowed to use our system...
    } else {
        // SSO fail
    }
}

Это в сборке DLL — к сожалению, мы застряли на .Net 3.5 — который предоставляет публичный API для ресурсов, которые могут быть ограничены правами пользователя. Он может использоваться в настольных приложениях или в приложении ASP.Net IIS с проверкой подлинности Windows (ASP.Net устанавливает экземпляр WindowsIdentity на Thread.CurrentPrincipal.Identity при использовании Windows auth, мы не поддерживаем другие виды IIS-аутентификации в настоящее время).

Могу ли я обоснованно доверять SID из экземпляра WindowsIdentity из тех источников, которые утверждают, что они прошли проверку подлинности?

Мне не приходило в голову задаться вопросом, хорошо ли это (doh!), пока в этом вопросе пользователь lc. выразил обеспокоенность в связи с тем, что сборка будет восприимчива к тому, что ее обманет вредоносное приложение, связанное с ним, и "подделало" эту информацию. У него не было никаких конкретных доказательств, указывающих на то, почему это может быть серьезной проблемой, хотя, следовательно, этот вопрос.


Что (немного), которое я нашел до сих пор:

  • Этот ответ делает заявку

    Вы можете доверять, что текущий WindowsIdentity - это тот, кто говорит, что это так, поскольку вы можете доверять любой данной части данных в своем приложении.

  • Книга Взлом кода утверждает, что ASP.Net требует, чтобы WindowsIdentity был связан с запросом при выполнении файла авторитарная проверка, которая, если истина кажется достаточно прочной основой для высказывания Microsoft, по крайней мере, считает ее достаточно хорошей.

  • Я могу найти множество примеров счастливого использования людьми информации WindowsIdentity в своем коде, но большинство из них не задают вопрос о том, являются ли они безопасными. Там подразумевается, но...

4b9b3361

Ответ 1

Вы не можете доверять одному из Thread.CurrentPrincipal, no. Нет ничего, что могло бы остановить выполнение кода, полностью доверяющего его подделке.

Мне удалось обмануть его в моей среде следующим образом:

var admin = new WindowsIdentity(@"Administrator");
var princ = new WindowsPrincipal(admin);
System.Threading.Thread.CurrentPrincipal = princ;

... перед вызовом кода. На моей машине созданный объект WindowsIdentity имеет IsAuthenticated как true и IsAnonymous false, и поэтому, конечно, ваш код извлекает SID администратора домена.

Это не работает во всех средах, но это должно, при условии, что исполняемый код имеет достаточные разрешения для использования отражения:

var ident = WindowsIdentity.GetCurrent();
Thread.CurrentPrincipal = new WindowsPrincipal(ident);
var userSid = ident.User;

var fakeSid = new SecurityIdentifier("S-1-3-0");

typeof (WindowsIdentity).GetField("m_user",
  BindingFlags.Instance | BindingFlags.NonPublic).SetValue(ident, fakeSid);

(Опять же, сделанный перед вызовом вашего кода.)


В принципе, нет ничего, что могло бы остановить две части кода, работающие под полным доверием внутри одного процесса, от лжи друг к другу.