コンテンツにスキップ

GraphQL Circular References

GraphQLの循環参照

説明

GraphQLを使用すると、クライアントは特定のデータを要求できます。その柔軟性を悪用して、複雑なクエリや再帰的なクエリを作成することができます。循環参照は、オブジェクトタイプが直接的または他のタイプを介して間接的に自身を参照する場合に発生します。

例:

 query CircularReferences  {
     user {
       friends {
         user {
           friends {
             user {
               __typename
             }
           }
         }
       }
     }
   }

GraphQLにおける循環参照のセキュリティへの影響:

  • サービス拒否: 入れ子になった参照が多すぎる大規模なクエリを送信することで、攻撃者はサーバーを過負荷状態にし、速度低下やクラッシュを引き起こす可能性があります。
  • リソースの枯渇: クエリの処理中にサーバーのメモリまたはCPUリソースが不足し、パフォーマンスの低下やサービスの利用不可につながる可能性があります。

推奨事項

GraphQLでの循環参照のリスクを軽減するには、次の推奨事項に従うことができます。 1. 深さの制限: クエリの深さをチェックするミドルウェアを実装し、制限を超えた場合はエラーを発生させます。 例:

class DepthAnalysisMiddleware:
    def resolve(self, next, root, info, **args):
        if info.operation.selection_set:
            depth = 0
            for field in info.operation.selection_set.selections:
                depth = max(depth, self._get_depth(field))
            if depth > 3:
                raise Exception('Query depth is too high')
        return next(root, info, **args)

    def _get_depth(self, field):
        if field.selection_set:
            return 1 + max(self._get_depth(f) for f in field.selection_set.selections)
        return 1
  1. 循環参照の検出: 循環参照を避けるようにスキーマを再設計します。 循環参照の例:
class User(graphene.ObjectType):
    id = graphene.ID()
    name = graphene.String()
    friends = graphene.List(lambda: User)

    def resolve_friends(self, info):
        return [User(id=1, name='Alice'), User(id=2, name='Bob')]

再設計されたスキーマの例:

  class FriendProfile(graphene.ObjectType):
      id = graphene.ID()
      name = graphene.String()

  class User(graphene.ObjectType):
      id = graphene.ID()
      name = graphene.String()
      friends = graphene.List(FriendProfile)

      def resolve_friends(self, info):
          return [FriendProfile(id=1, name='Alice'), FriendProfile(id=2, name='Bob')]
      const FriendProfile = new GraphQLObjectType({
          name: 'FriendProfile',
          fields: {
              id: { type: GraphQLID },
              name: { type: GraphQLString }
          }
      });

      const User = new GraphQLObjectType({
          name: 'User',
          fields: {
              id: { type: GraphQLID },
              name: { type: GraphQLString },
              friends: { type: new GraphQLList(FriendProfile) }
          }
      });  

リンク

標準

  • 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