Security
11 min read
1756 views

フェデレーテッドサブグラフインジェクション:"盲目"なGraphQLデータ漏洩

IT
InstaTunnel Team
Published by our engineering team
フェデレーテッドサブグラフインジェクション:"盲目"なGraphQLデータ漏洩

企業がモノリシックアーキテクチャからフェデレーテッドGraphQL(スーパグラフ)へ積極的に移行する中、新たで重大な脆弱性クラスが出現しています:フェデレーテッドサブグラフインジェクション。APIゲートウェイを強化する一方で、多くの組織はアーキテクチャのソフトな部分 — サブグラフ自体を見落としがちです。この脆弱性は、ゲートウェイとサブグラフ間の暗黙の信頼を悪用し、攻撃者がプライベートマイクロサービスから敏感なデータ断片を「ステッチ」して結合できるようにします。この記事では、攻撃の仕組み、従来のWAFでは見えない理由、そしてData GraphのためのZero Trustアーキテクチャの実装方法について解説します。


スーパグラフの台頭とセキュリティギャップ

現代のAPI環境では、Apollo Federation、Hasura、WunderGraphなどにより普及したGraphQL Federationは、複数のマイクロサービス(サブグラフ)を単一のクエリ可能なエンドポイント(スーパグラフまたはゲートウェイ)に統合する標準となっています。

信頼のアーキテクチャ

典型的なフェデレーテッド設定では:

  1. ユーザーがゲートウェイにクエリを送信
  2. ゲートウェイはJWTを検証し、高レベルの権限を確認し、クエリプランを構築
  3. ゲートウェイはクエリを断片に分割し、それぞれのサブグラフ(例:ユーザーサービス、請求サービス、在庫サービス)に送信
  4. サブグラフは自分の部分を実行し、JSONを返す
  5. ゲートウェイは結果を「ステッチ」してユーザーに返す

致命的な欠陥: 多くのエンジニアはサブグラフを「内部」とみなし、安全だと考えています。リクエストがサブグラフに到達した時点でゲートウェイが既に認証済みと想定しているためです。その結果、サブグラフはしばしば自身の認証チェックを省略し、典型的なConfused Deputy問題を引き起こします。


フェデレーテッドサブグラフインジェクションとは何か?

フェデレーテッドサブグラフインジェクションは、サーバー側の脆弱性であり、攻撃者がGraphQLクエリの構造を操作して、ゲートウェイに悪意のあるクエリ断片を脆弱なサブグラフに注入させるものです。

サブグラフはゲートウェイが唯一の呼び出し元と想定しており、「スマート」なものと信じているため、敏感なフィールド(PII、内部ID、管理フラグなど)へのリクエストを無検証で実行します。

なぜ「盲目」なのか?

「盲目」という用語は、二つの異なる失敗モードを指します:

ゲートウェイの盲目さ: ゲートウェイは構文的に有効なクエリを見て、「問題ない」と判断します。グローバルスキーマを確認し、「これで良い」と言いますが、実際のビジネスロジックの制約は理解していません。

サブグラフの盲目さ: サブグラフは、「User ID 123のSSNをください」といったリクエストを受け取りますが、元のクライアントのトークンやコンテキストを見ておらず、信頼しています。リクエストがゲートウェイのIPから来たと信じているのです。


攻撃の構造

シナリオ:”ステッチされた”アイデンティティ漏洩

スーパグラフには二つのサブグラフがあります:

  • ユーザーサブグラフ: 公開プロフィールデータを扱う
  • 請求サブグラフ: プライベートなクレジットカード情報や請求書を扱う

ユーザーサブグラフは以下を定義:

type User @key(fields: "id") {
  id: ID!
  username: String
  # 公開情報のみ
}

請求サブグラフはUser型を拡張:

extend type User @key(fields: "id") {
  id: ID! @external
  last4Digits: String
  invoices: [Invoice]
  # 機密情報:本人のみが閲覧可能
  internalRiskScore: Int
}

脆弱性

ゲートウェイはinvoicesをクエリするにはログインが必要としますが、internalRiskScoreフィールドには@authディレクティブが付いていません。これは開発者が”内部フィールドだからゲートウェイは公開しない”と想定していたためです。

スキーマの構成ミスや、Fragment Injectionを利用した攻撃により、ゲートウェイの表面検査を回避できる場合があります。

攻撃クエリ例

