계정 관련 허위 행위 감지 및 방지

이 문서에서는 reCAPTCHA Enterprise 계정 방어자를 사용하여 계정 관련 사기 활동을 감지하고 방지하는 방법을 설명합니다.

reCAPTCHA Enterprise를 사용하면 로그인이나 결제 같은 중요한 작업을 보호할 수 있습니다. 그러나 미묘한 유형의 계정 악용도 많이 존재하는데, 이런 행동은 일정 기간 동안 사이트에서 특정 사용자의 행동을 관찰해야 탐지할 수 있습니다. reCAPTCHA Enterprise 계정 방어자는 웹사이트에서 의심스러운 사이트 트렌드나 활동의 변화를 감지하기 위해 사이트별 모델을 생성함으로 이러한 유형의 미묘한 악용을 식별하는 데 도움이 됩니다. reCAPTCHA Enterprise 계정 방어자는 사이트별 모델을 사용하여 다음을 감지할 수 있습니다.

  • 의심스러운 활동
  • 활동이 비슷한 계정
  • 특정 사용자에게 신뢰할 수 있다고 표시된 기기에서 들어오는 요청

reCAPTCHA Enterprise 계정 방어자 및 사이트별 모델의 분석을 기반으로 다음을 수행할 수 있습니다.

  • 사기 계정 제한 또는 사용 중지
  • 계정 탈취 시도 방지
  • 성공적인 계정 탈취로 인한 피해 완화
  • 적법한 사용자 계정에서 전송된 요청에만 액세스 권한 부여
  • 신뢰할 수 있는 기기 중 하나에서 로그인하는 사용자의 불편 경감

시작하기 전에

환경에서 reCAPTCHA Enterprise를 설정하는 가장 좋은 방법을 선택하고 설정을 완료합니다.

reCAPTCHA Enterprise 계정 방어자 사용 설정

  1. Cloud Console에서 reCAPTCHA Enterprise 페이지로 이동합니다.

    reCAPTCHA Enterprise로 이동

  2. 페이지 상단의 리소스 선택기에 프로젝트 이름이 표시되는지 확인합니다.

    프로젝트 이름이 표시되지 않으면 리소스 선택기를 클릭한 다음 프로젝트를 선택합니다.

  3. 설정 클릭합니다.

  4. 계정 방어자 창에서 사용 설정을 클릭합니다.

  5. 계정 방어자 구성 대화상자에서 사용 설정을 클릭합니다.

reCAPTCHA Enterprise 계정 방어자 사용 설정이 Google 시스템에 전파되는 데 몇 시간이 걸릴 수 있습니다. 기능 사용 설정이 Google 시스템에 전파되면 평가의 일환으로 계정 방어자와 관련된 응답을 받아야 합니다.

워크플로 이해

reCAPTCHA Enterprise 계정 방어자를 사용하려면 다음 단계를 수행합니다.

  1. 클라이언트(웹페이지 또는 모바일 애플리케이션)에 점수 기반 사이트 키를 설치합니다.
  2. hashedAccountId를 사용하여 평가를 생성합니다.
  3. 평가 세부정보를 해석합니다.
  4. 계정 관련 메타데이터로 평가에 주석을 추가합니다.

이 단계를 완료하면 필요한 경우 유사한 동작으로 계정을 식별할 수 있습니다.

클라이언트에 점수 기반 사이트 키 설치

reCAPTCHA Enterprise 계정 방어자를 사용하려면 다음의 플랫폼별 안내를 따라 로그인 및 등록 페이지에 점수 기반 사이트 키를 설치하세요.

정확한 결과를 얻으려면 로그인 및 결제와 같은 중요한 작업 전후에 표시되는 페이지에 점수 기반 사이트 키를 설치하는 것이 좋습니다. 예를 들어 홈페이지, 로그인 페이지, 웹사이트의 시작 페이지에 방문을 포함하는 고객 워크플로를 생각해 보세요. 이 워크플로에서는 로그인 페이지에 점수 기반 사이트 키를 설치하여 로그인 페이지를 보호합니다. 정확한 결과를 얻으려면 홈페이지와 시작 페이지에 점수 기반 사이트 키를 설치하는 것이 좋습니다.

