זיהוי דליפות סיסמאות ופרטי כניסה שנפרצו

התכונה "הגנה על הסיסמה" ב-Google Cloud Fraud Defense מאפשרת לזהות פרטי כניסה שדלפו או נחשפו, כדי להגן על האפליקציות מפני מתקפות של השתלטות על חשבונות (ATO) ודחיסת פרטי כניסה. כחלק מההערכה, אתם יכולים לבדוק את פרטי הכניסה של המשתמשים מול פרצות באבטחת מידע ידועות באמצעות טכנולוגיית בדיקת הסיסמאות של Google.

לפני שמתחילים

  1. הכנת הסביבה ל-Google Cloud Fraud Defense.

  2. הגדרת Fraud Defense.

  3. מוודאים שהחיוב מופעל בפרויקט ב- Google Cloud .

    כדי להשתמש בתכונה "הגנה על הסיסמה" ב-Fraud Defense, צריך לקשר את החיוב לפרויקט ולהפעיל אותו. כדי להפעיל את החיוב, אתם יכולים להשתמש בכרטיס אשראי או במספר לקוח לחיוב קיים של פרויקט Google Cloud . אם אתם צריכים עזרה בנושאי חיוב, פנו לתמיכה בנושא חיוב ב-Cloud.

בדיקה אם פרטי הכניסה נחשפו או הודלפו

אתם יכולים לבדוק אם קבוצה של פרטי כניסה נחשפה באמצעות פונקציות קריפטוגרפיות או באמצעות מאגר Docker.

מאגר Docker הוא לקוח בקוד פתוח שמיישם את החישוב המאובטח רב-המשתתפים שנדרש כדי לשמור על פרטיות משתמשי הקצה ולחפש באופן מאובטח סיסמאות שדלפו. מידע נוסף זמין במאגר GitHub. הקונטיינר של Docker מסתיר את המורכבות של הטמעת האלגוריתמים הקריפטוגרפיים ומפשט את תהליך ההתקנה. היא גם מאפשרת לארח את אפליקציית הקונטיינר בתשתית שלכם.

פונקציה קריפטוגרפית

כדי לבדוק אם פרטי כניסה מסוימים נחשפו, אתם יכולים להשתמש בתכונה "הגנה על הסיסמה" כשאתם יוצרים הערכות לפעולות כמו כניסות, שינויי סיסמאות ואיפוס סיסמאות.

כדי לבדוק אם יש סיסמאות שדלפו ופרטי כניסה שנחשפו, פועלים לפי השלבים הבאים:

  1. יצירת פרמטרים של בקשה.
  2. יצירת הערכה לזיהוי דליפות של סיסמאות.
  3. אימות פרטי כניסה שדלפו באמצעות בדיקה.
  4. הבנת התוצאה וביצוע פעולות.

פרמטרים של בקשה ליצירה

  1. מחשבים את הפרמטרים הנדרשים של הבקשה באמצעות הפונקציות הקריפטוגרפיות שנדרשות על ידי הפרוטוקול לשמירה על רמת פרטיות גבוהה. התכונה "הגנה על הסיסמה" מספקת ספריות Java ו-TypeScript שעוזרות ליצור את השדות האלה:

  2. כדי ליצור אימותים של בדיקת סיסמאות, יוצרים אובייקט PasswordCheckVerifier.

    PasswordCheckVerifier verifier = new PasswordCheckVerifier();
    
  3. כדי להתחיל את תהליך האימות, צריך להתקשר למספר PasswordCheckVerifier#createVerification. בשיטה הזו, שם המשתמש והסיסמה משמשים לחישוב הפרמטרים לביצוע בדיקת הסיסמה.

    PasswordCheckVerification verification = verifier.createVerification("username", "password").get();
    
  4. יוצרים הערכה באמצעות פרמטרים של אימות.

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

    מערכי הבייטים lookupHashPrefix ו-encryptedUserCredentialsHash מכילים את הפרמטרים שנדרשים כדי להתחיל בדיקת סיסמאות Assessment.

יצירת הערכה לזיהוי דליפות של סיסמאות

משתמשים ב-method‏ projects.assessments.create.

לפני שמשתמשים בנתוני הבקשה, צריך להחליף את הנתונים הבאים:

  • ‫PROJECT_ID: מזהה הפרויקט ב- Google Cloud
  • ‫LOOKUP_HASH_PREFIX: תחילית של תחילית הגיבוב (hash) מסוג SHA-256 של שם המשתמש
  • ‫ENCRYPTED_USER_CREDENTIALS_HASH: גיבוב Scrypt מוצפן של פרטי הכניסה של המשתמש

ה-method של ה-HTTP וכתובת ה-URL:

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

גוף בקשת JSON:

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

כדי לשלוח את הבקשה עליכם לבחור אחת מהאפשרויות הבאות:

curl

שומרים את גוף הבקשה בקובץ בשם request.json ומריצים את הפקודה הבאה:

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

שומרים את גוף הבקשה בקובץ בשם request.json ומריצים את הפקודה הבאה:

$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

אתם אמורים לקבל תגובת JSON שדומה לזו:

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

אימות פרטי כניסה שדלפו מתוך הערכה

מחלצים מהתגובה של ההערכה את השדות reEncryptedUserCredentials ו-encryptedLeakMatchPrefixes, ומעבירים אותם לאובייקט המאמת כדי לקבוע אם פרטי הכניסה הודלפו או לא.

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

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

