diff --git a/src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-api-keys-unauthenticated-enum.md b/src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-api-keys-unauthenticated-enum.md index 5a75e14b7..849c91568 100644 --- a/src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-api-keys-unauthenticated-enum.md +++ b/src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-api-keys-unauthenticated-enum.md @@ -4,7 +4,7 @@ ## API Keys -有关 API 密钥的更多信息,请查看: +For more information about API Keys check: {{#ref}} ../gcp-services/gcp-api-keys-enum.md @@ -12,19 +12,19 @@ ### OSINT techniques -**Google API 密钥被任何类型的应用广泛使用**,这些应用从客户端使用。通常可以在网站源代码或网络请求中找到它们,在移动应用中,或者仅仅是在像 Github 这样的平台上搜索正则表达式。 +**Google API Keys are widely used by any kind of applications** that uses from the client side. It's common to find them in for websites source code or network requests, in mobile applications or just searching for regexes in platforms like Github. -正则表达式是:**`AIza[0-9A-Za-z_-]{35}`** +The regex is: **`AIza[0-9A-Za-z_-]{35}`** -例如,可以在 Github 上搜索: [https://github.com/search?q=%2FAIza%5B0-9A-Za-z\_-%5D%7B35%7D%2F\&type=code\&ref=advsearch](https://github.com/search?q=%2FAIza%5B0-9A-Za-z_-%5D%7B35%7D%2F&type=code&ref=advsearch) +Search it for example in Github following: [https://github.com/search?q=%2FAIza%5B0-9A-Za-z\_-%5D%7B35%7D%2F\&type=code\&ref=advsearch](https://github.com/search?q=%2FAIza%5B0-9A-Za-z_-%5D%7B35%7D%2F&type=code&ref=advsearch) ### Check origin GCP project -这对于检查**您找到的 API 密钥属于哪个 GCP 项目**非常有用。我们有不同的选项: +这对于检查**你找到的某个 API key 属于哪个 GCP project** 非常有用。我们有不同的选项: -- 联系 `https://www.googleapis.com/identitytoolkit/v3/relyingparty/getProjectConfig?key=` +- Contact `https://www.googleapis.com/identitytoolkit/v3/relyingparty/getProjectConfig?key=` -为了简洁起见,输出被截断,但在完整输出中,项目 ID 出现了超过 5 次。 +为了简洁,输出被截断了,但在完整输出中,project ID 出现了 5 次以上 ```bash curl -s "https://www.googleapis.com/identitytoolkit/v3/relyingparty/getProjectConfig?key=AIzaSyD[...]uE8Y" @@ -34,9 +34,9 @@ curl -s "https://www.googleapis.com/identitytoolkit/v3/relyingparty/getProjectCo "message": "Identity Toolkit API has not been used in project 943955951114 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/identitytoolkit.googleapis.com/overview?project=943955951114 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.", [...] ``` -- 联系 `https://www.googleapis.com/identitytoolkit/v3/relyingparty/getProjectConfig?key=` +- 访问 `https://identitytoolkit.googleapis.com/v1/projects?key=` -为了简洁起见,输出被截断,但在完整输出中,项目 ID 出现了超过 5 次。 +为了简洁,输出被截断了,但在完整输出中,project ID 出现了超过 5 次 ```bash curl -s "https://identitytoolkit.googleapis.com/v1/projects?key=AIzaSyD[...]uE8Y" @@ -46,7 +46,7 @@ curl -s "https://identitytoolkit.googleapis.com/v1/projects?key=AIzaSyD[...]uE8Y "message": "Identity Toolkit API has not been used in project 943955951114 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/identitytoolkit.googleapis.com/overview?project=943955951114 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.", [...] ``` -- [这个不再有效了!] `apikeys.keys.lookup` +- [这个现在不再可用!] `apikeys.keys.lookup` ```bash # If you have permissions gcloud services api-keys lookup AIzaSyD[...]uE8Y @@ -69,8 +69,99 @@ resource: projects/89123452509 service: cloudresourcemanager.googleapis.com reason: AUTH_PERMISSION_DENIED ``` -### 暴力破解 API 端点 +### 基于 Discovery-document 的 API recon -由于您可能不知道项目中启用了哪些 API,因此运行工具 [https://github.com/ozguralp/gmapsapiscanner](https://github.com/ozguralp/gmapsapiscanner) 并检查 **您可以使用 API 密钥访问的内容** 将会很有趣。 +一旦你有了有效的 key,不要只测试显而易见的 public APIs。在 Google 环境中,**discovery documents** 可以作为一种 machine-readable 的 attack-surface map,暴露 **resources, methods, paths, HTTP verbs, parameters, and request/response schemas**。 + +Useful targets: +```bash +# Public / common path +curl -s 'https://serviceusage.googleapis.com/$discovery/rest?key=' + +# Hidden docs behind a visibility label +curl -s 'https://serviceusage.googleapis.com/$discovery/rest?labels=GOOGLE_INTERNAL&key=' +``` +Notes: + +- 比较文档大小和 method count,区分是否带有诸如 `GOOGLE_INTERNAL` 之类的 labels。 +- 一个 **true nonexistent method** 通常会返回一个 **HTML 404**。带有 `Method not found.` 的 **JSON 404** 可能表示该 method 确实存在,但 **API key project 缺少所需的 visibility label**。 +- 一些 first-party APIs 通过 `*.clients6.google.com` 或 undocumented `*-pa.googleapis.com` hosts 访问,比通过 public API explorer 更容易。 + +这对于枚举 **internal/admin APIs accidentally exposed to the Internet** 以及基于 schema 构建 custom fuzzers、而不是手动猜测 JSON fields,特别有用。 + +### Key ownership filtering at scale + +如果你从 APKs、browser traffic、IPAs 或 binaries 中收集了很多 Google API keys,你可能会想快速识别 **每个 key 属于哪个 project**,以及它是否属于目标公司。 + +一个实用技巧是故意调用一个对该 key **not enabled** 的 API。Google 经常会在错误中泄露后端的 **project number**: +```bash +curl -s 'https://protos.googleapis.com/$discovery/rest?key=' +``` +寻找如下消息: +```text +Protos API has not been used in project 244648151629 before or it is disabled +``` +该 project number 随后可以与其他 endpoints、leaked metadata 或 internal company-mapping logic 关联起来,以便将 **in-scope first-party keys** 与 customer / third-party projects 区分开来。 + +### 在丢弃 key 之前先处理 key restrictions + +一个 restricted key 不一定没用。保留找到该 key 的上下文,并使用匹配的 headers 重放请求: +```bash +# Browser restricted +curl -H 'X-Goog-Api-Key: ' \ +-H 'Referer: https://target.google.com' \ +'https://servicemanagement.googleapis.com/v1/operations' + +# iOS restricted +curl -H 'X-Goog-Api-Key: ' \ +-H 'X-Ios-Bundle-Identifier: com.google.GoogleMobile' \ +'https://servicemanagement.clients6.google.com/v1/operations' + +# Android restricted +curl -H 'X-Goog-Api-Key: ' \ +-H 'X-Android-Package: com.google.android.settings.intelligence' \ +-H 'X-Android-Cert: ' \ +'https://servicemanagement.clients6.google.com/v1/operations' +``` +常见限制类型: + +- **HTTP Referer** +- **iOS bundle ID** (`X-Ios-Bundle-Identifier`) +- **Android package + signing cert** (`X-Android-Package` + `X-Android-Cert`) +- **Server IP** 限制,通常无法远程绕过 + +### first-party auth / origin whitelist 提示 + +一些 Google web APIs 接受 **session cookie + first-party authorization headers** 的组合,并托管在 `*.clients6.google.com` 上。在测试这些 APIs 时: + +- 保持 `Origin` 和 `Referer` 与通常使用该 API 的产品兼容。 +- 带有 `reason: SESSION_COOKIE_INVALID` 的 `401` 实际上可能表示 **origin 没有被加入白名单**,而不是 cookie 有问题。 +- 只能接受内部 origins(例如 `*.corp.google.com`)但又可被公开访问的 APIs,是 broken access control review 的高价值候选目标。 + +### 对已启用 APIs 进行 brute force 并 fuzz 文档化 methods + +由于你可能不知道项目中启用了哪些 APIs,运行工具 [https://github.com/ozguralp/gmapsapiscanner](https://github.com/ozguralp/gmapsapiscanner) 并检查**使用该 API key 你能访问什么** 会很有意思。 + +在识别出可达的 services 后,优先使用**基于 schema 的 fuzzing**,而不是盲猜: + +- 直接从 discovery docs 生成请求 +- 用**所有已知可用的 keys** 重放同一个请求 +- 规范化错误,以便区分**无效输入**与**visibility-label / auth / restriction** 失败 +- 对数值型 object identifiers,尝试附近的值,例如 `ID-1`、`ID+1`、`1`、`2`、`100`、`1000` +- 只有在你确认了**跨用户 data access** 或其他真实的 authorization failure 时才报告;单纯 enumeration 本身通常还不够 + +### 常见 vuln 模式:unauthenticated direct-object reference + +一个常见的 bug 模式是:**internal/admin API** 接受一个由 victim 控制的 identifier(例如 `gaiaId`),并且只验证请求携带了可用的 API key,但**从不检查调用者是否被授权访问该特定 object**。 +```bash +curl 'https://gfibervoice-pa.googleapis.com/v1/BssGetVoiceSettings?gaiaId=' \ +-H 'X-Goog-Api-Key: ' +``` +如果该 endpoint 返回另一个用户的电话号码、email address、settings 或其他 private fields,则将其视为经典的 **IDOR / broken access control** issue。 + +## References + +- [Hacking Google with AI: AI-Assisted Discovery-Document Fuzzing of Google APIs](https://brutecat.com/articles/hacking-google-with-ai) +- [Google APIs Explorer](https://developers.google.com/apis-explorer) {{#include ../../../banners/hacktricks-training.md}}