Firebase セキュリティ チェックリスト

Firebase リソースとユーザーのデータを安全に保つには、次のガイドラインに従ってください。すべての項目が必ずしも要件に当てはまるわけではありませんが、アプリを開発する際はそれらに留意してください。

不正なトラフィックを避ける

バックエンド サービスのモニタリングとアラートを設定する

サービス拒否(DoS)攻撃などの不正なトラフィックを検出するには、Cloud FirestoreRealtime DatabaseCloud StorageHosting のモニタリングとアラートを設定します。

アプリケーションへの攻撃が疑われる場合は、できるだけ早くサポートに連絡して、何が起こっているのかを知らせてください。

App Check を有効にする

自分のアプリだけがバックエンド サービスにアクセスできるようにするため、サポート対象のすべてのサービスで App Check を有効にします。

通常のトラフィックに合わせてスケールするように Cloud Functions を構成する

Cloud Functions は、アプリの需要に対応して自動的にスケールしますが、攻撃が発生した場合には、多額の請求が生じる可能性があります。これを防ぐには、アプリの通常のトラフィックに基づいて、関数の同時実行インスタンスの数を制限できます。

上限に近づいたときに通知されるようにアラートを設定する

サービスでリクエストが急増する場合、多くの場合は割り当てが開始され、アプリケーションへのトラフィックが自動的に抑制されます。[使用量と請求額] のダッシュボードをモニタリングしてください。ただし、リソースの使用量が予想を超えたときに通知されるように、プロジェクトで予算アラートを設定することもできます。

自己 DOS の防止: エミュレータを使用してローカルで関数をテストする

Cloud Functions の関数を開発する際に誤って DOS を実行しやすくなる可能性があります。たとえば、無限のトリガー書き込みループを作成した場合などです。開発に Firebase Emulator Suite を使用することで、このような誤りの影響がライブサービスに及ばないようにできます

(誤って自分で DOS を実行した場合は、index.js から関数を削除し、firebase deploy --only functions を実行して、関数をデプロイ解除します)。

リアルタイムの応答性がそれほど重要でない場合は、関数を防御的に構成する

関数の結果をリアルタイムで表示する必要がない場合は、結果をバッチで処理することで、不正なトラフィックを軽減できます。結果を Pub/Sub トピックに公開し、スケジュール設定された関数を使用して結果を定期的な間隔で処理します。

API キーについて

Firebase サービスの API キーは非公開ではない

Firebase は、アプリの Firebase プロジェクトを Firebase サービスに対して識別する目的でのみ API キーを使用します。データベースまたは Cloud Storage データへのアクセスを制御する目的では使用しません。このためには Firebase セキュリティ ルールが使用されます。このため、Firebase サービスの API キーをシークレットとして扱う必要はなく、クライアント コードに安全に埋め込むことができます。詳細については、Firebase の API キーをご覧ください。

API キーのスコープを設定する

API キーを使用してリクエストのなりすましを行おうとする攻撃者に対する抑止力を強化するため、アプリ クライアントをスコープとする API キーを作成できます。

FCM サーバーキーを非公開にする

Firebase サービスの API キーとは異なり、FCM サーバーキー(以前の FCM HTTP API で使用)は機密性が高いため、非公開にする必要があります。

サービス アカウント キーを非公開にする

Firebase サービスの API キーとは異なり、Admin SDK で使用されるサービス アカウントの秘密鍵は機密性が高いため、非公開にする必要があります。

セキュリティ ルール

本番環境またはロックモードでルールを初期化する

Cloud Firestore、Realtime Database、Cloud Storage を設定するときは、セキュリティ ルールを初期化してデフォルトですべてのアクセスを拒否するようにし、アプリの開発時に特定のリソースへのアクセスを許可するルールを追加します。

これは Cloud Firestore(本番環境モード)と Realtime Database(ロックモード)の新しいインスタンスのデフォルト設定の一つです。新しいデータベース インスタンスを設定するときにこのオプションを選択します。

Cloud Storage の場合、次のようなセキュリティ ルールの構成から始めます。

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

セキュリティ ルールはスキーマである。ドキュメントの追加時にルールを追加する

リリース前の作業として、アプリの作成後にセキュリティ ルールを作成しないでください。代わりに、アプリを作成するときにセキュリティ ルールを作成し、データベース スキーマのように扱います。新しいドキュメント タイプやパス構造を使用する必要がある場合は、最初にセキュリティ ルールを作成します。

Emulator Suite を使用したセキュリティ ルールの単体テストを CI に追加する

セキュリティ ルールがアプリの開発に対応しているようにするため、Firebase Emulator Suite を使用してルールの単体テストを行い、CI パイプラインにこれらのテストを追加します。Cloud FirestoreRealtime Database のガイドをご覧ください。

認証

カスタム認証: 信頼できる(サーバーサイド)環境から JWT を作成する

安全なログイン システム(カスタム システムまたはサードパーティ サービスなど)をすでに導入している場合は、既存のシステムを使用して Firebase サービスで認証できます。信頼できる環境からカスタム JWT を作成し、トークンをクライアントに渡します。クライアントは、このトークンを使用して認証を行います(iOS+AndroidウェブUnityC++)。

サードパーティ プロバイダでカスタム認証を使用する例については、ブログ投稿 Okta を使用して Firebase で認証するをご覧ください。

管理認証: OAuth 2.0 プロバイダが最も安全である

