É 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
conjuntotrue
vá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. :-)