Dado un nombre de usuario y una contraseña, ¿cómo puedo suplantar a ese usuario y ejecutar algún código como ese usuario?¿Cómo hacerse pasar por un usuario en código administrado?
Y por lograron quiero decir sin pinvokes o dllimports
Dado un nombre de usuario y una contraseña, ¿cómo puedo suplantar a ese usuario y ejecutar algún código como ese usuario?¿Cómo hacerse pasar por un usuario en código administrado?
Y por lograron quiero decir sin pinvokes o dllimports
Esta es la clase contenedora creamos que ha funcionado en varias plataformas Windows diferentes:
public class Impersonator
{
// constants from winbase.h
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_LOGON_NETWORK = 3;
public const int LOGON32_LOGON_BATCH = 4;
public const int LOGON32_LOGON_SERVICE = 5;
public const int LOGON32_LOGON_UNLOCK = 7;
public const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
public const int LOGON32_PROVIDER_DEFAULT = 0;
public const int LOGON32_PROVIDER_WINNT35 = 1;
public const int LOGON32_PROVIDER_WINNT40 = 2;
public const int LOGON32_PROVIDER_WINNT50 = 3;
[DllImport("advapi32.dll", SetLastError=true)]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
public static WindowsImpersonationContext LogOn(string userName, string password)
{
return LogOn(userName, password, "");
}
public static WindowsImpersonationContext LogOn(string userName, string password, string domain)
{
WindowsIdentity tempWindowsIdentity;
WindowsImpersonationContext impersonationContext;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if(RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return impersonationContext;
}
}
}
else
{
var win32 = new Win32Exception(Marshal.GetLastWin32Error());
//throw new Exception(string.Format("{0}, Domain:{1}, User:{2}, Password:{3}",
// win32.Message, domain, userName, password));
throw new Exception(win32.Message);
}
}
if(token!= IntPtr.Zero)
CloseHandle(token);
if(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);
return null; // Failed to impersonate
}
public static bool LogOff(WindowsImpersonationContext context)
{
bool result = false;
try
{
if (context != null)
{
context.Undo();
result = true;
}
}
catch
{
result = false;
}
return result;
}
}
Hay una pregunta similar con una gran respuesta here.
Tenga una mirada en WindowsImpersonationContext
de algo más de información (también hay otro gran ejemplo de código allí)
era curioso si se pudiera hacer sin cualquier dllimports – Simon
Si es un sitio web ASP.NET, entonces sí se puede hacer configurando el elemento '
@Simon: la suplantación de identidad también es útil durante las instalaciones o para ejecutar una aplicación "como" otra persona, como un administrador. – AMissico
Ver ImpersonationHelper
de Is it possible to safely get a SecureString value from VB .NET?. El código está listo para producción y robusto.
Es compatible con IDisposable
, contiene un método RunAs
(que tiene un valor incalculable), las contraseñas se manejan como SecureString
, y otras cosas poco útiles. También proporcioné el código de prueba para la clase ImpersonationHelper
y es extremadamente útil para la solución de problemas, y sus métodos de extensión son SecureString
que son útiles.
He hervido se reduce a dos métodos simples:
public bool ImpersonateValidUser(String userName, String domain, String password)
public void UndoImpersonation()
Puede directlyh copiar/pegar la clase de abajo y usarlo en su proyecto:
class ImpersonationContext
{
[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
public const int LOGON32_PROVIDER_WINNT50 = 3;
WindowsImpersonationContext impersonationContext;
public bool ImpersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_WINNT50, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
public void UndoImpersonation()
{
impersonationContext.Undo();
}
}
Claro, se reduce a dos métodos. Sin embargo, su código no tiene ningún error de manejo, y si ocurre un error, no libera los identificadores que creó. – AMissico
Todos los ejemplos que he visto no pueden t Tenga en cuenta el hecho de que el tipo de inicio de sesión no es una solución única para todos.
Por ejemplo, esto solo funcionará si el usuario al que está suplantando tiene permiso para iniciar sesión en el sistema de destino. No siempre es el caso cuando se accede a un cuadro de SQL Server remoto. LOGON32_LOGON_INTERACTIVE
NetworkClearText es el único que funciona de forma consistente para su uso con conexiones de SQL Server. - No hay texto claro no significa que está pasando credenciales de una manera insegura.
Cuando está en un grupo de trabajo y necesita suplantar a un usuario de dominio, NewCredentials es el que funciona. (no probado con conexiones de SQL Server)
funcionó muy bien John. Gracias. – GR7
De nada, silverCORE –
¿Dónde encontraste los valores de LOGON32_PROVIDER_x? –