Firebase の管理認証機能を使用する場合は、OAuth 2.0 または OpenID Connect プロバイダ(Google、Facebook など)が最も安全です。可能であれば、これらのプロバイダを 1 つ以上サポートしてください(ユーザーベースによって異なります)。

メール パスワード認証: ブルート フォース攻撃を防ぐためにログイン エンドポイントの割り当て量を厳しく設定する

Firebase の管理メール パスワード認証サービスを使用する場合は、ブルート フォース攻撃を防ぐため、identitytoolkit.googleapis.com エンドポイントのデフォルトの割り当てを厳しく設定します。この設定は、Google Cloud コンソールの API のページから行うことができます。

メール パスワード認証: メールの列挙保護を有効にする

Firebase の管理メール パスワード認証サービスを使用する場合は、悪意のあるアクターがプロジェクトの認証エンドポイントを悪用してアカウント名を推測することを防ぐため、メールの列挙保護を有効にします。

多要素認証を使用するために Cloud Identity Platform にアップグレードする

ログイン時のセキュリティを強化するため、Cloud Identity Platform にアップグレードして、多要素認証のサポートを追加できます。アップグレード後も、既存の Firebase Authentication コードは引き続き機能します。

匿名認証

ウォーム オンボーディングでは匿名認証のみを使用する

ユーザーが実際にログインする前に、匿名認証のみを使用してユーザーの基本状態を保存します。匿名認証は、ユーザー ログインに代わるものではありません。

スマートフォンを紛失したときにデータが必要な場合には、ユーザーを別のログイン方法に切り替える

ユーザーがローカル ストレージを消去したり、デバイスを切り替えた場合、匿名認証データは保持されません。1 つのデバイスでアプリを再起動した後もデータを保持する必要がある場合は、ユーザーを永久アカウントに変換します。

ユーザーをログイン プロバイダに変換するか、またはメールを確認することを要求するセキュリティ ルールを使用する

誰でもプロジェクトで匿名アカウントを作成できます。そのことを念頭に置いて、特定のログイン方法または確認済みのメールアドレスを要求するセキュリティ ルールですべての非公開データを保護してください。

次に例を示します。

allow write: if request.auth.token.firebase.sign_in_provider != "anonymous";
allow write: if request.auth.token.email_verified = true;

環境管理

開発環境とステージング環境用のプロジェクトを設定する

開発環境、ステージング環境、本番環境用に個別の Firebase プロジェクトを設定します。クライアント コードは、ステージング プロジェクトに対してテストされるまで、本番環境に統合しないでください。

チームによる本番環境データへのアクセスを制限する

大規模なチームで作業する場合は、事前定義ロールまたはカスタムの IAM ロールを使用して本番環境データへのアクセスを制限することで、誤りや不正使用の影響を軽減できます。

チームが開発に Emulator Suite を使用している場合は、本番環境プロジェクトへの幅広いアクセス権を付与する必要がないことがあります。

ライブラリ管理

ライブラリのスペルミスや新しいメンテナンス担当者に注意する

プロジェクトにライブラリを追加するときには、ライブラリの名前とそのメンテナンス担当者に十分に注意してください。インストールしようとしているライブラリと似た名前のライブラリに、悪意のあるコードが含まれていることがあります。

変更を理解していない状態でライブラリを更新しない

アップグレード前に、使用しているライブラリの変更ログを確認します。アップグレードにより付加価値がもたらされることを確認し、メンテナンス担当者が引き続き信頼できる当事者であることを確認してください。

ウォッチドッグ ライブラリを開発またはテストの依存関係としてインストールする

Snyk などのライブラリを使用してプロジェクトをスキャンし、安全でない依存関係があるかどうかを確認します。

Functions のモニタリングを設定し、ライブラリの更新後に確認する

Cloud Functions ロガー SDK を使用する場合は、ライブラリの更新によって引き起こされる動作など、異常な動作をモニタリングしてアラートを受け取ることができます。

Cloud Functions の関数の安全性

Cloud Functions の関数の環境変数には機密情報を含めない

自己ホスト型の Node.js アプリでは、環境変数を使用して秘密鍵などの機密情報を含めることがよくあります。Cloud Functions ではこの操作は行わないでください。 Cloud Functions は関数の呼び出し間で環境を再利用するため、機密情報を環境に保存しないでください。

  • 非公開ではない Firebase API キーを保存するには、コードにこのキーを埋め込むだけです。
  • Cloud Functions の関数で Firebase Admin SDK を使用している場合は、SDK は初期化時に認証情報を自動的に取得できるため、サービス アカウントの認証情報を明示的に指定する必要はありません。
  • サービス アカウントの認証情報を必要とする Google と Google Cloud APIs を呼び出す場合、Node.js 用 Google 認証ライブラリは、Cloud Functions に自動的に入力されるアプリケーションのデフォルト認証情報から認証情報を取得します。
  • Google 以外のサービスの秘密鍵と認証情報を Cloud Functions で使用できるようにするには、Cloud Secret Manager を使用します。

機密情報を暗号化する

Cloud Functions の関数に機密情報を渡すことを避けられない場合は、情報を暗号化するための独自のカスタム ソリューションを開発する必要があります。

シンプルな関数の方が安全です。複雑にする必要がある場合は、Cloud Run を検討してください。

Cloud Functions の関数は、できるだけシンプルでわかりやすいものにしてください。関数が複雑であると、見つけにくいバグや予期しない動作の原因となることがよくあります。

複雑なロジックや環境構成が必要な場合は、Cloud Functions の代わりに Cloud Run の使用を検討してください。