偵測及防範行動應用程式中的帳戶相關詐欺活動

本文說明如何使用 reCAPTCHA 帳戶防禦功能,偵測及防範行動應用程式中的帳戶相關詐欺活動。

reCAPTCHA 可協助您保護重要動作,例如登入和結帳。不過,有許多細微的帳戶濫用行為,可以透過觀察特定使用者在一段時間內於行動應用程式中的行為來偵測。reCAPTCHA 帳戶防禦功能會為您的行動應用程式建立網站專屬模型,偵測可疑行為趨勢或活動變化,協助您識別這類細微的濫用行為。reCAPTCHA 帳戶防護工具會使用網站專屬模型,協助您偵測下列情況:

  • 可疑活動
  • 行為相似的帳戶
  • 來自下列類型裝置的要求:已標為特定使用者信任的來源

根據 reCAPTCHA 帳戶防護和網站專屬模型的分析結果,您可以採取下列行動:

  • 限制或停用詐欺帳戶。
  • 防範帳戶盜用行為。
  • 減少帳戶盜用得逞的案例。
  • 只允許來自正當使用者帳戶的要求。
  • 減少使用者透過信任的裝置登入時遇到的阻礙。

事前準備

  1. 在專案中新增帳單帳戶,觸發自動安全性審查後,即可使用 reCAPTCHA 行動應用程式帳戶防護功能。 在專案中新增帳單帳戶 ,即可將網站加入這項功能。
  2. 準備 reCAPTCHA 環境
  3. 建立以分數為準的金鑰

為 reCAPTCHA 帳戶防護設定行動應用程式

reCAPTCHA 帳戶防護功能需要全面瞭解帳戶活動,才能有效偵測。如要開始將帳戶相關活動提供給 reCAPTCHA 帳戶防護功能,並建立及改善網站專用模型,請按照下列步驟操作:

  1. 將 reCAPTCHA 整合至行動應用程式。

  2. 製作重要使用者動作報表
  3. 評估重要使用者事件
  4. 為使用者事件加上註解,調整網站專屬模型

製作重要使用者動作報表

如要偵測可疑活動模式,並進一步瞭解網站上的一般活動模式,reCAPTCHA 帳戶防護機制需要重要使用者動作的相關資訊。針對應用程式中受 reCAPTCHA 保護的每個動作,請使用 RecaptchaAction 呼叫 execute() 方法。如要進一步瞭解 execute()RecaptchaAction,請參閱下列說明:

reCAPTCHA 提供內建動作集,如有需要,您也可以建立自訂動作。

下表列出您在回報重要使用者動作時可使用的動作名稱。

動作名稱 使用者啟動的事件或使用者動作
LOGIN

登入行動應用程式。

SIGNUP

透過行動應用程式申請。

評估重要使用者事件

在使用者動作中呼叫 execute() 時,系統會產生權杖。針對重要的使用者事件 (例如登入成功/失敗、註冊,以及登入使用者的動作),請建立評估,評估 execute() 呼叫的結果。評估結果會提供風險判定,您可以根據這項判定,決定如何處理潛在的詐欺活動。您可以採取下列行動:封鎖可疑要求、驗證高風險登入行為,以及調查感興趣的帳戶。

如要使用 reCAPTCHA 帳戶防護功能,您必須提供穩定的帳戶 ID,將使用者活動 (例如登入要求、已登入要求和註冊要求) 歸因於特定帳戶。這有助於 reCAPTCHA 帳戶防禦功能瞭解使用者活動模式,並為每個帳戶建立活動模型,以便更準確地偵測異常和濫用流量。

選擇使用者不會經常變更的穩定帳戶 ID accountId,並在 projects.assessments.create 方法中提供。這個穩定帳戶 ID 對於與同一位使用者相關的所有事件,都應具有相同的值。您可以提供下列任一項做為帳戶 ID:

使用者 ID

如果每個帳戶都能與穩定的使用者名稱、電子郵件地址或電話號碼建立專屬關聯,您就可以將這些資訊做為 accountId。當您提供這類跨網站 ID (可在不同網站重複使用的 ID) 時,reCAPTCHA 會使用這項資訊,根據跨網站模型標記濫用帳戶 ID,並運用與這些 ID 相關的跨網站濫用模式知識,加強保護使用者帳戶。

或者,如果每個帳戶都有專屬的內部使用者 ID,您可以將該 ID 提供為 accountId

雜湊處理或加密