query LeakRiskScore {
  node(id: "User:123") {
    ... on User {
      username
      _onBilling_internalRiskScore: internalRiskScore
    }
  }
}

実行の流れ

  1. ゲートウェイNodeへのリクエストを検知し、IDを解決
  2. クエリプランナーinternalRiskScoreが請求サブグラフにあると認識
  3. インジェクション: ゲートウェイは請求サブグラフへのフェッチリクエストを生成:
query {
  _entities(representations: [{ __typename: "User", id: "123" }]) {
    ... on User {
      internalRiskScore
    }
  }
}
  1. 請求サブグラフはリクエストを受け取り、internalRiskScoreをID 123のユーザーに対して返します。現在のユーザーが本人かどうかの検証は行いません。
  2. 漏洩: 請求サブグラフはスコア99(高リスク)を返します。
  3. レスポンス: 攻撃者はプライベートデータを取得します。

実際のCVE:理論だけではない

この攻撃パターンは、2025年後半に複数の高深刻度のCVEとしてApollo Federationに対して公開されました。これは最も広く展開されているフェデレーテッドGraphQLランタイムです。

CVE-2025-64530 — インターフェースアクセス制御回避(2025年11月)

深刻度:高

Apollo Federationの構成ロジック(バージョン2.9.5以前、2.10.4、2.11.5、2.12.1)に脆弱性があり、インターフェース型やフィールドのアクセス制御を回避できました。Apollo Federationは、ユーザー定義のアクセス制御ディレクティブ(@authenticated@requiresScopes@policy)をインターフェース型に誤って許可していました。GraphQL仕様では、インターフェースから実装型への継承ルールが定義されていないため、これらのディレクティブは伝播されません

攻撃者は、インラインまたは名前付きフラグメントを使って、インターフェースに設定された制御を完全に回避しながら、実装オブジェクト型を通じて保護されたデータにクエリを送ることができました。パッチは、インターフェース型に対するユーザー定義のアクセス制御ディレクティブを完全に拒否し、フェデレーションの構成ロジックが自動的に適切なディレクティブを生成するようにしました。

対策: Apollo Federation構成を2.9.5以上にアップグレード、または2.10.4、2.11.5、2.12.1にアップデート。未パッチの場合は、インターフェース型から実装型へのアクセス制御要件を手動でコピーしてください。

CVE-2025-64173 — 多相型認可失敗

深刻度:高

Apollo Router Coreのバージョン1.61.11以下(および2.0.0-alpha.0から2.8.1-rc.0まで)では、インターフェース型とその実装オブジェクト型のアクセス制御ディレクティブの処理に誤りがありました。すべての実装が同じ要件を共有している場合、Routerはインターフェースにディレクティブを適用し、実装型のディレクティブを無視しました。これにより、追加のアクセス制御が必要なデータに未認証のクエリがアクセスできてしまいました。

対策: Apollo Routerを1.61.12または2.8.1にアップグレード。

CVE-2025-64347 — リネームされたディレクティブの回避

深刻度:高

Apollo Router Coreのバージョン1.61.12-rc.0以下では、@linkインポートによるリネームされたアクセス制御ディレクティブが適用されませんでした。スキーマ構成の一環として@authenticatedをカスタム名にエイリアスした場合、Routerはそのディレクティブを強制しませんでした。修正はバージョン1.61.12と2.8.1で提供済みです。

GHSA-m8jr-fxqx-8xx6 — 推移的フィールドアクセス制御回避

フェデレーションの構成ロジックにおいて、@requires@fromContextを使ったフィールドが、保護されたデータに依存している場合、その依存フィールドと同じアクセス制御要件を持つ必要があります。攻撃者は、依存フィールドだけをリクエストし、実際に保護されたフィールドをリクエストしなくても、アクセス制御を回避できます。修正は、依存フィールドが参照するフィールドと同じアクセス制御を持つことを強制します。


攻撃のバリア:ダイレクトサブグラフ露出(”シャドウグラフ”)

ゲートウェイが完璧にセキュアでも、多くの組織はサブグラフエンドポイント(例:billing-service.internal:4000/graphql)を誤って公開しています:

  • 誤設定されたロードバランサやIngressコントローラー
  • 隣接サービスのサーバーサイドリクエストフォージェリ(SSRF)脆弱性
  • DMZから到達可能な予測可能な内部DNS名

