Détecter les fuites de mots de passe et les vols d'identifiants

Cette page explique comment utiliser la fonctionnalité de détection de fuite de mots de passe de reCAPTCHA pour détecter les fuites de mots de passe et les identifiants volés afin d'empêcher les piratages de compte et les attaques de type "credential stuffing". Avec reCAPTCHA, vous pouvez effectuer des audits réguliers sur les identifiants utilisateur (mots de passe) dans le cadre d'une évaluation afin de vous assurer qu'ils n'ont pas été compromis ou divulgués. Pour effectuer ces évaluations, Google utilise la fonctionnalité de Check-up Mots de passe.

Avant de commencer

  1. Préparez votre environnement pour reCAPTCHA.

  2. Configurez reCAPTCHA.

  3. Make sure that billing is enabled for your Google Cloud project.

    reCAPTCHA exige que la facturation soit associée et activée sur le projet pour utiliser la fonctionnalité de détection des fuites de mots de passe. Vous pouvez activer la facturation à l'aide d'une carte de crédit ou d'un ID de compte de facturation Google Cloud existant. Si vous avez besoin d'aide pour la facturation, contactez l'assistance Cloud Billing.

Vérifier les identifiants compromis et divulgués

Vous pouvez vérifier si un ensemble d'identifiants a été compromis à l'aide de fonctions cryptographiques ou à l'aide du conteneur Docker.

Le conteneur Docker est un client Open Source qui implémente le calcul multipartite sécurisé nécessaire pour préserver la confidentialité des utilisateurs finaux et rechercher de manière sécurisée les fuites de mots de passe. Pour en savoir plus, consultez le dépôt GitHub. Le conteneur Docker abstrait la complexité de l'implémentation des algorithmes cryptographiques et simplifie le processus d'installation. Il vous permet également d'héberger l'application de conteneur dans votre infrastructure.

Fonction cryptographique

Pour vérifier si un ensemble d'identifiants a été compromis, utilisez la détection des fuites de mots de passe lorsque vous créez des évaluations pour des actions telles que les connexions, les modifications et les réinitialisations de mots de passe.

Pour vérifier si des mots de passe ont été divulgués et si des identifiants ont été compromis, procédez comme suit:

  1. Générez des paramètres de requête.
  2. Créez une évaluation pour détecter les fuites de mots de passe.
  3. Vérifier les identifiants divulgués à partir d'une évaluation
  4. Interpréter le résultat et prendre les mesures nécessaires

Générer des paramètres de requête

  1. Calculez les paramètres de requête nécessaires à l'aide des fonctions cryptographiques requises par le protocole haute confidentialité. reCAPTCHA fournit des bibliothèques Java et TypeScript pour vous aider à générer ces champs:

  2. Pour créer des vérifications de mots de passe, créez un objet PasswordCheckVerifier.

    PasswordCheckVerifier verifier = new PasswordCheckVerifier();
    
  3. Pour lancer une validation, appelez PasswordCheckVerifier#createVerification. Cette méthode utilise le nom d'utilisateur et le mot de passe pour calculer les paramètres permettant d'effectuer la vérification du mot de passe.

    PasswordCheckVerification verification = verifier.createVerification("username", "password").get();
    
  4. Créez une évaluation à l'aide des paramètres de vérification.

    byte[] lookupHashPrefix = verification.getLookupHashPrefix();
    byte[] encryptedUserCredentialsHash = verification.getEncryptedUserCredentialsHash();
    

    Les tableaux d'octets lookupHashPrefix et encryptedUserCredentialsHash contiennent les paramètres requis pour lancer une vérification de mot de passe Assessment.

Créer une évaluation pour détecter les fuites de mots de passe

Utilisez la méthode projects.assessments.create.

Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • PROJECT_ID : ID de votre projet Google Cloud
  • LOOKUP_HASH_PREFIX: préfixe du hachage SHA-256 du nom d'utilisateur
  • ENCRYPTED_USER_CREDENTIALS_HASH: hachage Scrypt des identifiants utilisateur chiffrés

Méthode HTTP et URL :

POST https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments

Corps JSON de la requête :

{
  "private_password_leak_verification": {
    "lookup_hash_prefix": "LOOKUP_HASH_PREFIX",
    "encrypted_user_credentials_hash": "ENCRYPTED_USER_CREDENTIALS_HASH"
  }
}

