전체 가이드
심각 심각도데이터베이스 보안

Firebase Security Rules: 데이터베이스를 열어 두지 마세요

Firebase 웹 앱은 누구나 볼 수 있는 config 객체를 사용해 브라우저에서 Firestore, Realtime Database, Cloud Storage를 직접 읽고 씁니다. 요청 허용 여부를 결정하는 것은 Security Rules뿐입니다. 테스트 모드로 방치되었거나 모든 것을 허용하도록 느슨해진 규칙은 데이터베이스 전체를 인터넷에 노출합니다.

무엇인가요

Security Rules는 모든 읽기와 쓰기마다 Google 서버에서 평가되는 작은 정책 언어입니다. 각 match 블록은 경로 — 컬렉션, 문서, 스토리지 폴더 — 를 대상으로 하며, allow 문은 어떤 작업을 어떤 조건에서 허용할지 지정합니다. 조건에는 request.auth(누가 요청하는지)와 request.resource.data(무엇을 쓰려는지)를 사용합니다.

apiKey를 포함한 Firebase web config는 프로젝트를 식별할 뿐입니다. 시크릿이 아니며 그 자체로는 접근 권한을 주지 않습니다. 그래서 규칙이 그토록 중요합니다. 어떤 방문자든 여러분의 config로 Firebase SDK를 초기화하고 자신의 브라우저 콘솔에서 데이터베이스를 직접 조회할 수 있습니다.

왜 중요한가요

Firestore의 테스트 모드는 만료일까지 모든 읽기와 쓰기를 허용합니다. 기한이 지나 앱이 멈추면 흔히 쓰는 “해결책”이 allow read, write: if true인데 — 이렇게 하면 모든 문서를 전 세계 누구나 읽고 쓸 수 있게 됩니다. 노출된 Firebase 데이터베이스는 대규모 데이터 유출의 단골 원인이며, 찾아내고 빼내기도 아주 쉽습니다.

request.auth != null만 확인하는 규칙도 크게 낫지 않습니다. 누구나 계정을 만들 수 있고, 익명으로도 가능한 경우가 많아 그대로 모든 사용자의 데이터를 읽을 수 있습니다. 쓰기를 검증하지 않으면 사용자는 절대 제어해서는 안 되는 필드도 수정할 수 있습니다 — 예를 들어 자신의 프로필에 role: "admin"을 설정하는 식입니다.

고치는 방법

열린 규칙을 소유자 기반 규칙으로 바꾸기

기본적으로 거부하고 컬렉션별로 접근을 허용하세요. 이 예에서는 각 사용자가 users에 있는 자신의 문서만 읽고 쓸 수 있으며, 그 밖의 어떤 것에도 접근할 수 없습니다.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth != null
        && request.auth.uid == userId;
    }
    // Every other path is denied by default.
  }
}
사용자가 쓸 수 있는 내용 검증하기

사용자가 변경할 수 있는 필드를 제한해, 스스로 권한을 높이거나 서버가 관리하는 데이터를 조작하지 못하게 하세요. affectedKeys().hasOnly()는 다른 필드를 건드리는 모든 업데이트를 거부합니다.

match /users/{userId} {
  allow update: if request.auth.uid == userId
    && request.resource.data.diff(resource.data)
         .affectedKeys().hasOnly(["displayName", "photoURL"]);
}
재귀 와일드카드와 테스트 모드 규칙 제거하기

규칙에서 넓은 allow와 결합된 match /{document=**}, if true, 그리고 만료되는 테스트 모드 타임스탬프를 찾아보세요. Cloud Storage와 Realtime Database에는 별도의 규칙 파일이 있다는 점을 기억하고, 그것들도 잠그세요.

공격자처럼 규칙 테스트하기

Firebase 콘솔의 Rules Playground나 Emulator Suite와 @firebase/rules-unit-testing을 사용해, 인증되지 않은 사용자로서 그리고 다른 로그인 사용자로서 읽기를 실행해 보세요. 빠른 외부 점검 방법은 인증 없는 REST 요청입니다 — 문서가 반환된다면 그 컬렉션은 공개 상태입니다.

curl "https://firestore.googleapis.com/v1/projects/<project-id>/databases/(default)/documents/users"

자주 묻는 질문

Firebase apiKey는 시크릿인가요?

아니요. Firebase web config의 apiKey는 프로젝트를 식별하며 브라우저로 전달되도록 만들어졌습니다. 데이터는 Security Rules로 보호하고, Google Cloud에서 키를 앱이 실제로 사용하는 API로만 제한해 다른 유료 Google 서비스에 재사용되지 않도록 하세요.

request.auth != null이면 충분한가요?

대부분 그렇지 않습니다. 이는 요청자가 로그인했다는 것만 증명할 뿐, 데이터가 그 사람의 것임을 증명하지는 않습니다. request.auth.uid를 문서 소유자와 비교하거나, 사용자가 스스로 설정할 수 없는 역할을 확인하세요.

AppSafe가 Firebase 규칙을 점검하나요?

AppSafe는 Firebase 프로젝트를 조회하지 않으므로 규칙을 평가할 수 없습니다 — Rules Playground나 위의 curl 점검을 사용하세요. 다만 JavaScript에서 발견된 Google API 키(AIza… 형식)는 표시합니다. 같은 형식이 Maps나 Gemini 같은 유료 서비스에도 쓰이기 때문입니다. Firebase web config라면 정상이니, 키가 제한되어 있는지만 확인하세요.

내 앱도 영향을 받나요?

AppSafe는 이 문제와 수십 가지 다른 문제를 한 번의 무료 스캔으로 점검합니다.

내 앱 무료 스캔