Usurpation d’identité (User Impersonation)

0
721
Usurpation d’identité (User Impersonation)

Cette procédure consiste à changer le contexte de sécurité dans lequel vous vous trouvez. Cela signifie que vous pourrez exécuter du code avec des droits qui correspondent à un autre utilisateur. Cela peut être utilisé pour écrire des fichiers dans un répertoire particulier pour lequel seul un utilisateur a accès.

Exemple d’un cas concret :

Pour une application Web (MVC), il faut que celle-ci écrive dans un répertoire se trouvant sur un autre serveur Web. Cependant pour des règles de sécurité propres au client, il est impossible d’attribuer un utilisateur de l’Active Directory pour l’exécution de l’application pool. Afin de contourner cette règle de sécurité, l’utilisation de l’impersonation peut être utile. Grâce à cela, en créant un utilisateur sur l’Active Directory et en utilisant l’impersonation nous pourrons écrire des fichiers avec cet utilisateur. Voyons en détail la mise en place de l’impersonation. Pour cela, il faut appeler une fonction qui réside dans la DLL advapi32.dll. Il s’agit de la fonction LogonUser.

Syntax du code non managé en C++

BOOL LogonUser(
_In_ LPTSTR lpszUsername,
_In_opt_ LPTSTR lpszDomain,
_In_opt_ LPTSTR lpszPassword,
_In_ DWORD dwLogonType,
_In_ DWORD dwLogonProvider,
_Out_ PHANDLE phToken
);

Vous pouvez retrouver tous les détails de cette méthode ici :
https://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx
Comme il s’agit de code non managé, il faut utiliser l’attribut DLLImport.
Cette utilisation permet de faire appel à la fonction qui réside dans la DLL et de lancer son traitement.

[DllImport("advapi32.dll")]
private static extern bool LogonUser(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

Les trois premiers paramètres sont utiles pour l’authentification de l’utilisateur. Il s’agit simplement du nom de l’utilisateur ainsi que du domaine et évidemment de son mot de passe. Pour les paramètres suivants, vous trouverez les valeurs possibles pour le logon type (dwLogonType) et le provider (dwLogonProvider), dans le fichier WinBase.h. Ce fichier se trouve dans le répertoire suivant : C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include Tableau des valeurs possibles pour le paramètre dwLogonProvider

//
// Logon Support APIs
//
#define LOGON32_LOGON_INTERACTIVE 2
#define LOGON32_LOGON_NETWORK 3
#define LOGON32_LOGON_BATCH 4
#define LOGON32_LOGON_SERVICE 5
#define LOGON32_LOGON_UNLOCK 7
#if(_WIN32_WINNT >= 0x0500)
#define LOGON32_LOGON_NETWORK_CLEARTEXT 8
#define LOGON32_LOGON_NEW_CREDENTIALS 9
#endif // (_WIN32_WINNT >= 0x0500)

Afin d’avoir une utilisation interactive avec le système, l’utilisation du type « LOGON32_LOGON_INTERACTIVE » convient. Donc pour le paramètre dwLogonType qui est un type DWORD la valeur entière 2 sera utilisée.
Tableau des valeurs possibles pour le paramètre dwLogonType

#define LOGON32_PROVIDER_DEFAULT 0
#define LOGON32_PROVIDER_WINNT35 1
#if(_WIN32_WINNT >= 0x0400)
#define LOGON32_PROVIDER_WINNT40 2
#endif /* _WIN32_WINNT >= 0x0400 */
#if(_WIN32_WINNT >= 0x0500)
#define LOGON32_PROVIDER_WINNT50 3
#endif // (_WIN32_WINNT >= 0x0500)
#if(_WIN32_WINNT >= 0x0600)
#define LOGON32_PROVIDER_VIRTUAL 4
#endif // (_WIN32_WINNT >= 0x0600)

Nous utiliserons le provider par défaut (LOGON32_PROVIDER_DEFAULT) ce qui correspond à la valeur 0. Pour ce qui est du phToken, en réalité il s’agit d’un type PHANDLE. Ce type est un pointer d’Handle (descripteur) vers le token. En C# nous utiliserons donc le type IntPtr qui correspondra à ce pointeur. Comme il s’agit d’un paramètre « OUT » nous recevrons grâce au passage en référence le pointeur du token. Le pointeur du Token sera utilisé dans le constructeur de l’objet WindowsIdentity qui représente l’utilisateur.
Grâce à cet objet nous pourrons dès lors faire l’emprunt de l’identité de l’utilisateur en question.

WindowsIdentity newIdentity = newWindowsIdentity(phToken);
_windowsImpersonationContext = newIdentity.Impersonate();

En retour de l’appel de la méthode Impersonate, vous recevrez un WindowsImpersonationContext.
Cela correspond à l’utilisateur avant l’emprunt de son identité. Suite à l’ensemble de ces informations, j’ai créé un objet UserImpersonation. Pour en faire une utilisation correcte et facile cette classe implémente IDisposable. De cette manière, il vous sera facile de l’utiliser via un USING habituel. Cela aura également pour effet d’implémenter un dispose sur l’objet UserImpersonation. Dans ce dispose, la méthode Undo de l’objet WindowsImpersonationContext est appelée, ce qui a pour effet de rétablir le contexte de l’utilsateur. Le token qui vous a été renvoyé lors de la connexion de l’utilisateur doit impérativement être proprement clôturé. Pour se faire, un DLLImport de kernel32.dll doit être effectué et la méthode CloseHandle sera utilisée.

Syntaxe du code non managé en C++
BOOL WINAPI CloseHandle(
_In_ HANDLE hObject
);

Vous pouvez retrouver tous les détails de cette méthode ici :
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
Cette méthode prend en paramètre le Handle du token.

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);

