É possível enganar esse código de identidade do Windows para usar o usuário errado?

TL; DR O token do usuário pode estar contido em umWindowsIdentityéToken propriedade (digamos,someIdentity.Token) sejam falsificados de modo que:

var validated = new WindowsIdentity(someIdentity.Token);

... retornará uma instância que afirma representar um usuário que, de fato, não foi autenticado e aindaIsAuthenticated conjuntotrueválido.Name e.User propriedades, etc.?

Abaixo, eu coloquei alguns limites nisso; é presumivelmente impossívelcompletamente à prova de falsificação.

A história completa:

Noesta resposta, Damien_The_Unbeliever demonstrou de maneira inteligente que algum código meu poderia ser levado a acreditar que ele tinha um usuário autenticado válido em umWindowsIdentity exemplo quando não. Para encurtar a história, meu código estava assumindo que seThread.CurrentPrincipal.Identity foi uma instância deWindowsIdentity eIsAuthorized estavatrue, que representava um usuário autenticado e eu podia confiar no SID no.User:

WindowsIdentity identity = Thread.CurrentPrincipal == null
    ? null
    : Thread.CurrentPrincipal.Identity as WindowsIdentity;

if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) {
    // ...use and trust the SID in identity.User, the
    // username in identity.Name, etc....
}

(Há uma razão para esse código estar usando o encadeamento em vez deWindowsIdentity.GetCurrent().)

Seu código para enganar isso (ligeiramente modificado):

var ident = WindowsIdentity.GetCurrent();
Thread.CurrentPrincipal = new WindowsPrincipal(ident);
var fakeSid = new SecurityIdentifier("S-1-3-0"/* E.g., some SID you want to trick me into believing is the real user */);
typeof(WindowsIdentity).GetField("m_user", BindingFlags.Instance | BindingFlags.NonPublic)
    .SetValue(ident, fakeSid);

E com certeza, se você fizer isso, chame meu código acima, meu código será enganado. Parabéns Damien.

Assim, na verdadeira moda da corrida armamentista, eis o meu código revisado que captura a paródia e a nega:

WindowsIdentity identity = Thread.CurrentPrincipal == null
    ? null
    : Thread.CurrentPrincipal.Identity as WindowsIdentity;

if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) {
    var validated = new WindowsIdentity(identity.Token);
    if (!validated.User.Equals(identity.User) || !validated.IsAuthenticated || validated.IsAnonymous) {
        // Something fishy is going on, don't trust it
    } else {
        // Good! Use the validated one
        identity = validated;
        // ...use and trust the SID in identity.User, the
        // username in identity.Name, etc....
    }
}

Como você pode ver, é precisoToken a partir da identidade fornecida e cria umNovo WindowsIdentity instância usando esse token. Se os SIDs das identidades corresponderem, continuamos, e, confiando na validada. (Odocumentação paraWindowsIdentity(IntPtr token) diz que o valor inicial deIsAuthenticated seráfalse, mas isso está errado nos meus testes, supondo que eu o criei com um token de usuário válido.)

A única maneira de ver que isso poderia ser enganado seria com um token de usuário falsificado que, no entanto, passa nas validações que o Windows faz com ele. Isso parece improvável para mim. Mas então, esta é uma área de ignorância para mim.

Limites:

Devo notar que estou apenas filmando por umrazoável grau de segurança de logon único aqui, fazendo minha devida diligência. Se um aplicativo mal-intencionado começou a interceptar chamadas do sistema / comprometeu o próprio Windows, bem, não há muito o que eu possa fazer sobre isso. Como Damien apontou nos comentários sobre essa outra pergunta, ele provavelmente poderia criar um contêiner de host que ignorasse completamente a nomenclatura forte (e, portanto, poderia me dar uma ideia completamente falsaWindowsIdentity tipo). Justo. Perfeição mata. Só não quero deixar as portas abertas como a que Damien gentilmente demonstrou. Se eu lançasse um sistema e ele fosse invadido com facilidade, eu ficaria muito envergonhado com isso. :-)

questionAnswers(1)

yourAnswerToTheQuestion