GraphQL API 的 5 个安全提示
2015 年,Facebook 创建了 GraphQL,作为 REST API 的替代方案,通过使 API 调用更加灵活,为前端开发人员提供更多功能。GraphQL 通过为其 API 使用者提供一种查询语言来实现这一目标,使他们能够仅查询所需的数据。
虽然 GraphQL 可以改善前端开发人员的体验,但其规范对安全性没有任何意见。GraphQL API 需要将查询转换为数据提取,这会给您的 API 架构增加另一层复杂性。
我们已经写了一篇关于十大 API 安全线程的文章,它们都适用于 GraphQL API。在本文中,您将了解有关提高 GraphQL API 安全性的其他增强功能。
美国和欧盟的新隐私法使得每个安全漏洞都对 API 公司构成巨大的财务风险。
1.全面的查询授权
尽管小型 API 通常提供 HTTP 可访问数据库的方式,但 GraphQL 通常与数据源无关。这意味着 GraphQL 不关心数据来自哪里。数据可以来自数据库,也可以从另一个 API 获取。这也意味着,GraphQL 不是数据存储,因此它必须针对实际数据源进行身份验证,并检查用户是否有权访问来自这些源的特定数据。
假设一个为许多不同客户端提供服务的 GraphQL 服务器在上游服务或数据库中被认证为一个用户。在这种情况下,GraphQL 服务器必须自行在解析内部进行授权检查。否则,这可能会导致 CCPA 法律所监管的私人数据甚至更糟的医疗数据泄露,并让您承担责任。
如果需要,您可以检查每个解析器中的权限:
const resolvers = {
Query: {
adminResolver: async (parent, args, context) => {
if(!context.user || !context.roles.includes("admin")) throw new Error("Permission denied!");
...
return data;
},
},
};
2. 输入验证和规范化
过去,开发人员会在前端生成 SQL 查询,并将其发送到 API 以从 SQL 数据库中获取数据;因此,SQL 注入应运而生。攻击者可以编写 SQL 并将其发送到 API,API 会执行该查询,而无需进一步询问。
虽然没有人阻止 GraphQL API 开发人员创建接受在服务器上盲目执行的 SQL 字符串的类型,但这种情况很少见。
但接受来自客户端的数据始终存在风险。这就是为什么在获取任何数据之前,所有输入都应经过验证和规范化。特别是自定义标量由于它们不进行默认验证,因此很容易受到这种威胁。
3. 自省限制
GraphQL 为其 API 使用者提供了便捷的自省功能,允许 GraphQL 客户端询问 API 提供哪些类型的数据。这很棒,因为现在客户端开发人员不必查看文档,而是可以直接询问 API 服务器有哪些数据可用。
但如果不严格控制,内省也可能被滥用。例如,当提供管理功能的 GraphQL 类型可以被普通用户发现和使用时。
GraphQL API 创建者必须使用严格的授权方案进行自省,以使攻击者更难找到 API 漏洞。如果外部开发人员不使用您的 API,在生产环境中禁用自省功能也是一个好主意。
例如,Apollo 服务器允许使用简单的配置标志禁用自省:
const IS_PRODUCTION = process.env.ENVIRONMENT === "production";
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: !IS_PRODUCTION,
});
server.listen();
4. 查询限制
GraphQL 查询为 API 消费者提供了很大的灵活性,只需一个请求就可以准确获取他们想要的数据,但此功能也可能以多种方式被滥用。
恶意客户端可能会出于各种原因创建非常深入、复杂或通常长时间运行的查询。如果这些攻击者发现导致大量计算的极端情况或利用N+1 查询问题,它们会导致 API 超载并严重降低其他客户端的性能。
这就是为什么 GraphQL API 应该将查询执行时间限制在合理的最大值。更好的是,实现此目标的另一种方法是限制查询深度或复杂性,从而使执行常见的 GraphQL DDoS 攻击变得更加困难,这些攻击往往使用递归和深度查询来破坏服务。
5. 上游错误隐藏
如前所述,GraphQL API 不是数据存储机制;这意味着它使用上游服务(如数据库或其他 API)来获取实际数据。这些服务也可能出现错误。如果您将上游服务的错误传递给客户端,攻击者可以利用它们来了解您的架构。
为了减轻这种威胁,您应该始终在将上游错误传递给客户端之前对其进行处理;这样,您可以隐藏获取数据的服务,并禁止攻击者利用这些服务可能存在的错误或安全漏洞。
我们来看下面的代码示例:
const resolvers = {
Query: {
myResolver: async (parent, args, context) => {
try {
const data = await fetchFromRemoteDataSource();
return process(data);
} catch (upstreamError) {
const cleanError = analyzeUpstreamError(upstreamError);
throw cleanError;
}
},
},
};
解析器尝试从远程数据源获取一些数据,但这可能会失败。我们捕获的错误来自远程数据源,因此它可能包含有关数据源的信息。
我们需要分析错误并清除所有上游信息,然后再将其传递给客户端。
确保 GraphQL API 的安全
GraphQL API 是改善前端团队开发人员体验的绝佳方式。它通过为客户提供一种指定所需内容的方式来帮助优化数据获取。但这是以 API 架构的复杂性增加为代价的,这增加了 API 的攻击面。
随着GDPR和加拿大注册会计师协会法律规定罚款高达数百万美元,API 创建者比以往任何时候都更需要保持常见的 API 威胁在开发 API 时要牢记这一点,并留意可能出现的 GraphQL 特定弱点。
原文地址:https://www.moesif.com/blog/technical/security/5-Security-Tips-for-Your-GraphQL-API/