安全でないルールの回避

このガイドでは、Firebase セキュリティ ルール構成における一般的な脆弱性、独自のルールを確認してセキュリティを強化する方法、デプロイする前に変更内容をテストする手順について説明します。

データが適切に保護されていないという警告を受け取った場合は、ここで説明している一般的な過ちを確認し、脆弱なルールがあれば更新してください。

Firebase セキュリティ ルールにアクセスする

既存のセキュリティ ルールを表示するには、Firebase CLI か Firebase コンソールのいずれかを使用します。更新したルールを誤って上書きしないよう、常に同じ手段を使用してルールを編集します。ローカルに定義されたルールが最新の更新を反映しているかどうかわからなくても、Firebase コンソールには常に Firebase セキュリティ ルールの最新のデプロイ済みバージョンが表示されます。

Firebase コンソールからルールにアクセスするには、プロジェクトを選択し、[Realtime Database]、[Cloud Firestore]、または [Storage] のいずれかに移動します。対象のデータベースやストレージ バケットに移動したら、[ルール] をクリックします。

Firebase CLI からルールにアクセスする場合は、firebase.json ファイルに指定されているルールファイルに移動します。

Firebase セキュリティ ルールを理解する

Firebase セキュリティ ルールは、悪意のあるユーザーからデータを保護します。Firebase コンソールでデータベース インスタンスや Cloud Storage バケットを作成する際に、すべてのユーザーに対してアクセスを拒否するか(ロックモード)、すべてのユーザーにアクセス権を付与するか(テストモード)を選択できます。開発中はより自由な構成が必要になることがありますが、十分な時間をかけてルールを適切に構成し、データのセキュリティを確保してからアプリを本番環境にデプロイしてください。

アプリを開発しながらルールのさまざまな構成をテストする際は、ローカル Firebase エミュレータのいずれかを使用して、ローカル開発環境でアプリを実行します。

安全でないルールに関する一般的なシナリオ

デフォルトで設定したセキュリティ ルール、または最初にアプリを開発する際に使用したルールについては、アプリをデプロイする前に確認し、更新する必要があります。以下に説明する陥りがちな落とし穴を避けて、ユーザーのデータを適切に保護してください。

オープン アクセス

Firebase プロジェクトを設定する際、開発中にオープン アクセスを許可するようにルールを設定してしまうことがあります。アプリのユーザーは自分だけだと思いがちですが、アプリをデプロイすると、そのアプリはインターネット上で利用可能な状態になります。ユーザー認証を行っていない場合や、セキュリティ ルールを構成していない場合は、誰でもプロジェクト ID を推測してデータにアクセスし、データを窃取、変更、削除できてしまいます。

非推奨事項: すべてのユーザーに読み取りと書き込みアクセス権を付与する。

Cloud Firestore

// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this ruleset in production; it allows
// anyone to overwrite your entire database.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

Realtime Database

{
  // Allow read/write access to all users under any conditions
  // Warning: **NEVER** use this ruleset in production; it allows
  // anyone to overwrite your entire database.

  "rules": {
    ".read": true,
    ".write": true
  }
}
    

Cloud Storage

// Anyone can read or write to the bucket, even non-users of your app.
// Because it is shared with App Engine, this will also make
// files uploaded via App Engine public.
// Warning: This rule makes every file in your Cloud Storage bucket accessible to any user.
// Apply caution before using it in production, since it means anyone
// can overwrite all your files.

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write;
    }
  }
}
    
解決策: 読み取りと書き込みのアクセス権を制限するルール。

データ階層に合ったルールを構築します。この非安全性に対する一般的な解決策の一つは、Firebase Authentication によるユーザーベースのセキュリティです。詳しくは、ルールを使用したユーザーの認証をご覧ください。

Cloud Firestore

Realtime Database

Cloud Storage

認証されたユーザーのアクセス

ルールによってユーザーがログイン済みであることが確認されますが、その認証に基づき、それ以上はアクセスが制限されないことがあります。いずれかのルールに auth != null が含まれている場合は、ログインしているすべてのユーザーがそのデータにアクセスできても問題ないことを確認します。

非推奨事項: ログインしているすべてのユーザーが、データベース全体に対して読み取りと書き込みのアクセス権を持っている。

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow read, write: if request.auth.uid != null;
    }
  }
}

Realtime Database

{
  "rules": {
    ".read": "auth.uid !== null",
    ".write": "auth.uid !== null"
  }
}

Cloud Storage

// Only authenticated users can read or write to the bucket
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}
解決策: セキュリティ条件を使用してアクセスを制限する。

認証を確認するときは、いずれかの認証プロパティを使用して、特定のユーザーによる特定のデータセットへのアクセスをさらに制限することもできます。さまざまな認証プロパティの詳細については、こちらをご覧ください。

Cloud Firestore

Realtime Database

Cloud Storage

(Realtime Database)ルールの不適切な継承

Realtime Database セキュリティ ルールは、より狭いルールで、より深い子ノードのルールを上書きする親パスをカスケードします。子ノードでルールを書き込むときは、追加の権限しか付与できないことに注意してください。データベースのより深いパスのデータへのアクセスを絞り込んだり取り消したりすることはできません。

非推奨事項: 子パスでのルールの絞り込み
{
  "rules": {
     "foo": {
        // allows read to /foo/*
        ".read": "data.child('baz').val() === true",
        "bar": {
          /* ignored, since read was allowed already */
          ".read": false
        }
     }
  }
}
解決策: 広いルールを親パスで作成し、子パスでより詳細な権限を付与する。より細かくデータアクセスを制限する場合は、ルールも細かくします。Realtime Database セキュリティ ルールのカスケードについては、データのセキュリティ保護をご覧ください。

クローズド アクセス

アプリの開発中における一般的なアプローチとしては、データを遮断するという方法もあります。通常、これは以下のように、すべてのユーザーに対して読み取りと書き取りのアクセス権を拒否することを意味します。

Cloud Firestore

// Deny read/write access to all users under any conditions
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Realtime Database

{
  "rules": {
    ".read": false,
    ".write": false
  }
}
    

Cloud Storage

// Access to files through Cloud Storage is completely disallowed.
// Files may still be accessible through App Engine or Google Cloud Storage APIs.

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}

Firebase Admin SDK と Cloud Functions は、引き続きデータベースにアクセスできます。Firebase Admin SDK と組み合わせて Cloud Firestore や Realtime Database をサーバーのみのバックエンドとして使用する場合は、これらのルールを使用します。これによってセキュリティは確保されますが、アプリのクライアントによって適切にデータが取得されることをテストする必要が生じます。

Cloud Firestore セキュリティ ルールとその仕組みについて詳しくは、Cloud Firestore セキュリティ ルールを使ってみるをご覧ください。

Cloud Firestore セキュリティ ルールをテストする

アプリの動作を確認して Cloud Firestore セキュリティ ルールの構成を検証するには、Firebase エミュレータを使用します。変更をデプロイする前に、Cloud Firestore エミュレータを使用して、ローカル環境で単体テストの実施と自動化を行います。

Firebase コンソールで Firebase セキュリティ ルールをすばやく検証するには、Firebase セキュリティ ルール シミュレータを使用します。