检测密码泄露和凭据盗用

reCAPTCHA Enterprise 可以检测密码泄露和凭据盗用,以防范帐号盗用 (ATO) 和凭据填充攻击。借助 reCAPTCHA Enterprise,您可以在进行任何评估过程中对用户凭据(密码)进行定期审核,以确保它们没有被泄露或盗用。为了执行这些评估,Google 会使用密码安全检查功能。

准备工作

  1. 选择在您的环境中设置 reCAPTCHA Enterprise 的最佳方法,并完成设置。

  2. 在进行安全审核后,即可访问密码泄露检测功能。请与我们的销售团队联系,在您的网站上启用此功能。

检查凭据是否被盗用和/或泄露

要检查一组凭据是否已遭泄露,请在对操作进行评估期间查询密码安全检查数据库,例如登录和密码更改或重置。

创建评估时,根据规范化过程修改用户名,并使用具有特定盐的 Scrypt 对密码进行哈希处理。

规范化用户名

要规范化用户名,请对用户名使用小写字母,删除网域组件,然后移除所有点,如以下示例所示:

  • canonicalize(foo.bar@COM) = foobar
  • canonicalize(TEST@MAIL.COM) = test

以下代码展示了使用 Python 3 的规范化逻辑的示例。

#!/usr/bin/env python3

def canonicalize_username(username):
  """Canonicalize a username which must be a UTF-8 encoded string."""
  if "@" in username:
    username = username[:username.rfind("@")]
  return username.lower().replace(".", "")

计算 hashed_user_credentials

  1. 计算 Scrypt(canonicalized_username + password + username_updated_salt),其中 username_updated_salt = canonicalized_username + fixed_saltcanonicalized_username 是用户名的规范化版本。

    以下 Python 3 示例显示了固定的盐和 Scrypt 参数。

    #!/usr/bin/env python3
    import base64
    import hashlib
    
    # Scrypt hash salt
    USER_CREDENTIALS_HASH_SALT = [
        48, 118, 42, 210, 63, 123, 161, 155, 248, 227, 66, 252, 161, 167, 141, 6,
        230, 107, 228, 219, 184, 79, 129, 83, 197, 3, 200, 219, 189, 222, 165, 32
    ]
    
    # Scrypt hash parameters and constants
    SCRYPT_HASH_CPU_MEM_COST = 1 << 12
    SCRYPT_HASH_BLOCK_SIZE = 8
    SCRYPT_HASH_PARALLELIZATION = 1
    SCRYPT_MAX_MEMORY = 1024 * 1024 * 32
    SCRYPT_HASH_KEY_LENGTH = 32
    
    def process_credentials(username, password):
      """Process user credentials to be used with the credentials check service."""
    
      canonicalized_username = canonicalize_username(username)
    
      # Compute the salt by appending the username to the fixed hash salt.
      salt = bytes([ord(character) for character in list(canonicalized_username)] +
                   USER_CREDENTIALS_HASH_SALT)
    
      # Compute the data to be hashed
      data = bytes(canonicalized_username + password, encoding="utf8")
    
      # Compute Scrypt hash using hashlib.
      scrypt_hash = hashlib.scrypt(
          password=data,
          salt=salt,
          n=SCRYPT_HASH_CPU_MEM_COST,
          r=SCRYPT_HASH_BLOCK_SIZE,
          p=SCRYPT_HASH_PARALLELIZATION,
          maxmem=SCRYPT_MAX_MEMORY,
          dklen=SCRYPT_HASH_KEY_LENGTH)
      return canonicalized_username, base64.b64encode(scrypt_hash)
    
  2. 要验证您的实现是否正确,请使用以下预期的 base64 编码哈希示例。

     compute_scrypt_hash(`test@domain.com`, `s0m3passw0rd!`) = `1rzih02go6/dNcr1CQu9Ne+x4CC8xqSVuGaSWe+WhWk=`
    

API 请求

只有 v1beta1 端点支持创建用于检测密码泄露和凭据盗用的评估。

使用 projects.assessments.create 方法。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID
  • CANONICALIZED_USERNAME:规范化用户名
  • HASHED_USER_CREDENTIALS:使用 Scrypt 算法进行哈希处理的凭据

HTTP 方法和网址:

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

请求 JSON 正文:

{
  "password_leak_verification": {
    "canonicalized_username": "CANONICALIZED_USERNAME"
    "hashed_user_credentials": "HASHED_USER_CREDENTIALS"
  }
}

如需发送请求,请选择以下方式之一:

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/v1beta1/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/v1beta1/projects/PROJECT_ID/assessments" | Select-Object -Expand Content

您应该收到类似以下内容的 JSON 响应:

{
  "name": "projects/698047609967/assessments/fb22000000000000",
  "score": 0,
  "reasons": [],
  "passwordLeakVerification": {
    "hashedUserCredentials": "IDuS/soXlsLHmOm1A8zw+mChTI561MufdTaqL3k+zC4=",
    "credentialsLeaked": [true | false],
    "canonicalizedUsername": "test"
  }
}