Pour envoyer votre requête, choisissez l'une des options suivantes :

curl

Enregistrez le corps de la requête dans un fichier nommé request.json, puis exécutez la commande suivante :

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments"

PowerShell

Enregistrez le corps de la requête dans un fichier nommé request.json, puis exécutez la commande suivante :

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://recaptchaenterprise.googleapis.com/v1/projects/PROJECT_ID/assessments" | Select-Object -Expand Content

Vous devriez recevoir une réponse JSON de ce type :

{
  "name": "projects/698047609967/assessments/fb22000000000000",
  "score": 0,
  "reasons": [],
  "privatePasswordLeakVerification": {
    "lookupHashPrefix": "zoxZwA==",
    "encryptedUserCredentialsHash": "AyRihRcKaGLj/FA/r2uqQY/fzfTaDb/nEcIUMeD3Tygp",
    "reencryptedUserCredentialsHash": "Aw65yEbLM39ww1ridDEfx5VhkWo11tzn/R1B88Qqwr/+"
    "encryptedLeakMatchPrefixes": [
      "n/n5fvPD6rmQPFyb4xk=", "IVQqzXsbZenaibID6OI=", ..., "INeMMndrfnlf6osCVvs=",
      "MkIpxt2x4mtyBnRODu0=", "AqUyAUWzi+v7Kx03e6o="]
  }
}

Vérifier les identifiants divulgués à partir d'une évaluation

Dans la réponse d'évaluation, extrayez les champs reEncryptedUserCredentials et encryptedLeakMatchPrefixes, puis transmettez-les à l'objet de validation pour déterminer si les identifiants ont été divulgués ou non.

PasswordCheckResult result = verifier.verify(verification,
result.getReEncryptedUserCredentials(),
result.getEncryptedLeakMatchPrefixes()
).get();

System.out.println("Credentials leaked: " + result.areCredentialsLeaked());

Exemple de code

Pour découvrir comment implémenter la détection des fuites de mots de passe à l'aide de TypeScript, consultez l'exemple de code TypeScript sur GitHub.

L'exemple de code suivant montre comment implémenter la détection des fuites de mots de passe à l'aide de Java:

Java

Pour vous authentifier auprès de reCAPTCHA, configurez les Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.


import com.google.cloud.recaptcha.passwordcheck.PasswordCheckResult;
import com.google.cloud.recaptcha.passwordcheck.PasswordCheckVerification;
import com.google.cloud.recaptcha.passwordcheck.PasswordCheckVerifier;
import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
import com.google.protobuf.ByteString;
import com.google.recaptchaenterprise.v1.Assessment;
import com.google.recaptchaenterprise.v1.CreateAssessmentRequest;
import com.google.recaptchaenterprise.v1.PrivatePasswordLeakVerification;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import org.bouncycastle.util.encoders.Base64;

public class CreatePasswordLeakAssessment {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException {
    // TODO(developer): Replace these variables before running the sample.
    // Google Cloud Project ID.
    String projectID = "project-id";

    // Username and password to be checked for credential breach.
    String username = "username";
    String password = "password";

    checkPasswordLeak(projectID, username, password);
  }

