web-dev-qa-db-ja.com

GraphQL / Apolloサーバーでのネスト攻撃をどのように防止しますか?

次のようなクエリを使用して、Apolloサーバーに対するネストされた攻撃をどのように防ぎますか?

{
  authors {
    firstName
    posts {
      title
      author {
        firstName
        posts{
          title
          author {
            firstName
            posts {
              title
              [n author]
                [n post]
            }
          }
        }
      }
    }
  }
}

つまり、クエリで送信される再帰の数をどのように制限できますか?これは、潜在的なサーバーの脆弱性である可能性があります。

47
jboothe

執筆時点では、GraphQL-JSやApollo Serverにこの懸念を処理する組み込み機能はありませんが、GraphQLの人気が高まるにつれて、シンプルなソリューションが確実に必要になるはずです。この懸念は、スタックのいくつかのレベルでいくつかのアプローチで対処できます。また、常にレート制限と組み合わせて、サーバーに多くのクエリを送信できないようにする必要があります(これはRESTも同様)。

考えられるさまざまな方法をすべてリストし、これらのソリューションがさまざまなGraphQLサーバーに実装されているため、この答えを最新に保つようにします。それらのいくつかは非常に単純であり、いくつかはより複雑です。

  1. クエリの検証:すべてのGraphQLサーバーで、クエリを実行する最初のステップはvalidationです-これはサーバーは、クエリに重大なエラーがあるかどうかを判断しようとするため、構文エラーや無効な引数が事前に見つかった場合に実際のサーバーリソースの使用を避けることができます。 GraphQL-JSには、ESLintによく似た形式に従う デフォルトルールの選択 が付属しています。 フラグメント内の無限サイクル を検出するルールがあるように、検証ルールを記述して、ネストが多すぎるクエリを検出し、検証段階で拒否することができます。
  2. クエリのタイムアウト:クエリが静的にリソースを大量に消費することを検出できない場合(おそらく、浅いクエリでも非常に高価になる可能性があります!)、クエリの実行にタイムアウトを追加するだけです。これにはいくつかの利点があります。(1)推論するのが難しくないハード制限であり、(2)これはバックエンドの1つが応答に不当に長い時間がかかる状況でも役立ちます。多くの場合、アプリのユーザーは、応答を得るために10秒以上待機するよりも不足しているフィールドを好むでしょう。
  3. クエリホワイトリスト:これはおそらく最も複雑な方法ですが、許可されたクエリのリストを事前にコンパイルし、そのリストに対して着信クエリをチェックすることができます。クエリが完全に静的な場合(クライアントでリレーのようなものを使用して動的なクエリを生成しない)、これが最も信頼性の高いアプローチです。自動ツールを使用して、デプロイ時にアプリからクエリ文字列を引き出すことができるため、開発時には必要なクエリを作成できますが、本番では必要なクエリのみが許可されます。このアプローチのもう1つの利点は、クエリの検証を完全にスキップできることです。可能なクエリはすべて有効であることがわかっているためです。静的クエリとホワイトリストのその他の利点については、この投稿をお読みください: https://dev-blog.apollodata.com/5-benefits-of-static-graphql-queries-b7fa90b0b69a
  4. クエリコスト制限:(編集で追加)クエリタイムアウトと同様に、クエリの実行中に異なる操作、たとえばデータベースクエリにコストを割り当てることができます、クライアントがクエリごとに使用できる合計コストを制限します。これは、単一のクエリの最大並列性を制限することと組み合わせることができるため、クライアントが数千の並列リクエストを開始するものをバックエンドに送信するのを防ぐことができます。

(1)と(2)は、特に多くの新しい開発者がこれらの懸念に気付いていない可能性があるため、おそらくすべてのGraphQLサーバーがデフォルトで持つべきものです。 (3)特定の種類のアプリでのみ機能しますが、非常に厳しいパフォーマンスまたはセキュリティ要件がある場合に適しています。

52
stubailo

Stubailoの答えのポイント(4)を補うために、着信GraphQLドキュメントにコストと深さの境界を課すNode.js実装がいくつかあります。

これらは、検証フェーズを補足するカスタムルールです。

12
Andy Carlson

クエリのホワイトリストのバリエーションはクエリ署名です。

ビルドプロセス中に、各クエリは、サーバーと共有されているがクライアントにはバンドルされていないシークレットを使用して暗号で署名されます。その後、実行時にサーバーはクエリが本物であることを検証できます。

ホワイトリストに勝る利点は、クライアントでクエリを作成するときにサーバーを変更する必要がないことです。これは、複数のクライアントが同じサーバー(Web、デスクトップ、モバイルアプリなど)にアクセスする場合に特に役立ちます。

3
Tamlyn

クエリのコスト制限には、 graphql-cost-analysis を使用できます

これは、クエリを実行する前に解析する検証ルールです。 GraphQLサーバーでは、必要なスキーマタイプマップの各フィールドにコスト構成を割り当てるだけです。

2
Schrax

お見逃しなく graphql-rate-limit ????基本的かつきめ細かいレート制限をクエリまたは突然変異に追加するGraphQLディレクティブ。

2
Carlos Rufo