Firebase 자동 생성 API 키의 2024년 5월 restriction은 enabled API를 허용해 새 API enable 시 자동으로 접근권이 확장된다
요약
- 2024년 5월 Firebase는 기존의 unrestricted auto-provisioned API 키를 일괄적으로 "Firebase APIs + currently enabled APIs"로 restrict했다.
- "currently enabled APIs" 조항 때문에 이후 프로젝트에 새 API를 enable하면 기존 키가 silently 그 API에 대한 접근권을 얻는다.
- 결과적으로 클라이언트에 임베드된 키가 유출되어 있을 경우, 새로 enable한 API(예: Gemini)를 통해 과금/데이터 피해가 발생할 수 있다.
본문
2024년 5월 자동 restriction의 정확한 동작
Firebase 공식 문서에 따르면 2024년 5월에 다음 세 종류로 분기 처리됐다:
| 키 종류 | 처리 |
|---|---|
| Firebase auto-provisioned + unrestricted | "Firebase APIs + currently enabled APIs"로 자동 restrict |
| Firebase auto-provisioned + 이미 restricted | 변경 없음 |
| 사용자가 수동 생성한 키 | 변경 없음 |
콘솔 UI에서는 이 키들이 "restricted" 상태로 표시된다. 하지만 진짜 "제한"이 걸린 게 아니라, 그 시점에 활성화된 모든 API를 허용하는 화이트리스트일 뿐이다.
"currently enabled APIs"의 함정
화이트리스트가 그 시점 enable된 API에 묶여 있는 게 아니라, 동적으로 "현재 enable된 API들"을 따른다(혹은 그 시점 enable된 API들의 스냅샷이라도 이후 신규 enable에 대해 별도 가드가 없다). 따라서:
- T 시점: 프로젝트에 API A, B만 enable. 키는 A, B만 허용.
- T+n 시점: API C(예: Generative Language API)를 새로 enable.
- 같은 키가 C도 호출 가능해진다 — 개발자가 키 설정을 건드리지 않아도.
이 동작은 콘솔에서 별도 경고나 notification 없이 일어난다.
Gemini 사례 (Truffle Security 보고)
Truffle Security 분석에 따르면, 과거 "Maps API 키는 공개해도 안전"이라는 Google 가이드에 따라 클라이언트 코드/공개 저장소에 노출되어 있던 키들이 무수히 많다. 어떤 프로젝트에서든 Generative Language API를 enable하는 순간:
- 기존에 노출된 키가 자동으로 Gemini endpoint에 접근 가능
- 공격자가 노출된 키로 다음과 같이 호출 가능:
curl "https://generativelanguage.googleapis.com/v1beta/files?key=$LEAKED_KEY" - 200 OK가 떨어지면 private files 접근, 캐시 데이터 조회, 프로젝트 owner 계정으로 과금 누적
Google은 이미 노출된 키에 대해 retroactive audit/notification을 하지 않았다.
피해 시나리오
- 모바일 앱에 embed된 Firebase API 키 — Play Store APK 추출이나 디컴파일로 누구나 획득 가능
- 웹사이트 source에 노출된 Maps API 키 — view-source: 한 번이면 끝
- 과거 public GitHub commit에 실수로 push된 키 — secret scanning 전 commit에 남음
이 키들이 May 2024 restriction을 받으면 콘솔상 "restricted"로 보이지만, 프로젝트가 Gemini, Vertex AI, 다른 과금 API를 enable하는 순간 그 API들도 호출 가능해진다.
점검 방법
# 키 목록과 restriction 상태
gcloud services api-keys list --project=<PROJECT_ID> --format=json
# 특정 키의 상세 restriction
gcloud services api-keys describe <KEY_ID> --project=<PROJECT_ID>
확인 포인트:
restrictions.apiTargets: 비어있거나 enable된 거의 모든 API가 들어가 있으면 사실상 무제한restrictions.androidKeyRestrictions.allowedApplications: 비어있으면 application restriction 없음 (참고: GCP API 키의 androidKeyRestrictions 빈 객체는 제한이 없는 것과 같다)
콘솔에서 노란 경고(⚠️) 표시는 추가 확인 필요 — restriction이 적용 안 된 상태일 수도 있고, application restriction 누락 등의 다른 이유일 수도 있다.
안전한 설정
May 2024 자동 restriction에 의존하지 말고 명시적으로 좁혀야 한다:
# 1. API Target을 실제 필요한 것으로만 좁힘
gcloud services api-keys update <KEY_ID> \
--api-target=service=firebaseinstallations.googleapis.com \
--api-target=service=firebaseremoteconfig.googleapis.com
# 2. Application Restriction (Android 예시)
gcloud services api-keys update <KEY_ID> \
--allowed-application=sha1_fingerprint=<SHA1>,package_name=<PACKAGE>
핵심은 "enabled APIs 화이트리스트"가 아닌 "필요한 API만 명시한 화이트리스트" 로 바꿔두는 것. 그래야 이후 새 API를 enable해도 이 키로는 호출 불가.
운영 원칙
- 새 API를 enable할 때마다 기존 모든 키의 apiTargets 영향을 점검 (특히 외부 노출 가능성 있는 키)
- Firebase auto-provisioned 키는 "restricted"로 보여도 신뢰하지 말고 직접 좁힐 것
- 노출 가능성이 있는 키는 회전 + apiTargets 좁힘 + Application restriction 3종 세트
- 신규 키는 처음부터 apiTargets와 application restriction을 명시해서 생성
관련 노트
- GCP API 키의 androidKeyRestrictions 빈 객체는 제한이 없는 것과 같다
- GCP API 키 호출자 IP는 Cloud Audit Data Access Log를 켜야 추적할 수 있다
- GCP SA key의 사용 흔적은 private_key_id로 필터링한다