  /*
   * Detect password leaks and breached credentials to prevent account takeovers
   * (ATOs) and credential stuffing attacks.
   * For more information, see:
   * https://cloud.google.com/recaptcha-enterprise/docs/check-passwords and
   * https://security.googleblog.com/2019/02/protect-your-accounts-from-data.html

   * Steps:
   * 1. Use the 'create' method to hash and Encrypt the hashed username and
   * password.
   * 2. Send the hash prefix (26-bit) and the encrypted credentials to create
   * the assessment.(Hash prefix is used to partition the database.)
   * 3. Password leak assessment returns a list of encrypted credential hashes to
   * be compared with the decryption of the returned re-encrypted credentials.
   * Create Assessment also sends back re-encrypted credentials.
   * 4. The re-encrypted credential is then locally verified to see if there is
   * a match in the database.
   *
   * To perform hashing, encryption and verification (steps 1, 2 and 4),
   * reCAPTCHA Enterprise provides a helper library in Java.
   * See, https://github.com/GoogleCloudPlatform/java-recaptcha-password-check-helpers

   * If you want to extend this behavior to your own implementation/ languages,
   * make sure to perform the following steps:
   * 1. Hash the credentials (First 26 bits of the result is the
   * 'lookupHashPrefix')
   * 2. Encrypt the hash (result = 'encryptedUserCredentialsHash')
   * 3. Get back the PasswordLeak information from
   * reCAPTCHA Enterprise Create Assessment.
   * 4. Decrypt the obtained 'credentials.getReencryptedUserCredentialsHash()'
   * with the same key you used for encryption.
   * 5. Check if the decrypted credentials are present in
   * 'credentials.getEncryptedLeakMatchPrefixesList()'.
   * 6. If there is a match, that indicates a credential breach.
   */
  public static void checkPasswordLeak(
      String projectID, String username, String password)
      throws ExecutionException, InterruptedException, IOException {

    // Instantiate the java-password-leak-helper library to perform the cryptographic functions.
    PasswordCheckVerifier passwordLeak = new PasswordCheckVerifier();

    // Create the request to obtain the hash prefix and encrypted credentials.
    PasswordCheckVerification verification =
        passwordLeak.createVerification(username, password).get();

    byte[] lookupHashPrefix = Base64.encode(verification.getLookupHashPrefix());
    byte[] encryptedUserCredentialsHash = Base64.encode(
        verification.getEncryptedUserCredentialsHash());

    // Pass the credentials to the createPasswordLeakAssessment() to get back
    // the matching database entry for the hash prefix.
    PrivatePasswordLeakVerification credentials =
        createPasswordLeakAssessment(
            projectID,
            lookupHashPrefix,
            encryptedUserCredentialsHash);

    // Convert to appropriate input format.
    List<byte[]> leakMatchPrefixes =
        credentials.getEncryptedLeakMatchPrefixesList().stream()
            .map(x -> Base64.decode(x.toByteArray()))
            .collect(Collectors.toList());

    // Verify if the encrypted credentials are present in the obtained match list.
    PasswordCheckResult result =
        passwordLeak
            .verify(
                verification,
                Base64.decode(credentials.getReencryptedUserCredentialsHash().toByteArray()),
                leakMatchPrefixes)
            .get();

    // Check if the credential is leaked.
    boolean isLeaked = result.areCredentialsLeaked();
    System.out.printf("Is Credential leaked: %s", isLeaked);
  }

  // Create a reCAPTCHA Enterprise assessment.
  // Returns:  PrivatePasswordLeakVerification which contains
  // reencryptedUserCredentialsHash and credential breach database
  // whose prefix matches the lookupHashPrefix.
  private static PrivatePasswordLeakVerification createPasswordLeakAssessment(
      String projectID,
      byte[] lookupHashPrefix,
      byte[] encryptedUserCredentialsHash)
      throws IOException {
    try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {

      // Set the hashprefix and credentials hash.
      // Setting this will trigger the Password leak protection.
      PrivatePasswordLeakVerification passwordLeakVerification =
          PrivatePasswordLeakVerification.newBuilder()
              .setLookupHashPrefix(ByteString.copyFrom(lookupHashPrefix))
              .setEncryptedUserCredentialsHash(ByteString.copyFrom(encryptedUserCredentialsHash))
              .build();

      // Build the assessment request.
      CreateAssessmentRequest createAssessmentRequest =
          CreateAssessmentRequest.newBuilder()
              .setParent(String.format("projects/%s", projectID))
              .setAssessment(
                  Assessment.newBuilder()
                      // Set request for Password leak verification.
                      .setPrivatePasswordLeakVerification(passwordLeakVerification)
                      .build())
              .build();

      // Send the create assessment request.
      Assessment response = client.createAssessment(createAssessmentRequest);

      // Get the reCAPTCHA Enterprise score.
      float recaptchaScore = response.getRiskAnalysis().getScore();
      System.out.println("The reCAPTCHA score is: " + recaptchaScore);

      // Get the assessment name (id). Use this to annotate the assessment.
      String assessmentName = response.getName();
      System.out.println(
          "Assessment name: " + assessmentName.substring(assessmentName.lastIndexOf("/") + 1));

      return response.getPrivatePasswordLeakVerification();
    }
  }
}

Conteneur Docker

