GraphQL 是一种查询语言,用于 API 设计和数据交互。它是由 Facebook 发布的一款新型的数据查询和操作语言,自 2012 年起在内部使用,自 2015 年起获得开源许可。由于技术原因,越来越多的公司使用 GraphQL 并将其后端切换到这个新系统,但是,虽然这种查询语言有很多优点,但随着查询变得更加复杂,它也有一些安全问题。信息泄露、业务逻辑错误、IDOR 和不当访问控制是 GraphQL 端点上最常见的漏洞。

GraphQL与传统RESTful API的区别

GraphQL 允许客户端在一个请求中明确地指定需要的数据,并返回预期的结果,而不是像 RESTful API 那样只能获取预定义的资源。因此,GraphQL 简化了客户端与服务器之间的通信,提高了应用程序的性能和可扩展性。

与传统的 RESTful API 不同,GraphQL 通过将数据查询和数据修改分离开来,使得客户端能够更灵活地控制所需数据的粒度和类型,并且在多个资源之间建立关系。这样,客户端就可以很容易地实现高效的数据获取和更新,而无需为每个特定的用例编写特定的 API。

GraphQL应用

目前正在使用GraphQL的大型公司包括Facebook、PayPal、GitHub、Shopify、Twitter、Tesla、Hackerone等大型公司,可见GraphQL正在迅猛发展。

GraphQL渗透测试前置知识

GraphQL查询语言

我们根据前文已经得知,GraphQL是一种用于API的查询语言,它支持很多种查询方式:

  • Query
  • Mutation
  • Subscription
  • Input
  • Enum
  • Union
  • Interface

我们接下来主要介绍一下Query、Mutation、Subscription这三种。

Query

Query是GraphQL中最常用的一种方式。它用于从服务端获取数据,类似于RESTful API的GET方法。使用Query可以指定需要返回的字段以及过滤条件。

例如,以下查询会请求服务器返回用户ID为1的用户名和电子邮件地址:

javascript
复制代码
query {
  user(id: 1) {
    name
    email
  }
}
Mutation

Mutation用于在服务端修改或添加数据,类似于RESTful API的POST、PUT和DELETE方法。Mutation支持向服务端提交一些参数,并根据参数来执行相应的操作。

例如,以下Mutation会将用户ID为1的用户名更改为"NewName":

bash
复制代码
mutation {
  updateUser(id: 1, name: "NewName") {
    id
    name
    email
  }
}
Subscription

Subscription是GraphQL中的一种高级特性,它允许客户端通过WebSocket连接实时接收来自服务器的数据更新。这对于需要实时通知的应用程序非常有用,如在线聊天、股票报价等。

例如,以下Subscription会订阅一个名为newMessage的频道,并在有新消息时返回消息内容:

css
复制代码
subscription {
  newMessage(channel: "chat") {
    content
    author
  }
}

GraphQL渗透测试方法和流程

  • 渗透测试准备工作

  • 渗透测试步骤

    • 枚举 GraphQL Schema
    • 查询漏洞
    • 注入漏洞
    • 认证和授权漏洞
常见的GraphQL路径
bash
复制代码
/graphql
/graphql-console
/graphql-devtools
/graphql-explorer
/graphql-playground
/graphql-playground-html
/graphql.php
/graphql/console
/graphql/graphql
/graphql/graphql-playground
/graphql/schema.json
/graphql/schema.xml
/graphql/schema.yaml
/graphql/v1
/HyperGraphQL
/je/graphql
/laravel-graphql-playground
/lol/graphql
/portal-graphql
/v1/api/graphql
/v1/graphql
/v1/graphql-explorer
/v1/graphql.php
/v1/graphql/console
/v1/graphql/schema.json
/v1/graphql/schema.xml
/v1/graphql/schema.yaml
/v2/api/graphql
/v2/graphql
/v2/graphql-explorer
/v2/graphql.php
/graph
/graphql/console/
/graphiql
/graphiql.php
内省攻击

内省攻击本质上来说就是因为没有修改默认配置导致攻击者可以通过查询 __schema 或者 __type 等系统级别的 Schema 来获取服务器上定义的所有类型、字段、枚举等信息。攻击者可以利用这些信息去了解服务器的数据结构和业务逻辑,为下一步的攻击行动做准备。

内省攻击包含以下几个方面:

  • 获取所有暴露的接口和类型信息:攻击者可以使用 __schema 查询来获取所有可用的 Schema 信息,包括对象类型、标量类型、枚举类型、接口类型和输入类型等。
  • 获取所有字段信息:攻击者可以通过 __type.fields 查询来获取所有字段信息,包括字段名称、类型和描述等。
  • 获取实际数据:攻击者可以通过查询实际数据,如用户账号、密码、秘密答案等,从而获取更高的权限或者直接篡改系统。