如果沒有與每個帳戶唯一相關聯的內部使用者 ID,您可以將任何穩定 ID 轉換為不透明的網站專屬帳戶 ID。reCAPTCHA 帳戶防護功能仍需使用這個 ID 瞭解使用者活動模式並偵測異常行為,但不會與其他網站共用。

請挑選任何穩定的帳戶 ID,並使用加密或雜湊處理方式,在傳送至 reCAPTCHA 前將其設為不透明:

  • 加密 (建議):使用確定性加密方法加密帳戶 ID,產生穩定的密文。如需詳細操作說明,請參閱「以決定性方式加密資料」。選擇對稱式加密而非雜湊處理時,您不需要保留使用者 ID 與對應不透明使用者 ID 之間的對應關係。解密 reCAPTCHA 傳回的不透明 ID,將其轉換為使用者 ID。

  • 雜湊處理:建議使用 SHA256-HMAC 方法,並搭配您選擇的自訂鹽值,對帳戶 ID 進行雜湊處理。由於雜湊值只能單向轉換,您必須保留產生的雜湊值與使用者 ID 之間的對應關係,才能將傳回的雜湊帳戶 ID 對應回原始帳戶。

除了為所有帳戶相關要求提供穩定的帳戶 ID,您還可以為特定要求提供其他帳戶 ID (可能不穩定)。除了 accountId 之外,您還可提供特定情境的帳戶 ID,協助 reCAPTCHA Account Defense 瞭解使用者活動,並偵測帳戶入侵嘗試,確保使用者帳戶安全。提供額外 ID 後,reCAPTCHA 會根據跨網站模型,標記濫用帳戶 ID,並運用與這些 ID 相關的跨網站濫用模式知識,加強保護使用者帳戶。例如,您可以提供下列資訊:

  • 用於登入要求的登入代碼,可以是使用者名稱、電子郵件地址或電話號碼

  • 已通過驗證的電子郵件地址或電話號碼,用於多重驗證要求

  • 使用者在帳戶更新要求中提供的電子郵件地址或電話號碼 (主要或次要)

  • 使用者在註冊要求期間提供的電子郵件地址和電話號碼

在所有與帳戶相關的請求中,將所選的穩定帳戶 ID 附加至 projects.assessments.create 方法的 accountId 參數。選用:在評估中,使用 userIds 欄位為相關要求提供其他帳戶 ID。

使用任何要求資料之前,請先替換以下項目:

  • PROJECT_ID:您的 Google Cloud 專案 ID
  • TOKEN:從 execute() 呼叫傳回的權杖
  • KEY_ID:與應用程式相關聯的 reCAPTCHA 金鑰
  • ACCOUNT_ID:與使用者帳戶建立專屬關聯的 ID,可將使用者帳戶連結至應用程式
  • EMAIL_ADDRESS:選用。與這項要求相關聯的電子郵件地址 (如有)
  • PHONE_NUMBER:選用。與這項要求相關聯的電話號碼 (如有)
  • USERNAME:選用。與這項要求相關聯的使用者名稱 (如有)

HTTP 方法和網址:

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

JSON 要求內文:

{
  "event": {
    "token": "TOKEN",
    "siteKey": "KEY_ID",
    "userInfo": {
      "accountId": "ACCOUNT_ID",
      "userIds": [
        {
          "email": "EMAIL_ADDRESS"
        },
        {
          "phoneNumber": "PHONE_NUMBER"
        },
        {
          "username": "USERNAME"
        }
      ]
    }
  }
}

如要傳送要求,請選擇以下其中一個選項:

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 回覆:

{
  "tokenProperties": {
    "valid": true,
    "androidPackageName": "com.example.app" or "iosBundleId": "com.example.app",
    "action": "login",
    "createTime": "2019-03-28T12:24:17.894Z"
  },
  "riskAnalysis": {
    "score": 0.6,
  },
  "event": {
    "token": "TOKEN",
    "siteKey": "KEY",
    "userInfo": {
      "accountId": "ACCOUNT_ID"
    }
  },
  "name": "projects/PROJECT_NUMBER/assessments/b6ac310000000000",
  "accountDefenderAssessment": {
    "labels": ["SUSPICIOUS_LOGIN_ACTIVITY"]
  }
}

程式碼範例

Java

如要向 reCAPTCHA 進行驗證,請設定應用程式預設憑證。詳情請參閱「為本機開發環境設定驗證機制」。


