コンテンツにスキップ

Circular Fragment in GraphQL

GraphQL における循環フラグメント

説明

GraphQL における循環フラグメント(Circular fragments)とは、GraphQL クエリ内のフラグメントが互いに参照し合い、循環参照を引き起こす状況を指します。これにより、無限ループ、リソースの枯渇、およびサービス拒否(DoS)攻撃などの問題が発生する可能性があります。攻撃者はこれを利用して GraphQL サーバーを過負荷にし、正規ユーザーに対して利用不可または応答を遅延させる可能性があります。

GraphQL における循環フラグメントのセキュリティへの影響:

1. サービス拒否(DoS): 循環フラグメント参照により、サーバーがクエリを無限に解決し続け、過剰なリソースを消費して、最終的にクラッシュまたは速度低下を引き起こす可能性があります。 2. リソースの枯渇: 無限のフラグメントループは高い CPU およびメモリ使用量につながり、リソースの枯渇を引き起こし、アプリケーションやサーバーのパフォーマンスを低下させます。 3. クエリの複雑性の悪用: 攻撃者は循環フラグメントを含む複雑なクエリを作成し、GraphQL サーバーにおける深さや再帰の制限の欠如を悪用する可能性があります。

循環フラグメントの基本的な例は次のようになります:

fragment UserFields on User {
  name
  ...MoreUserFields
}

fragment MoreUserFields on User {
  email
  ...UserFields
}

この例では、UserFieldsMoreUserFields を参照し、MoreUserFieldsUserFields を参照することで、循環参照を作成しています。

推奨事項

GraphQL における循環フラグメントのリスクを緩和するには、次の手順を検討してください:

1. スキーマ分析による循環フラグメントの検出

悪用される前に循環参照を検出して防ぐために、GraphQL スキーマとクエリに対して静的分析を実装します。一部の GraphQL サーバーライブラリは、スキーマを分析するためのツールを提供しています。

  • Tooling: GraphQL Code Generator や GraphQL Inspector などの GraphQL リンティングツールを使用して循環フラグメントを検出し、それらが本番環境に到達するのを防ぎます。

GraphQL Code Generator を使用した例:

npm install @graphql-codegen/cli
npx graphql-codegen init

GraphQL クエリ内の潜在的な循環フラグメントの問題を検出するスキーマ検証を出力するようにコードジェネレータを設定できます。

2. クエリコスト分析の実装

クエリの複雑性分析を使用して、各フィールド、フラグメント、またはクエリに「コスト」を割り当てます。クエリまたはフラグメントが事前定義されたコストのしきい値を超えた場合、自動的に拒否されるように設定できます。

  • Tooling: graphql-query-complexity のようなライブラリを使用して、クエリのコストを計算し、循環フラグメントの影響を制限できます。

graphql-query-complexity を使用した JavaScript の例:

const { getComplexity, simpleEstimator } = require('graphql-query-complexity');

const server = new ApolloServer({
  schema,
  validationRules: [
    queryComplexity({
      estimators: [
        simpleEstimator({ defaultComplexity: 1 })
      ],
      maximumComplexity: 1000,  // Queries that exceed this complexity will be rejected
      onComplete: (complexity) => {
        console.log('Query Complexity:', complexity);
      },
    }),
  ],
});

3. 深さと再帰の制限の適用

一部の GraphQL サーバーの実装では、リソースの枯渇を防ぐために、クエリの深さと再帰の制限を定義できます。これにより、循環フラグメントによって引き起こされる無限ループを回避できます。

  • Tooling: 例えば Apollo Server は、過度の再帰を防ぐことができるクエリの深さ制限をサポートしています。

Apollo Server でのクエリ深さ制限の使用例:

const { ApolloServer } = require('apollo-server');
const depthLimit = require('graphql-depth-limit');

const server = new ApolloServer({
  schema,
  validationRules: [depthLimit(5)],  // Set query depth limit to 5
});

4. フラグメントの賢明な使用

複雑なクエリでのフラグメントの過剰な使用は避けてください。過度の使用はパフォーマンスの低下につながり、循環参照の可能性を開きます。代わりに、複雑なクエリを複数の中小規模のクエリに分割することを検討してください。

  • Recommendation: クエリの設計を見直し、フラグメントの使用を特定のモジュール化されたデータ部分に制限してください。

例:

query {
  user(id: "1") {
    name
    email
    posts {
      title
      content
    }
  }
}

複数のフラグメントを互いにネストするのではなく、このようなよりシンプルなクエリを使用します。

リンク

標準

  • CWE_TOP_25:
    • CWE_400
  • PCI_STANDARDS:
    • REQ_6_2
    • REQ_6_4
    • REQ_11_3
  • OWASP_MASVS_L2:
    • MSTG_PLATFORM_2
  • OWASP_ASVS_L3:
    • V13_4_1
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
    • CC_9_1
  • HIPAA_CONTROLS:
    • SECURITY212
    • SECURITY213