如下三段GraphQL 查询语句本质上是相同的,都是用于获取 GraphQL Schema 的元数据信息。它们的区别在于格式和编写方式

typescript
复制代码
{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}
json
复制代码
{"query": "query IntrospectionQuery{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}"}
swift
复制代码
{"query":"query Query {\n    __schema {\n      queryType { name }\n      mutationType { name }\n      subscriptionType { name }\n      types {\n        ...FullType\n      }\n      directives {\n        name\n        description\n        locations\n        args {\n          ...InputValue\n        }\n      }\n    }\n  }\n\n  fragment FullType on __Type {\n    kind\n    name\n    description\n    fields(includeDeprecated: true) {\n      name\n      description\n      args {\n        ...InputValue\n      }\n      type {\n        ...TypeRef\n      }\n      isDeprecated\n      deprecationReason\n    }\n    inputFields {\n      ...InputValue\n    }\n    interfaces {\n      ...TypeRef\n    }\n    enumValues(includeDeprecated: true) {\n      name\n      description\n      isDeprecated\n      deprecationReason\n    }\n    possibleTypes {\n      ...TypeRef\n    }\n  }\n\n  fragment InputValue on __InputValue {\n    name\n    description\n    type { ...TypeRef }\n    defaultValue\n  }\n\n  fragment TypeRef on __Type {\n    kind\n    name\n    ofType {\n      kind\n      name\n      ofType {\n        kind\n        name\n        ofType {\n          kind\n          name\n          ofType {\n            kind\n            name\n            ofType {\n              kind\n              name\n              ofType {\n                kind\n                name\n                ofType {\n                  kind\n                  name\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }"}

可以使用burp的插件进行分析

之后就可以查找其中一些漏洞了,比如修改ID参数查询其他人员信息

如果graphql内省模式被禁用,可以尝试使用工具。

github.com/nikitastupi…

github.com/assetnote/b…

GraphQL 渗透测试实战案例分析

消耗服务器资源攻击案例

我们首先请求一次该接口发现用时30481

然后添加一个systemUpdate参数再次请求,可以看到时间变成了80725。如果添加更多的systemUpdate参数即可导致攻击发生。

SSRF漏洞案例

防御和修复 GraphQL 漏洞的建议

  1. 限制查询语句的深度和复杂度:GraphQL 支持嵌套查询和参数化查询,这使得攻击者可以构造非常复杂的查询来增加服务器的负载,甚至可能导致拒绝服务攻击。为了防范此类攻击,可以对查询语句进行深度和复杂度限制,以确保每个查询不会占用过多的资源。
  2. 限制查询的访问权限:GraphQL API 应该只允许授权访问,而不是任何人都可以访问。可以通过身份验证、IP 白名单、API 密钥等方式来限制查询的访问权限,从而避免恶意查询和攻击。
  3. 限制查询返回的字段和数据量:攻击者可以利用查询返回大量的数据来耗尽服务器资源或者获取敏感信息。为了防止这种情况发生,应该限制每个查询返回的字段和数据量,并对某些敏感字段进行隐藏或者过滤处理。
  4. 检查输入参数的合法性:GraphQL 允许客户端自由传递参数,这也使得攻击者可以利用参数注入漏洞来攻击系统。因此,在服务器端需要对输入参数进行严格校验和过滤,避免恶意参数的注入和攻击。
  5. 关闭内省查询:GraphQL 内省机制被用来获取服务器上定义的所有类型、字段、枚举等信息。攻击者可以利用这些信息了解服务器的数据结构和业务逻辑,从而进行进一步攻击。为了防范此类攻击,应该关闭或限制内省查询功能。

​最后

为了帮助大家更好的学习网络安全,小编给大家准备了一份网络安全入门/进阶学习资料,里面的内容都是适合零基础小白的笔记和资料,不懂编程也能听懂、看懂,所有资料共282G,朋友们如果有需要全套网络安全入门+进阶学习资源包,可以点击免费领取(如遇扫码问题,可以在评论区留言领取哦)~

😝有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

👉CSDN大礼包🎁:全网最全《网络安全入门&进阶学习资源包》免费分享(安全链接,放心点击)👈

1️⃣零基础入门

① 学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

② 路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

因篇幅有限,仅展示部分资料

2️⃣视频配套资料&国内外网安书籍、文档

① 文档和书籍资料

② 黑客技术

因篇幅有限,仅展示部分资料

👉CSDN大礼包🎁:全网最全《网络安全入门&进阶学习资源包》免费分享(安全链接,放心点击)👈

3️⃣网络安全源码合集+工具包

4️⃣网络安全面试题

5️⃣汇总

所有资料 ⚡️ ,朋友们如果有需要全套 《网络安全入门+进阶学习资源包》,扫码获取~

👉CSDN大礼包🎁:全网最全《网络安全入门&进阶学习资源包》免费分享(安全链接,放心点击)👈

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