Apolloのセキュリティガイダンスによると、サブグラフが直接アクセス可能な場合、ルーターのセキュリティ制御を完全に回避します。_entitiesクエリは、フェデレーテッドデータを取得するための特別なクエリですが、これが認証なしで誰でもアクセスできるデータアクセス手段となります。

攻撃者がサブグラフに直接到達できる場合、ゲートウェイのリクエストを模倣できます:

POST http://billing-service.internal:4000/graphql

{
  "_entities": [{ "__typename": "User", "id": "456" }],
  "query": "query { _entities(representations: [{ __typename: \"User\", id: \"456\" }]) { ... on User { internalRiskScore invoices { amount } } } }"
}

JWTも認証ヘッダーも不要です。内部アクセスの生のリクエストです。


なぜ従来のWAFはこれを見逃すのか

Webアプリケーションファイアウォール(WAF)は主にHTTPリクエストの署名(URLパターン、ペイロード、既知の悪意のある文字列)に基づいて動作します。フェデレーテッドサブグラフインジェクションは以下を生成します:

  • 構文的に有効なGraphQLクエリ
  • Content-Type: application/jsonを含む標準的なPOST /graphqlリクエスト
  • SQLやシェルコマンド、従来のインジェクションペイロードは含まれません
  • ゲートウェイのログから見て”成功”と見なされるリクエスト(200 OKレスポンス)

これにより、ゲートウェイのアクセスログには異常が記録されません。 この侵害は、サブグラフ自体がリクエストの不正を認識しないため、すべての層で見えなくなります。これはコンプライアンスの問題の核心であり、GDPRやCCPAの監査では、正当なユーザーリクエストが200を返し、どのサブグラフフィールドが実際に返されたかの記録が残らないことになります。


深層防御:スーパグラフのセキュリティ

“ゲートウェイトラスト”から”ゼロトラスト”へ移行するには、すべての層で制御を行う必要があります。

1. サブグラフレベルの認証(ゴールデンルール)

ゲートウェイだけに頼らず、各サブグラフが独立してユーザーを検証し、特定のオブジェクトへのアクセス権を確認する必要があります。

// 請求サブグラフのリゾルバ例
const resolvers = {
  User: {
    internalRiskScore: async (userEntity, args, context) => {
      // 重要:リゾルバレベルで認証を検証
      if (context.userId !== userEntity.id && !context.isAdmin) {
        throw new AuthenticationError("リスクスコアの閲覧権限がありません");
      }
      return fetchRiskScore(userEntity.id);
    }
  }
};

contextオブジェクトは、ゲートウェイからサブグラフへリクエストごとにJWTを伝播させて設定します。これは絶対に必要です。

2. ゲートウェイとサブグラフ間の通信のセキュリティ

サブグラフは正当なゲートウェイからのリクエストのみ受け付けるべきです。選択肢は二つ:

Mutual TLS (mTLS): 最も強力な防御策。サブグラフはゲートウェイに発行されたクライアント証明書のみを受け入れます。攻撃者や誤設定のSSRFからのリクエストはTLSハンドシェイクで拒否されます。

HMAC署名リクエスト: ゲートウェイは共有シークレットでサブグラフへのリクエストに署名し、サブグラフは署名を検証します。単純な静的ヘッダー(例:x-gateway-secret: "hardcoded-value")は不十分です。秘密情報はソースコードやログ、環境ダンプに漏れる可能性があります。

3. ネットワーク分離 — サブグラフは内部に限定

Apolloの公式セキュリティドキュメントでも強調されている通り、サブグラフはルーターからのみアクセス可能にすべきです。パブリックインターネットやDMZセグメント、ゲートウェイ以外のサービスからはアクセスさせてはいけません。これをネットワークレベル(セキュリティグループ、VPCポリシー、KubernetesのNetworkPolicy)で強制します。

4. _service_entitiesの公開エンドポイントを無効化

_serviceフィールドはサブグラフのSDL(スキーマ定義言語)を公開します。_entitiesはフェデレーションクエリのエントリポイントです。どうしても外部公開が必要な場合は、信頼できるゲートウェイIPからのリクエスト以外はこれらのフィールドをブロックするミドルウェアを使用してください。

5. パッチ適用と最新状態の維持

