Mendeteksi kebocoran sandi dan kredensial yang diretas

Halaman ini menjelaskan cara menggunakan fitur deteksi kebocoran sandi reCAPTCHA untuk mendeteksi kebocoran sandi dan kredensial yang diretas guna mencegah pengambilalihan akun (ATO) dan serangan credential stuffing. Dengan reCAPTCHA, Anda dapat melakukan audit reguler terhadap kredensial pengguna (sandi) sebagai bagian dari penilaian apa pun untuk memastikan bahwa kredensial tersebut belum bocor atau dilanggar. Untuk melakukan penilaian ini, Google menggunakan fitur Pemeriksaan Sandi.

Sebelum memulai

  1. Siapkan lingkungan Anda untuk reCAPTCHA.

  2. Siapkan reCAPTCHA.

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

    reCAPTCHA mewajibkan penagihan ditautkan dan diaktifkan di project untuk menggunakan fitur deteksi kebocoran sandi. Anda dapat mengaktifkan penagihan menggunakan kartu kredit atau ID penagihan project Google Cloud yang ada. Jika Anda memerlukan bantuan terkait penagihan, hubungi dukungan Penagihan Cloud.

Memeriksa kredensial yang diretas dan bocor

Anda dapat memeriksa apakah kumpulan kredensial telah disusupi dengan menggunakan fungsi kriptografis atau menggunakan penampung Docker.

Penampung Docker adalah klien open source yang mengimplementasikan komputasi multi-pihak yang aman yang diperlukan untuk menjaga privasi pengguna akhir dan mencari kebocoran sandi dengan aman. Untuk mengetahui informasi selengkapnya, lihat Repo GitHub. Penampung Docker membuat abstraksi kompleksitas penerapan algoritma kriptografis dan menyederhanakan proses penginstalan. Layanan ini juga memungkinkan Anda menghosting aplikasi penampung di infrastruktur Anda.

Fungsi kriptografis

Untuk memeriksa apakah kumpulan kredensial telah disusupi, gunakan deteksi kebocoran sandi saat membuat penilaian untuk tindakan seperti login, perubahan sandi, dan reset sandi.

Untuk memeriksa kebocoran sandi dan kredensial yang dilanggar, selesaikan langkah-langkah berikut:

  1. Buat parameter permintaan.
  2. Membuat penilaian untuk mendeteksi kebocoran sandi.
  3. Memverifikasi kredensial yang bocor dari penilaian.
  4. Menafsirkan verdict dan mengambil tindakan.

Membuat parameter permintaan

  1. Hitung parameter permintaan yang diperlukan menggunakan fungsi kriptografis yang diperlukan oleh protokol privasi tinggi. reCAPTCHA menyediakan library Java dan TypeScript untuk membantu membuat kolom ini:

  2. Untuk membuat verifikasi pemeriksaan sandi, buat objek PasswordCheckVerifier.

    PasswordCheckVerifier verifier = new PasswordCheckVerifier();
    
  3. Untuk memulai verifikasi, panggil PasswordCheckVerifier#createVerification. Metode ini menggunakan nama pengguna dan sandi untuk menghitung parameter guna melakukan pemeriksaan sandi.

    PasswordCheckVerification verification = verifier.createVerification("username", "password").get();
    
  4. Buat penilaian menggunakan parameter verifikasi.

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

    Array byte lookupHashPrefix dan encryptedUserCredentialsHash berisi parameter yang diperlukan untuk memulai pemeriksaan sandi Assessment.

Membuat penilaian untuk mendeteksi kebocoran sandi

Gunakan metode projects.assessments.create.

Sebelum menggunakan salah satu data permintaan, lakukan penggantian berikut:

  • PROJECT_ID: project ID Google Cloud Anda
  • LOOKUP_HASH_PREFIX: awalan hash SHA-256 nama pengguna
  • ENCRYPTED_USER_CREDENTIALS_HASH: hash Scrypt kredensial pengguna terenkripsi

Metode HTTP dan URL:

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

Isi JSON permintaan:

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

Untuk mengirim permintaan Anda, pilih salah satu opsi berikut:

curl

Simpan isi permintaan dalam file bernama request.json, dan jalankan perintah berikut:

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

Simpan isi permintaan dalam file bernama request.json, dan jalankan perintah berikut:

$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

Anda akan melihat respons JSON seperti berikut:

{
  "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="]
  }
}

Memverifikasi kredensial yang bocor dari penilaian

