Partager via


Usurpation d'identité

Certains systèmes de fichiers peuvent trouver utile d’effectuer des opérations pour le compte de l’appelant d’origine. Par exemple, un système de fichiers réseau peut avoir besoin de capturer les informations de sécurité de l’appelant au moment de l’ouverture d’un fichier afin qu’une opération ultérieure puisse être effectuée à l’aide des informations d’identification appropriées. Sans aucun doute, il existe de nombreux autres cas spéciaux où ce type de fonctionnalité est utile, à la fois dans un système de fichiers et dans des applications spécifiques.

Les routines clés nécessaires à l’emprunt d’identité sont les suivantes :

  • PsImpersonateClientSeImpersonateClientEx--initie l’emprunt d’identité. Sauf si un thread spécifique est indiqué, l’emprunt d’identité est effectué dans le contexte de thread actuel.

  • PsRevertToSelf--met fin à l’emprunt d’identité dans le contexte de thread actuel.

  • PsReferencePrimaryToken--contient une référence sur le jeton principal (processus) du processus spécifié. Cette fonction peut être utilisée pour capturer le jeton pour n’importe quel processus sur le système.

  • PsDereferencePrimaryToken--libère une référence sur un jeton principal précédemment référencé.

  • SeCreateClientSecurityFromSubjectContext-retourne un contexte de sécurité client utile pour l’emprunt d’identité à partir d’un contexte de sujet (fourni au FSD lors de la gestion de IRP_MJ_CREATE, par exemple).

  • SeCreateClientSecurity crée un contexte de sécurité client basé sur les informations d’identification de sécurité d’un thread existant sur le système.

  • ImpersonateSecurityContext--impersonate le contexte de sécurité dans ksecdd.sys, le service de sécurité du noyau.

  • RevertSecurityContext--met fin à l'usurpation d'identité dans ksecdd.sys, le service de sécurité du noyau.

L'usurpation d'identité est facile à mettre en œuvre. L'exemple de code suivant illustre l'emprunt d'identité élémentaire :

NTSTATUS PerformSpecialTask(IN PFSD_CONTEXT Context)
{
  BOOLEAN CopyOnOpen;
  BOOLEAN EffectiveOnly;
  SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
  NTSTATUS Status;
  PACCESS_TOKEN oldToken;

  //
  // We need to perform a task in the system process context
  //
  if (NULL == Context->SystemProcess) {

    return STATUS_NO_TOKEN;

  }

  //
  // Save the existing token, if any (otherwise NULL)
  //
  oldToken = PsReferenceImpersonationToken(PsGetCurrentThread(),
                                           &CopyOnOpen,
                                           &EffectiveOnly,
                                           &ImpersonationLevel);

  Status = PsImpersonateClient( PsGetCurrentThread(),
                                Context->SystemProcess,
                                TRUE,
                                TRUE,
                                SecurityImpersonation);
  if (!NT_SUCCESS(Status)) {

    if (oldToken)
        PsDereferenceImpersonationToken(oldToken);
    return Status;

  }

  //
  // Perform task - whatever it is
  //


  //
  // Restore to previous impersonation level
  //
  if (oldToken) {
    Status = PsImpersonateClient(PsGetCurrentThread(),
                                 oldToken,
                                 CopyOnOpen,
                                 EffectiveOnly,
                                 ImpersonationLevel);

    if (!NT_SUCCESS(Status)) {
      //
      // This is bad - we can't restore, we can't leave it this way 
      //
      PsRevertToSelf();
    }
    PsDereferenceImpersonationToken(oldToken);
  } else {
    PsRevertToSelf();
  }

  return Status;
}

Il existe de nombreuses variantes de ce code d’emprunt d’identité qui sont disponibles pour les développeurs de systèmes de fichiers, mais cela fournit une illustration de base de la technique.