跳转至

GraphQL 中的对象限制覆盖

描述

GraphQL 中的对象限制覆盖(Object Limit Overriding)是指攻击者可以操纵查询参数以超过 API 预期限制的漏洞。这通常涉及将极大的值传递给分页或限制参数,从而可能导致拒绝服务(DoS)攻击或过度消耗资源。

潜在风险:

拒绝服务(DoS): 通过请求过多的对象,攻击者可以使服务器不堪重负,导致性能下降或中断。

资源耗尽: 请求大量对象的查询可能会使服务器的内存和处理能力超载。

数据暴露: 在某些情况下,绕过限制可能会导致未经授权访问大量数据。

成本增加: 对于基于云的服务,由于资源使用率高,处理具有极大限制的查询可能会导致意想不到的成本。

存在漏洞的查询示例:

query {
  users(first: 1000000) {
    id
    name
    email
  }
}

建议

为了缓解 GraphQL 中对象限制覆盖的风险,请实施以下措施:

查询复杂性分析: 使用工具或库来分析并限制传入查询的复杂性。诸如 graphql-query-complexity 之类的库可以提供帮助。

速率限制(Rate Limiting): 实施速率限制,以限制单个用户或 IP 地址在特定时间范围内可以发送的查询数量。

分页和限制: 对单个查询返回的数据量应用限制。确保使用分页来控制数据量。

Example Implementation:

const { ApolloServer, gql } = require('apollo-server');
const { getComplexity, simpleEstimator, fieldExtensionsEstimator } = require('graphql-query-complexity');
const { GraphQLObjectType, GraphQLInt, GraphQLString, GraphQLSchema } = require('graphql');

// Define your GraphQL schema
const typeDefs = gql`
  type Query {
    hello: String
    user(id: ID!): User
  }

  type User {
    id: ID!
    name: String
    age: Int
  }
`;

// Define your resolvers
const resolvers = {
  Query: {
    hello: () => 'Hello world!',
    user: (_, { id }) => ({
      id,
      name: 'John Doe',
      age: 30,
    }),
  },
};

// Create an Apollo Server instance with query complexity analysis
const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [
    {
      // This plugin computes the complexity of incoming queries
      requestDidStart: () => ({
        didResolveOperation({ request, document }) {
          const complexity = getComplexity({
            schema: server.schema,
            query: document,
            variables: request.variables,
            estimators: [
              fieldExtensionsEstimator(),
              simpleEstimator({ defaultComplexity: 1 }),
            ],
          });

          // Define a maximum complexity limit
          const maxComplexity = 100;

          // Check if the query complexity exceeds the maximum allowed
          if (complexity > maxComplexity) {
            throw new Error(`Query is too complex: ${complexity}. Maximum allowed complexity: ${maxComplexity}`);
          }
        },
      }),
    },
  ],
});

// Start the server
server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});
from graphql import parse, execute, validate, GraphQLError
from graphql.language.visitor import visit, Visitor

class ComplexityVisitor(Visitor):
    def __init__(self):
        self.complexity = 0
        self.max_complexity = 100

    def enter_field(self, node, key, parent, path, ancestors):
        complexity = 1  # Base complexity for each field
        self.complexity += complexity
        if self.complexity > self.max_complexity:
            raise GraphQLError(f"Query complexity exceeds maximum allowed complexity of {self.max_complexity}")

def complexity_middleware(schema, query):
    document = parse(query)
    visitor = ComplexityVisitor()
    visit(document, visitor)
    return visitor.complexity

def execute_with_complexity_check(schema, query, variables=None):
    complexity = complexity_middleware(schema, query)
    if complexity > 100:
        raise GraphQLError(f"Query complexity exceeds maximum allowed complexity of 100")
    result = execute(schema, parse(query), variable_values=variables)
    return result

By using these recommendations and configurations, you can better protect your GraphQL APIs from the risks associated with object limit overriding.

使用 Ostorlab 检测此问题

Ostorlab 会检查 Web 应用、API 和网络是否存在此问题。

创建账户

链接

标准

  • CWE_TOP_25:
    • CWE_20
    • CWE_400
  • PCI_STANDARDS:
    • REQ_6_1
    • REQ_6_2
    • REQ_6_4
    • REQ_11_3
  • OWASP_MASVS_L2:
    • MSTG_PLATFORM_2
  • OWASP_ASVS_L3:
    • V13_4_1
  • SOC2_CONTROLS:
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
    • CC_9_1
  • HIPAA_CONTROLS:
    • SECURITY212
    • SECURITY213
  • OWASP_TOP_10:
    • A03_2021