import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
import com.google.protobuf.ByteString;
import com.google.recaptchaenterprise.v1.AccountDefenderAssessment.AccountDefenderLabel;
import com.google.recaptchaenterprise.v1.Assessment;
import com.google.recaptchaenterprise.v1.CreateAssessmentRequest;
import com.google.recaptchaenterprise.v1.Event;
import com.google.recaptchaenterprise.v1.ProjectName;
import com.google.recaptchaenterprise.v1.RiskAnalysis.ClassificationReason;
import com.google.recaptchaenterprise.v1.TokenProperties;
import com.google.recaptchaenterprise.v1.UserId;
import com.google.recaptchaenterprise.v1.UserInfo;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class AccountDefenderAssessment {

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

    // recaptchaSiteKey: Site key obtained by registering a domain/app to use recaptcha
    // services.
    String recaptchaSiteKey = "recaptcha-site-key";

    // token: The token obtained from the client on passing the recaptchaSiteKey.
    // To get the token, integrate the recaptchaSiteKey with frontend. See,
    // https://cloud.google.com/recaptcha-enterprise/docs/instrument-web-pages#frontend_integration_score
    String token = "recaptcha-token";

    // recaptchaAction: The action name corresponding to the token.
    String recaptchaAction = "recaptcha-action";

    // Unique ID of the user, such as email, customer ID, etc.
    String accountId = "default" + UUID.randomUUID().toString().split("-")[0];

    // User phone number
    String phoneNumber = "555-987-XXXX";

    // User email address
    String emailAddress = "john.doe@example.com";

    accountDefenderAssessment(projectId, recaptchaSiteKey, token, recaptchaAction, accountId, phoneNumber, emailAddress);
  }

  /**
   * This assessment detects account takeovers. See,
   * https://cloud.google.com/recaptcha-enterprise/docs/account-takeovers The input is the hashed
   * account id. Result tells if the action represents an account takeover. You can optionally
   * trigger a Multi-Factor Authentication based on the result.
   */
  public static void accountDefenderAssessment(
      String projectId,
      String recaptchaSiteKey,
      String token,
      String recaptchaAction,
      String accountId,
      String phoneNumber,
      String emailAddress)
      throws IOException {
    try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {

      // Set the properties of the event to be tracked.
      Event.Builder eventBuilder =
          Event.newBuilder()
              .setSiteKey(recaptchaSiteKey)
              .setToken(token);

      // Set the account id, email address and phone number (of the user).
      eventBuilder.setUserInfo(
        UserInfo.newBuilder()
          .setAccountId(accountId)
          .addUserIds(UserId.newBuilder().setEmail(emailAddress))
          .addUserIds(UserId.newBuilder().setPhoneNumber(phoneNumber)));

      Event event = eventBuilder.build();

      // Build the assessment request.
      CreateAssessmentRequest createAssessmentRequest =
          CreateAssessmentRequest.newBuilder()
              .setParent(ProjectName.of(projectId).toString())
              .setAssessment(Assessment.newBuilder().setEvent(event).build())
              .build();

      Assessment response = client.createAssessment(createAssessmentRequest);

      // Check integrity of the response token.
      if (!checkTokenIntegrity(response.getTokenProperties(), recaptchaAction)) {
        return;
      }

      // Get the reason(s) and the reCAPTCHA risk score.
      // For more information on interpreting the assessment,
      // see: https://cloud.google.com/recaptcha-enterprise/docs/interpret-assessment
      for (ClassificationReason reason : response.getRiskAnalysis().getReasonsList()) {
        System.out.println(reason);
      }
      float recaptchaScore = response.getRiskAnalysis().getScore();
      System.out.println("The reCAPTCHA score is: " + recaptchaScore);
      String assessmentName = response.getName();
      System.out.println(
          "Assessment name: " + assessmentName.substring(assessmentName.lastIndexOf("/") + 1));

      // Get the Account Defender result.
      com.google.recaptchaenterprise.v1.AccountDefenderAssessment accountDefenderAssessment =
          response.getAccountDefenderAssessment();
      System.out.println(accountDefenderAssessment);

      // Get Account Defender label.
      List<AccountDefenderLabel> defenderResult =
          response.getAccountDefenderAssessment().getLabelsList();
      // Based on the result, can you choose next steps.
      // If the 'defenderResult' field is empty, it indicates that Account Defender did not have
      // anything to add to the score.
      // Few result labels: ACCOUNT_DEFENDER_LABEL_UNSPECIFIED, PROFILE_MATCH,
      // SUSPICIOUS_LOGIN_ACTIVITY, SUSPICIOUS_ACCOUNT_CREATION, RELATED_ACCOUNTS_NUMBER_HIGH.
      // For more information on interpreting the assessment, see:
      // https://cloud.google.com/recaptcha-enterprise/docs/account-defender#interpret-assessment-details
      System.out.println("Account Defender Assessment Result: " + defenderResult);
    }
  }

  private static boolean checkTokenIntegrity(
      TokenProperties tokenProperties, String recaptchaAction) {
    // Check if the token is valid.
    if (!tokenProperties.getValid()) {
      System.out.println(
          "The Account Defender Assessment call failed because the token was: "
              + tokenProperties.getInvalidReason().name());
      return false;
    }

    // Check if the expected action was executed.
    if (!tokenProperties.getAction().equals(recaptchaAction)) {
      System.out.printf(
          "The action attribute in the reCAPTCHA tag '%s' does not match "
              + "the action '%s' you are expecting to score",
          tokenProperties.getAction(), recaptchaAction);
      return false;
    }
    return true;
  }
}