דוגמת קוד

‫Node.js‏ (TypeScript)

כדי ללמוד איך להטמיע את ההגנה על הסיסמה באמצעות Node.js (TypeScript), קראו את דוגמת הקוד של TypeScript ב-GitHub.

Java

כדי לבצע אימות ב-Fraud Defense, צריך להגדיר את Application Default Credentials. למידע נוסף, ראו הגדרת אימות לסביבת פיתוח מקומית.


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;

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 = verification.getLookupHashPrefix();
    byte[] encryptedUserCredentialsHash = 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 -> x.toByteArray())
            .collect(Collectors.toList());

    // Verify if the encrypted credentials are present in the obtained match list.
    PasswordCheckResult result =
        passwordLeak
            .verify(
                verification,
                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();
    }
  }
}

מאגר Docker

כדי לבדוק אם פרטי הכניסה דלפו, שולחים באופן מאובטח את צמד פרטי הכניסה של שם המשתמש והסיסמה לקונטיינר באמצעות חיבור localhost או על ידי הגדרת HTTPS בקונטיינר. לאחר מכן, הקונטיינר מצפין את פרטי הכניסה האלה לפני שהוא שולח בקשת API, ומאמת את התוצאה שהוצפנה מחדש באופן מקומי.

כדי לשלוח בקשות לקונטיינר של Docker:

  1. הגדרת Docker.
  2. הכנת סביבה לקונטיינר של Docker.
  3. יוצרים ומריצים את הקונטיינר.
  4. שליחת בקשות HTTP למאגר.
  5. הבנת התוצאה וביצוע פעולות.

הכנה להרצת הקונטיינר של Docker

  1. בוחרים שיטת אימות.

    הקונטיינר תומך בהגדרה של Application Default Credentials, או יכול לקבל מפתח API לצורך אימות.

  2. מגדירים את מאגר ה-PLD כך שיפעל עם HTTPS או במצב הדגמה של מארח מקומי בלבד.

    מכיוון שהקונטיינר מקבל פרטי כניסה רגישים של משתמשי קצה (שמות משתמשים וסיסמאות), צריך להריץ אותו באמצעות HTTPS או במצב הדגמה של מארח מקומי בלבד. להנחיות לגבי הגדרת HTTPS, קראו את README ב-GitHub.

בשלבים הבאים משתמשים באימות באמצעות מפתח API ומריצים את הלקוח במצב הדגמה של localhost בלבד.

יצירה והפעלה של קונטיינר Docker

  1. משכפלים את המאגר:

    git clone github.com/GoogleCloudPlatform/reCAPTCHA-PLD
    
  2. יוצרים את הקונטיינר:

    docker build . -t pld-local
    
  3. מפעילים את הקונטיינר:

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

הקונטיינר מתחיל לפעול ומגיש בקשות ביציאה 8080 של localhost.

שליחת בקשות ל-localhost

לפני שמשתמשים בנתוני הבקשה, צריך להחליף את הנתונים הבאים:

  • ‫LEAKED_USERNAME: שם המשתמש של זוג פרטי הכניסה שהודלפו.
  • ‫LEAKED_PASSWORD: הסיסמה של זוג פרטי הכניסה שדלפו.

ה-method של ה-HTTP וכתובת ה-URL:

POST http://localhost:8080/createAssessment/

גוף בקשת JSON:

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

כדי לשלוח את הבקשה עליכם לבחור אחת מהאפשרויות הבאות:

curl

שומרים את גוף הבקשה בקובץ בשם request.json ומריצים את הפקודה הבאה:

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

PowerShell

שומרים את גוף הבקשה בקובץ בשם request.json ומריצים את הפקודה הבאה:

$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

אתם אמורים לקבל תגובת JSON שדומה לזו:


  { "leakedStatus":"LEAKED" }


 OR


  { "leakedStatus":"NO_STATUS" }

הבנת התוצאה וביצוע פעולות

התגובה להערכה מראה אם פרטי הכניסה הודלפו, ומספקת מידע שאתם יכולים להשתמש בו כדי לבצע את הפעולות המתאימות להגנה על המשתמשים שלכם.

בטבלה הבאה מפורטות הפעולות המומלצות שאפשר לבצע כשמזוהה סיסמה שדלפה:

זוהתה סיסמה שדלפה פעולות להגנה על המשתמש
במהלך הכניסה לחשבון
  • לדחות את הסיסמה ולדרוש מהלקוח לבחור סיסמה אחרת, ולהפעיל אתגר אימות רב-שלבי (MFA), אם אפשר.
  • להזכיר למשתמש להשתמש בסיסמאות ייחודיות בחשבונות שונים.
  • לדרוש סיסמאות חזקות באתר.
  • אם המשתמש לא משתמש באימות רב-שלבי (MFA), בקשו ממנו להפעיל אותו.
במהלך יצירת החשבון או איפוס הסיסמה
  • לדרוש מהמשתמש לשנות את הסיסמה.
  • להפעיל תהליך של אימות רב-שלבי (MFA).

אם אתם עדיין לא משתמשים בספק MFA באתר, אתם יכולים להשתמש ביכולת ה-MFA של Fraud Defense.

המאמרים הבאים