Dari respons penilaian, ekstrak kolom reEncryptedUserCredentials dan encryptedLeakMatchPrefixes, lalu teruskan ke objek verifier untuk menentukan apakah kredensial bocor atau tidak.

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

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

Contoh kode

Untuk mempelajari cara menerapkan deteksi kebocoran sandi menggunakan TypeScript, lihat contoh kode TypeScript di GitHub.

Contoh kode berikut menunjukkan cara menerapkan deteksi kebocoran sandi dengan menggunakan Java:

Java

Untuk melakukan autentikasi ke reCAPTCHA, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, lihat Menyiapkan autentikasi untuk lingkungan pengembangan lokal.


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();
    }
  }
}

Penampung Docker

Untuk memeriksa apakah kredensial bocor, kirimkan pasangan kredensial nama pengguna dan sandi dengan aman ke penampung menggunakan koneksi localhost atau dengan menyiapkan HTTPS di penampung. Penampung kemudian mengenkripsi kredensial ini sebelum membuat Permintaan API ke reCAPTCHA, dan memverifikasi hasil yang dienkripsi ulang secara lokal.

Untuk mengirim permintaan ke penampung Docker, selesaikan langkah-langkah berikut:

  1. Siapkan Docker.
  2. Menyiapkan lingkungan untuk penampung Docker.
  3. Buat dan jalankan penampung.
  4. Kirim permintaan HTTP ke penampung.
  5. Menafsirkan verdict dan mengambil tindakan.

Bersiap untuk menjalankan container Docker

  1. Pilih strategi autentikasi.

    Penampung mendukung penetapan Kredensial Default Aplikasi atau dapat menerima Kunci API untuk autentikasi.

  2. Konfigurasikan penampung PLD untuk berjalan dengan HTTPS atau dalam mode demo khusus localhost.

    Karena penampung menerima kredensial pengguna akhir yang sensitif (nama pengguna dan sandi), penampung harus dijalankan dengan HTTPS atau dalam mode demo khusus localhost. Untuk panduan konfigurasi HTTPS, lihat README di GitHub.

Langkah-langkah berikut menggunakan autentikasi kunci API dan menjalankan klien dalam mode demo khusus localhost.

Mem-build dan menjalankan container Docker

  1. Meng-cloning repository

    git clone github.com/GoogleCloudPlatform/reCAPTCHA-PLD
    
  2. Buat container:

    docker build . -t pld-local
    
  3. Mulai penampung:

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

Penampung dimulai dan mulai menayangkan permintaan di port 8080 localhost.

Mengirim Permintaan Localhost

Sebelum menggunakan salah satu data permintaan, lakukan penggantian berikut:

  • LEAKED_USERNAME: nama pengguna pasangan kredensial yang bocor.
  • LEAKED_PASSWORD: sandi pasangan kredensial yang bocor.

Metode HTTP dan URL:

POST http://localhost:8080/createAssessment/

Isi JSON permintaan:

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

Untuk mengirim permintaan Anda, pilih salah satu opsi berikut:

curl

Simpan isi permintaan dalam file bernama request.json, lalu jalankan perintah berikut:

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

PowerShell

Simpan isi permintaan dalam file bernama request.json, lalu jalankan perintah berikut:

$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

Anda akan melihat respons JSON seperti berikut:


  { "leakedStatus":"LEAKED" }


 OR


  { "leakedStatus":"NO_STATUS" }

Menafsirkan verdict dan mengambil tindakan

Respons penilaian menunjukkan apakah kredensial bocor dan memberi Anda informasi yang dapat digunakan untuk mengambil tindakan yang sesuai guna melindungi pengguna.

Tabel berikut mencantumkan tindakan yang direkomendasikan yang dapat Anda lakukan saat sebuah sandi yang bocor terdeteksi:

Sandi bocor terdeteksi Tindakan untuk melindungi pengguna Anda
Selama login
  • Tolak dan minta pelanggan untuk memilih sandi yang berbeda, dan picu tantangan MFA, jika memungkinkan.
  • Ingatkan pengguna untuk menggunakan sandi unik di seluruh akun.
  • Mewajibkan sandi yang kuat di situs Anda.
  • Minta pengguna untuk mengaktifkan autentikasi multi-faktor (MFA) jika mereka tidak menggunakannya.
Selama pembuatan akun atau reset sandi
  • Wajibkan pengguna mengubah sandinya.
  • Memicu alur autentikasi multi-faktor (MFA).

Jika belum menggunakan penyedia MFA di situs, Anda dapat menggunakan kemampuan MFA reCAPTCHA.

Langkah selanjutnya