Ce qui nous donne pour le Dipose de l’objet UserImpersonation ceci :

public void Dispose()
{
if (_windowsImpersonationContext != null)
_windowsImpersonationContext.Undo();
if (_tokenHandle != IntPtr.Zero)
CloseHandle(_tokenHandle);
}

Voici un exemple d’utilisation de l’objet.

using (UserImpersonation user = new UserImpersonation("login", "domain","password"))
{
if (user.ImpersonateValidUser())
{
File.WriteAllText("Programmez.txt", "UserImpersonation");
}
}

Vous pourrez constater que le propriétaire du fichier créé est bien l’utilisateur que vous passez en paramètre. Si vous désirez utiliser ce mécanisme, un package Nuget est à votre disposition.
https://www.nuget.org/packages/UserImpersonation/
Le code source est également disponible sur Github.
https://github.com/michelcedric/UserImpersonation
Code complet :

/// <summary>
/// Object to change the user authticated
/// </summary>
public class UserImpersonation : IDisposable
{
/// <summary>
/// Logon method (check athetification) from advapi32.dll
/// </summary>
/// <param name="lpszUserName"></param>
/// <param name="lpszDomain"></param>
/// <param name="lpszPassword"></param>
/// <param name="dwLogonType"></param>
/// <param name="dwLogonProvider"></param>
/// <param name="phToken"></param>
/// <returns></returns>
[DllImport("advapi32.dll")]
private static extern bool LogonUser(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
/// <summary>
/// Close
/// </summary>
/// <param name="handle"></param>
/// <returns></returns>
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
privateWindowsImpersonationContext _windowsImpersonationContext;
private IntPtr _tokenHandle;
private string _userName;
private string _domain;
private string _passWord;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;
/// <summary>
/// Initialize a UserImpersonation
/// </summary>
/// <param name="userName"></param>
/// <param name="domain"></param>
/// <param name="passWord"></param>
public UserImpersonation(string userName, string domain, string passWord)
{
_userName = userName;
_domain = domain;
_passWord = passWord;
}
/// <summary>
/// Valiate the user inforamtion
/// </summary>
/// <returns></returns>
public bool ImpersonateValidUser()
{
bool returnValue = LogonUser(_userName, _domain, _passWord,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
ref _tokenHandle);
if (false == returnValue)
{
return false;
}
WindowsIdentity newId = newWindowsIdentity(_tokenHandle);
_windowsImpersonationContext = newId.Impersonate();
return true;
}
#region IDisposable Members
/// <summary>
/// Dispose the UserImpersonation connection
/// </summary>
public void Dispose()
{
if (_windowsImpersonationContext != null)
_windowsImpersonationContext.Undo();
if (_tokenHandle != IntPtr.Zero)
CloseHandle(_tokenHandle);
}
#endregion
}
Usurpation d’identité (User Impersonation)
Évaluez cet article
PARTAGER SUR
Ayoub Belkadi
Ayoub Belkadi est un consultant et Freelance SEO. Il optimise des sites web pour atteindre la première page de Google en utilisant le référencement naturel Whitehat SEO. Il concois aussi des sites web sous la platforme Wordpress 100% responsive.

Choisir une plateforme pour commenter :

  • Facebook
  • Google Plus
  • Disqus
  • WordPress

LAISSER UNE RÉPONSE

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.