Pour vérifier si des identifiants ont été divulgués, envoyez de manière sécurisée la paire d'identifiants nom d'utilisateur et mot de passe au conteneur à l'aide d'une connexion localhost ou en configurant HTTPS sur le conteneur. Le conteneur chiffre ensuite ces identifiants avant d'envoyer une requête API à reCAPTCHA, puis vérifie le résultat chiffré à nouveau localement.

Pour envoyer des requêtes au conteneur Docker, procédez comme suit:

  1. Configurez Docker.
  2. Préparez un environnement pour le conteneur Docker.
  3. Créez et exécutez le conteneur.
  4. Envoyer des requêtes HTTP au conteneur
  5. Interpréter le résultat et prendre les mesures nécessaires

Préparer l'exécution du conteneur Docker

  1. Choisissez une stratégie d'authentification.

    Le conteneur permet de définir des identifiants par défaut de l'application ou d'accepter une clé API pour l'authentification.

  2. Configurez le conteneur PLD pour qu'il s'exécute avec HTTPS ou en mode démonstration localhost uniquement.

    Étant donné que le conteneur accepte des identifiants d'utilisateur final sensibles (noms d'utilisateur et mots de passe), il doit être exécuté avec HTTPS ou en mode démonstration localhost uniquement. Pour obtenir des conseils sur la configuration HTTPS, consultez le fichier README sur GitHub.

Les étapes suivantes utilisent l'authentification par clé API et exécutent le client en mode démonstration localhost uniquement.

Créer et exécuter le conteneur Docker

  1. Clonez le dépôt :

    git clone github.com/GoogleCloudPlatform/reCAPTCHA-PLD
    
  2. Créez le conteneur :

    docker build . -t pld-local
    
  3. Démarrez le conteneur:

    docker run --network host \
    -e RECAPTCHA_PROJECT_ID=PROJECT_ID \
    -e GOOGLE_CLOUD_API_KEY=API_KEY \
    pld-local
    

Le conteneur démarre et commence à répondre aux requêtes sur le port 8080 de localhost.

Envoyer des requêtes localhost

Avant d'utiliser les données de requête ci-dessous, effectuez les remplacements suivants :

  • LEAKED_USERNAME: nom d'utilisateur de la paire d'identifiants divulgués.
  • LEAKED_PASSWORD: mot de passe de la paire d'identifiants divulgués.

Méthode HTTP et URL :

POST http://localhost:8080/createAssessment/

Corps JSON de la requête :

{
    "username":"LEAKED_USERNAME",
    "password":"LEAKED_PASSWORD"
}

Pour envoyer votre requête, choisissez l'une des options suivantes :

curl

Enregistrez le corps de la requête dans un fichier nommé request.json, puis exécutez la commande suivante :

curl -X POST \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"http://localhost:8080/createAssessment/"

PowerShell

Enregistrez le corps de la requête dans un fichier nommé request.json, puis exécutez la commande suivante :

$headers = @{  }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "http://localhost:8080/createAssessment/" | Select-Object -Expand Content

Vous devriez recevoir une réponse JSON de ce type :


  { "leakedStatus":"LEAKED" }


 OR


  { "leakedStatus":"NO_STATUS" }

Interpréter le résultat et prendre des mesures

La réponse de l'évaluation indique si les identifiants ont été divulgués et vous fournit des informations que vous pouvez utiliser pour prendre les mesures appropriées afin de protéger vos utilisateurs.

Le tableau suivant liste les actions recommandées que vous pouvez effectuer lorsqu'un mot de passe divulgué est détecté:

Mot de passe volé détecté Actions à effectuer pour protéger votre utilisateur
Lors de la connexion
  • Refusez et demandez au client de choisir un autre mot de passe, et déclenchez un défi MFA, si possible.
  • Rappelez à l'utilisateur d'utiliser des mots de passe uniques pour tous ses comptes.
  • Exigez des mots de passe sécurisés sur votre site.
  • Demandez à l'utilisateur d'activer l'authentification multifacteur (MFA) s'il ne l'utilise pas.
Lors de la création d'un compte ou de la réinitialisation du mot de passe
  • Exiger que l'utilisateur modifie son mot de passe
  • Déclencher un flux d'authentification multifacteur (MFA).

Si vous n'utilisez pas encore de fournisseur d'authentification MFA sur votre site, vous pouvez utiliser la fonctionnalité d'authentification multifacteur de reCAPTCHA.

Étape suivante