上記のCVEは、フェデレーションランタイムの設計ミスも含め、構成レベルの脆弱性を示しています。次のことを行いましょう:

  • Apollo Routerやフェデレーション構成、使用しているライブラリのセキュリティアドバイザリを監視
  • apollo checkrover subgraph checkをCI/CDパイプラインに組み込み、スキーマのアクセス制御の問題を事前に検出
  • GraphQL InspectorApollo GraphOS schema checksを使い、公開されているが敏感な型を返すフィールドを特定

6. @requires@fromContext依存関係のアクセス制御強化

GHSA-m8jr-fxqx-8xx6に従い、@requires@fromContextを使ったフィールドを監査し、保護されたデータに依存するフィールドには一致したアクセス制御ディレクティブを付与してください。修正済みの構成ライブラリは自動的にこれを強制しますが、古いバージョンを使う場合は手動で確認が必要です。

7. サブグラフでのクエリコスト分析

攻撃者はフェデレーションインジェクションを利用して、深くネストされた関係をリクエストし、サービス拒否(DoS)攻撃を仕掛けることも可能です。クエリの深さ制限やコスト分析をサブグラフレベルで実施し、不正なエンティティクエリによるリソース枯渇を防ぎましょう。


ビジネスとコンプライアンスへの影響

フェデレーテッドサブグラフインジェクションの成功は、即時のデータ漏洩だけでなく、ビジネスに深刻な影響を及ぼします:

データ漏洩: メールアドレス、ID、金融データなどのPIIが、保護されていると信じられていたサービス間で漏洩します。

コンプライアンス違反: ゲートウェイのログには200 OKが記録されるため、不正アクセスの監査証跡が残りません。GDPRやCCPAの調査では、アクセス制御が適切に行われていたことを証明できない可能性があります。

評判の損失: フェデレーテッドアーキテクチャはスケーラビリティのために採用されますが、この層での侵害は、スーパグラフ内のすべてのサービスに影響を及ぼす可能性があります。


まとめ

フェデレーテッドGraphQLは開発速度を大きく向上させますが、従来のセキュリティ境界を根本的に破壊します。フェデレーテッドサブグラフインジェクションは、「スマートゲートウェイ」と「ダムサブグラフ」の間のギャップを狙います。2025年後半に公開されたCVEは、主要なフェデレーションランタイムの構成ロジックにアクセス制御の回避をもたらす脆弱性が存在することを示しています。

重要な原則はシンプルです:認証ロジックはデータとともに移動すべきであり、リクエストだけに付随すべきではありません。 セキュリティチームはスーパグラフを監査し、すべてのサブグラフを公開サービスとみなして、各層でアクセス制御を確実に実施してください。

Continue from this article into the most relevant product guides and workflows.

Related Topics

#Federated GraphQL, GraphQL federation security, sub-graph injection, GraphQL supergraph attack, GraphQL data leak, GraphQL authorization bypass, GraphQL gateway trust issue, GraphQL microservices security, GraphQL fragment injection, GraphQL query stitching attack, Apollo Federation security, GraphQL schema stitching risk, GraphQL access control flaw, distributed GraphQL security, GraphQL privilege escalation, GraphQL overfetching attack, GraphQL lateral data access, GraphQL microservice data leak, API federation vulnerability, GraphQL trust boundary failure, GraphQL gateway bypass, subgraph authorization gap, GraphQL policy enforcement, GraphQL security 2026, GraphQL attack chain, GraphQL blind data exfiltration, GraphQL query abuse, GraphQL introspection abuse, GraphQL field-level authorization, GraphQL cross-service data leak, GraphQL fragment abuse, GraphQL directive bypass, GraphQL schema composition risk, GraphQL supergraph misconfiguration, GraphQL zero trust architecture, GraphQL API security testing, GraphQL pentesting, GraphQL red team, GraphQL blue team defense, GraphQL monitoring, GraphQL query allowlist, persisted queries security, GraphQL complexity attack vs injection, GraphQL injection variant, API gateway vs subgraph security, microservices authorization failure, distributed auth flaw, GraphQL RBAC bypass, GraphQL ABAC failure, GraphQL data stitching exploit, GraphQL sensitive field exposure, GraphQL API breach, enterprise GraphQL security, GraphQL threat modeling, GraphQL federation attack surface, secure subgraph design, GraphQL least privilege, GraphQL contract testing security, Apollo Router security, GraphQL mesh security

Keep building with InstaTunnel

Read the docs for implementation details or compare plans before you ship.

Share this article

More InstaTunnel Insights

Discover more tutorials, tips, and updates to help you build better with localhost tunneling.

Browse All Articles