웹사이트나 모바일 애플리케이션의 다양한 페이지에 고유한 작업이 포함된 점수 기반 사이트 키를 설치하면 reCAPTCHA Enterprise 계정 방어자가 적법한 계정과 허위 계정의 동작을 기반으로 커스텀 사이트별 모델을 만듭니다. 고유한 작업이 포함된 점수 기반 사이트 키를 설치하는 방법은 사용자 작업을 위한 점수 기반 사이트 키 설치를 참조하세요.

hashedAccountId를 사용하여 평가 생성

중요한 작업 평가를 만듭니다. 중요한 작업에는 성공한 로그인과 실패한 로그인, 등록, 로그인한 사용자의 추가 작업이 포함됩니다.

hashedAccountId를 사용하여 평가를 생성하려면 다음을 수행하세요.

  1. SHA256-HMAC 메서드를 사용하여 웹 사이트의 사용자 계정에 안정적인 해시된 고유 사용자 식별자를 생성합니다. 사용자 ID, 사용자 이름 또는 이메일 주소에서 이 식별자를 생성할 수 있습니다.

  2. 해시된 사용자 식별자를 projects.assessments.create 메서드의 hashedAccountId 매개변수에 추가합니다. hashedAccountId를 사용하면 reCAPTCHA Enterprise 계정 방어자에서 허위 계정과 도용된 계정을 감지할 수 있습니다.

    요청 데이터를 사용하기 전에 다음을 바꿉니다.

    • PROJECT_ID: Google Cloud 프로젝트 ID
    • TOKEN: grecaptcha.enterprise.execute() 호출에서 반환 토큰
    • KEY: 사이트/앱과 연결된 reCAPTCHA 키
    • HASHED_ACCOUNT_ID: 웹사이트의 사용자 계정에 대한 SHA256-HMAC 메서드를 사용하여 생성한 해시된 안정적 사용자 식별자

    HTTP 메서드 및 URL:

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

    JSON 요청 본문:

    {
      "event": {
        "token": "TOKEN",
        "siteKey": "KEY",
        "hashedAccountId": "HASHED_ACCOUNT_ID"
      }
    }
    

    요청을 보내려면 다음 옵션 중 하나를 선택합니다.

    curl

    요청 본문을 request.json 파일에 저장하고 다음 명령어를 실행합니다.

    curl -X POST \
    -H "Authorization: Bearer "$(gcloud auth application-default 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 application-default 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,
        "hostname": "www.google.com",
        "action": "login",
        "createTime": "2019-03-28T12:24:17.894Z"
       },
      "riskAnalysis": {
        "score": 0.6,
      },
     "event": {
        "token": "TOKEN",
        "siteKey": "KEY",
        "expectedAction": "USER_ACTION"
      },
      "name": "projects/PROJECT_ID/assessments/b6ac310000000000",
      "accountDefenderAssessment": {
        labels: ["SUSPICIOUS_LOGIN_ACTIVITY"]
      }
    }
    
    

코드 샘플

자바


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 java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;

public class AccountDefenderAssessment {

  public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
    // 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 customer, such as email, customer ID, etc.
    String userIdentifier = "default" + UUID.randomUUID().toString().split("-")[0];

    // Hash the unique customer ID using HMAC SHA-256.
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    byte[] hashBytes = digest.digest(userIdentifier.getBytes(StandardCharsets.UTF_8));
    ByteString hashedAccountId = ByteString.copyFrom(hashBytes);