解讀重大使用者事件的風險判定結果

啟用 Account Defense 後建立評估時,Account Defense 會在評估回應中傳回 accountDefenderAssessmentaccountDefenderAssessment 的值有助於評估使用者活動屬於正當或詐欺行為。此外,這個方法也會傳回評估 ID,您必須在註解使用者事件時使用這個 ID。

以下是 JSON 回應範例:

{
  "tokenProperties": {
    "valid": true,
    "androidPackageName": "com.example.app" or "iosBundleId": "com.example.app",
    "action": "login",
    "createTime": "2019-03-28T12:24:17.894Z"
   },
  "riskAnalysis": {
    "score": 0.6,
  },
 "event": {
    "token": "TOKEN",
    "siteKey": "KEY_ID",
    "expectedAction": "USER_ACTION"
  },
  "name": "projects/PROJECT_ID/assessments/b6ac310000000000X",
  "accountDefenderAssessment": {
    labels: ["SUSPICIOUS_LOGIN_ACTIVITY"]
  }
}

accountDefenderAssessment 欄位可包含下列任一值:

說明
SUSPICIOUS_LOGIN_ACTIVITY 表示要求極有可能涉及憑證填入或帳戶盜用。
SUSPICIOUS_ACCOUNT_CREATION 表示要求代表高風險的濫用帳戶建立行為。
PROFILE_MATCH

表示使用者的屬性與這位使用者先前看到的屬性相符。這個值表示使用者目前使用的裝置是先前用來存取行動應用程式的信任裝置。

只有在下列情況下,系統才會傳回 PROFILE_MATCH

  • 您使用多重驗證(MFA) 或雙重驗證(2FA),且 reCAPTCHA 帳戶防護會在使用者通過 MFA 或 2FA 驗證後,將使用者設定檔標示為可信任。
  • 您可以將評估結果標註為 LEGITIMATEPASSED_TWO_FACTOR,reCAPTCHA 帳戶防護功能會將相應的使用者設定檔標示為信任。

為事件加上註解,調整網站專屬模型

如要向 reCAPTCHA 帳戶防護提供更多資訊,並改善網站專屬的偵測模型,您必須建立評估,為評估的事件加上註解。

如要加註評估,請使用評估 ID,向 projects.assessments.annotate 方法傳送要求。在該要求的內文中,您會加入標籤,提供評估中所述事件的額外資訊。

