全部指南
严重程度:中危API 安全

公开的 GraphQL 内省:为何是个问题以及如何关闭

GraphQL 内省是一个内置查询,会返回 API 的完整 schema:每个类型、字段、参数和 mutation。它在开发中必不可少,但对于私有 API,在生产环境中不应可被访问。如果保持开启,它就是一张展示你整个后端攻击面的地图。

这是什么

每个 GraphQL 服务器都实现了一小组元字段,其中最主要的是 __schema 和 __type。只需向 /graphql 发送一次带有 `query { __schema { types { name fields { name } } } }` 的 POST 请求,就能返回完整的类型定义。

GraphiQL、Apollo Sandbox 和 Playground UI 等工具依赖内省来自动补全查询并渲染 schema 浏览器。在开发中这正是你想要的;但在生产环境的私有 API 上,这意味着世界上任何人都可以下载同一张地图。

为什么重要

schema 会列出你的模型、它们之间的关系以及你暴露的每个 mutation——包括从未打算被外部发现的管理、内部和已弃用字段。攻击者会利用它构建一份有针对性的操作列表,用于探测认证绕过、IDOR 和注入漏洞。

即使每个字段的授权都正确无误,refundOrder、impersonateUser 或 exportBackup 这类隐藏的 mutation 也不应自我暴露。内省把攻击者的侦察阶段从数小时的猜测变成了一次请求。

如何修复

在 Apollo Server 中禁用内省

当 NODE_ENV 为 production 时关闭内省。在本地保持开启,以便你的团队仍可在 Sandbox 中浏览 schema。

import { ApolloServer } from "@apollo/server";

const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: process.env.NODE_ENV !== "production",
});
在 GraphQL Yoga / graphql-http 中禁用

Yoga 提供了一流的插件;graphql-http 可以使用 graphql-js 提供的验证规则。两者都会在内省查询执行之前将其拦截。

// GraphQL Yoga
import { createYoga } from "graphql-yoga";
import { useDisableIntrospection } from "@graphql-yoga/plugin-disable-introspection";

export const yoga = createYoga({
  schema,
  plugins: process.env.NODE_ENV === "production" ? [useDisableIntrospection()] : [],
});

// graphql-http (or express-graphql)
import { NoSchemaIntrospectionCustomRule } from "graphql";

const validationRules = process.env.NODE_ENV === "production"
  ? [NoSchemaIntrospectionCustomRule]
  : [];
从生产环境中移除 schema 浏览器界面

GraphiQL、Playground 和 Apollo Sandbox 是为了帮助人们浏览 schema 而存在的——它们不应出现在公开的生产端点上。请将它们置于认证检查之后,或者在生产构建中完全不挂载它们。

优先依靠授权而非屏蔽列表

禁用内省是一项加固措施,而不是访问控制。每个字段仍然需要在 resolver 层面进行正确的授权——否则任何猜到字段名的人仍然可以调用它。把内省视为其中一层防护,而不是唯一的防护。

常见问题

隐藏 schema 不就是通过隐蔽实现安全吗?

部分是的——执着的攻击者仍然可以暴力猜测字段名。但让侦察变得廉价且完整,是值得阻止的。所有商业 GraphQL API 指南以及 OWASP GraphQL 速查表都建议在生产环境中禁用内省。

如果是希望开发者浏览 schema 的公开 API 呢?

有意识地发布 schema——发布 Schema Definition Language 文件、托管文档站点,或者只在认证后才开放内省。这与匿名 POST 请求就能返回所有内容截然不同。

AppSafe 如何检测这个问题?

AppSafe 会向 /graphql 和 /api/graphql 发送一个小型内省查询,并查找状态为 200 的 __schema 响应。如果有返回,就会在 API 安全类别中以中等严重程度标记。

你的应用受影响了吗?

AppSafe 一次免费扫描,就能检查这个问题以及数十项其他问题。

免费扫描我的应用