    accountDefenderAssessment(projectId, recaptchaSiteKey, token, recaptchaAction, hashedAccountId);
  }

  /**
   * 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,
      ByteString hashedAccountId)
      throws IOException {
    try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {

      // Set the properties of the event to be tracked.
      Event event =
          Event.newBuilder()
              .setSiteKey(recaptchaSiteKey)
              .setToken(token)
              // Set the hashed account id (of the user).
              // Recommended approach: HMAC SHA256 along with salt (or secret key).
              .setHashedAccountId(hashedAccountId)
              .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;
  }
}

평가 세부정보 해석

평가를 생성하면 사용자는 다음 JSON 예시와 같은 응답을 수십합니다. reCAPTCHA Enterprise 계정 방어자는 평가 응답의 일부로 accountDefenderAssessment를 반환합니다. accountDefenderAssessment 값은 사용자 활동이 합법적인지 또는 사기인지 평가하는 데 도움이 됩니다.

{
  "tokenProperties": {
    "valid": true,
    "hostname": "www.google.com",
    "action": "login",
    "createTime": "2019-03-28T12:24:17.894Z"
   },
  "riskAnalysis": {
    "score": 0.6,
  },
 "event": {
    "token": "TOKEN",
    "siteKey": "KEY",
    "expectedAction": "USER_ACTION"
  },
  "name": "projects/PROJECT_ID/assessments/b6ac310000000000",
  "accountDefenderAssessment": {
    labels: ["SUSPICIOUS_LOGIN_ACTIVITY"]
  }
}

accountDefenderAssessment 필드에는 다음 값이 포함될 수 있습니다.

  • PROFILE_MATCH: 사용자 속성이 이전에 이 특정 사용자에 표시된 속성과 일치함을 나타냅니다. 이 값은 이 사용자가 이전에 웹사이트에 액세스하는 데 사용한 신뢰할 수 있는 기기에 있음을 나타냅니다.

    PROFILE_MATCH는 다음 시나리오에서만 반환됩니다.

    • 사용자가 다단계(MFA) 또는 2단계 인증(2FA)을 사용할 때 사용자가 MFA 또는 2FA 챌린지를 통과한 후 reCAPTCHA Enterprise 계정 방어자가 사용자 프로필을 신뢰할 수 있는 것으로 표시하는 경우

    • 사용자가 평가를 LEGITIMATE로 주석 처리하며 reCAPTCHA Enterprise 계정 방어자가 해당 사용자 프로필을 신뢰할 수 있는 것으로 표시하는 경우

  • SUSPICIOUS_LOGIN_ACTIVITY: 요청이 이전에 의심스러운 로그인 활동이 있었던 프로필과 일치했음을 나타냅니다. 이 값은 이 요청과 유사한 사용자 인증 정보 스터핑 공격이 있음을 나타냅니다.

  • SUSPICIOUS_ACCOUNT_CREATION: 요청이 이전에 의심스러운 계정 생성 동작이 있었던 프로필과 일치했음을 나타냅니다. 이 값은 계정이 가짜이거나 허위임을 나타낼 수 있습니다.

계정 관련 메타데이터로 평가에 주석 추가

평가에 주석을 달아 reCAPTCHA Enterprise 계정 방어자가 다음 작업을 수행할 수 있게 하세요.

  • 특정 식별자와의 모든 상호작용을 분석하고 정확한 점수와 이유 코드를 반환합니다.
  • 사이트에는 사이트별 공격자 모델을 만듭니다.

평가에 주석을 추가할 때 알려진 이벤트에 라벨을 추가하여 참양성 및 참음성에 대한 주석을 확인합니다. 요청이 적법한지 또는 허위인지 여부를 평가하는 이벤트에 주석을 추가하고 평가 이유를 포함하는 것이 가장 좋습니다. 그러나 이유 없이 이전 평가에 주석을 적용할 수도 있습니다.

평가에 주석을 추가할 때 평가 ID와 함께 요청을 projects.assessments.annotate 메서드로 보냅니다. 요청 본문에 평가에 설명된 이벤트에 대한 추가 정보를 제공하는 라벨을 포함합니다.

평가에 주석을 추가하려면 다음을 수행합니다.

  1. 사용 사례에 따라 요청 JSON 본문에 추가할 라벨을 결정합니다.

    다음 표는 평가 주석을 추가하는 데 사용할 수 있는 라벨을 이해하는 데 도움이 됩니다.

    라벨 설명 샘플 사용 사례
    annotation

    평가 적법성을 나타내는 라벨입니다. 가능한 값은 LEGITIMATE 또는 FRAUDULENT입니다.

    로그인과 같은 중요한 작업의 적법성을 나타내려면 이 라벨을 사용하세요.

    로그인 이벤트가 적법함을 나타내려면 다음 요청 JSON 본문을 사용합니다.

    
    {
    "annotation": "LEGITIMATE"
    }
    
    reasons

    평가를 지원하는 라벨입니다. 가능한 값 목록은 이유 값을 참조하세요.

    이 라벨을 사용하여 중요한 작업의 주석을 지원하는 이유를 제공합니다. 존재하지 않는 계정에 대한 요청에는 INCORRECT_PASSWORD를 사용하는 것이 좋습니다.

    • 실패한 로그인 시도를 구분하려면 다음 요청 JSON 본문을 사용합니다.

      
      {
      "reasons": ["INCORRECT_PASSWORD"]
      }
      
    • 사용자가 2단계 챌린지를 성공적으로 통과했음을 나타내려면 다음 요청 JSON 본문을 사용합니다.

      
      {
      "annotation": "LEGITIMATE",
      "reasons": ["PASSED_TWO_FACTOR"]
      }
      
    hashedAccountId

    해시된 계정 ID를 이벤트와 연결하는 라벨입니다. 해시된 계정 ID는 웹사이트의 사용자 계정에 대한 SHA256-HMAC 방법으로 생성되는 안정적인 해시된 사용자 식별자입니다.

    해시된 계정 ID 없이 평가를 만든 경우 이 라벨을 사용하여 이벤트의 해시된 계정 ID를 제공하세요.

    이벤트가 해시된 계정 ID와 연결되어 있음을 나타내려면 다음 요청 JSON 본문을 사용합니다.

    
    {
    "hashedAccountId": "HASHED_ACCOUNT_ID"
    }
    

  2. 적절한 라벨을 사용하여 주석 요청을 만듭니다.

    요청 데이터를 사용하기 전에 다음을 바꿉니다.

    • ASSESSMENT_ID: projects.assessments.create 호출에서 반환된 name 필드 값입니다.
    • ANNOTATION: (선택사항) 평가가 타당한지 또는 허위인지를 나타내는 라벨입니다.
    • REASONS: 선택사항. 주석을 지원하는 이유입니다. 가능한 값 목록은 이유 값을 참조하세요.
    • HASHED_ACCOUNT_ID: (선택사항) 웹사이트의 사용자 계정에 SHA256-HMAC 메서드를 사용하여 생성한 해시된 안정적 사용자 식별자

    자세한 내용은 주석 라벨을 참조하세요.

    HTTP 메서드 및 URL:

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

    JSON 요청 본문:

    {
      "annotation": ANNOTATION,
      "reasons": REASONS,
      "hashedAccountId": HASHED_ACCOUNT_ID
    }
    

    요청을 보내려면 다음 옵션 중 하나를 선택합니다.

    curl

    요청 본문을 request.json 파일에 저장하고 다음 명령어를 실행합니다.

    curl -X POST \
    -H "Authorization: Bearer "$(gcloud auth application-default 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 application-default 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)와 빈 응답을 받게 됩니다.

코드 샘플

자바


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;

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";

    // hashedAccountId: Set the hashedAccountId corresponding to the assessment id.
    ByteString hashedAccountId = ByteString.copyFrom(new byte[] {});

    annotateAssessment(projectID, assessmentId, hashedAccountId);
  }

  /**
   * 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, ByteString hashedAccountId) 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)
              .setHashedAccountId(hashedAccountId)
              .build();

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

다음 단계