如要為評估作業加上註解,請按照下列步驟操作:

  1. 視用途而定,決定要在要求 JSON 主體中新增的資訊和標籤。

    下表列出可用於註解事件的標籤和值:

    標籤 說明 要求範例
    reasons 這是必要旗標,可協助您進行評估的標籤。

    在活動發生後幾秒或幾分鐘內,於 reasons 標籤中提供即時活動詳細資料,因為這些資料會影響即時偵測。

    如需可能值的清單,請參閱原因值

    示例:如要偵測帳戶遭盜用,請使用 CORRECT_PASSWORDINCORRECT_PASSWORD 值,為輸入的密碼是否正確加上註解。如果您部署了自己的 MFA,可以新增下列值:INITIATED_TWO_FACTOR,以及 PASSED_TWO_FACTORFAILED_TWO_FACTOR

          {
          "reasons": ["INCORRECT_PASSWORD"]
          }
        
    annotation (選用步驟) 標籤,用於指出評估的合法性。

    提供登入和註冊事件的相關事實,以驗證或修正 annotation 標籤中的風險評估。

    可能的值:LEGITIMATEFRAUDULENT

    您可以隨時傳送這項資訊,也可以將其納入批次作業。 不過,建議您在事件發生後幾秒或幾分鐘內傳送這項資訊,因為這會影響即時偵測。

          {
           "annotation": "LEGITIMATE"
          }
    
      
    accountId

    (選用步驟) 將帳戶 ID 與事件建立關聯的標籤。

    如果您建立評估時沒有帳戶 ID,請使用這個標籤,在有活動帳戶 ID 時提供。

      {
       "accountId": "ACCOUNT_ID"
      }
  2. 使用適當的標籤建立註解要求。

    使用任何要求資料之前,請先替換以下項目:

    • ASSESSMENT_ID:從 projects.assessments.create 呼叫傳回的 name 欄位值。
    • ANNOTATION:選用。標籤,指出評估是否合法或有詐欺行為。
    • REASONS:選用。佐證註解的理由。如需可能值的清單,請參閱原因值
    • ACCOUNT_ID:選用。這個 ID 只會與您應用程式中的使用者帳戶建立關聯。

    詳情請參閱註解標籤

    HTTP 方法和網址:

    POST https://recaptchaenterprise.googleapis.com/v1/ASSESSMENT_ID:annotate

    JSON 要求內文:

    {
      "annotation": ANNOTATION,
      "reasons": REASONS,
      "accountId": ACCOUNT_ID
    }
    

    如要傳送要求,請選擇以下其中一個選項:

    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/ASSESSMENT_ID:annotate"

    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/ASSESSMENT_ID:annotate" | Select-Object -Expand Content

    您應該會收到執行成功的狀態碼 (2xx) 和空白回應。

程式碼範例

Java

如要向 reCAPTCHA 進行驗證,請設定應用程式預設憑證。詳情請參閱「為本機開發環境設定驗證機制」。


import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
import com.google.protobuf.ByteString;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentRequest;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentRequest.Annotation;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentRequest.Reason;
import com.google.recaptchaenterprise.v1.AnnotateAssessmentResponse;
import com.google.recaptchaenterprise.v1.AssessmentName;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

public class AnnotateAccountDefenderAssessment {

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

    // assessmentId: Value of the 'name' field returned from the CreateAssessment call.
    String assessmentId = "account-defender-assessment-id";

    // accountId: Set the accountId corresponding to the assessment id.
    String accountId = "default" + UUID.randomUUID().toString().split("-")[0];

    annotateAssessment(projectID, assessmentId, accountId);
  }

  /**
   * Pre-requisite: Create an assessment before annotating. Annotate an assessment to provide
   * feedback on the correctness of recaptcha prediction.
   */
  public static void annotateAssessment(
      String projectID, String assessmentId, String accountId) throws IOException {

    try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {
      // Build the annotation request.
      // For more info on when/how to annotate, see:
      // https://cloud.google.com/recaptcha-enterprise/docs/annotate-assessment#when_to_annotate
      AnnotateAssessmentRequest annotateAssessmentRequest =
          AnnotateAssessmentRequest.newBuilder()
              .setName(AssessmentName.of(projectID, assessmentId).toString())
              .setAnnotation(Annotation.LEGITIMATE)
              .addReasons(Reason.PASSED_TWO_FACTOR)
              .setAccountId(accountId)
              .build();

      // Empty response is sent back.
      AnnotateAssessmentResponse response = client.annotateAssessment(annotateAssessmentRequest);
      System.out.println("Annotated response sent successfully ! " + response);
    }
  }
}

啟用 reCAPTCHA Account Defense

為 reCAPTCHA 帳戶防護設定行動應用程式後,即可啟用 reCAPTCHA 帳戶防護。

  1. 前往 Google Cloud 控制台的「reCAPTCHA」reCAPTCHA頁面。

    前往 reCAPTCHA

  2. 確認頁面頂端的資源選取器中顯示專案名稱。

    如果沒有看到專案名稱,請按一下資源選取器,然後選取專案。

  3. 按一下「設定」
  4. 在「帳戶防護」窗格中,按一下「設定」

  5. 在「設定帳戶防護」對話方塊中,按一下「啟用」,然後點選「儲存」

啟用 reCAPTCHA 帳戶防護功能後,可能需要幾小時才能在系統中全面生效。這項功能啟用後,系統會開始在評估結果中提供帳戶防禦相關的回應。

後續步驟