GraphQl详解以及攻击面分析

admin 2026-02-03 01:13:03 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详解GraphQL语法及其与REST的区别,重点分析信息泄露、深度嵌套DoS、权限绕过及注入攻击等安全风险。文章提供内省查询和服务发现路径检测方法,并推荐使用Burp插件InQL辅助测试,为安全评估提供实战参考。 综合评分: 90 文章分类: WEB安全,漏洞分析,渗透测试


cover_image

GraphQl详解以及攻击面分析

原创

信安路漫漫 信安路漫漫

信安路漫漫

2026年2月2日 07:01 上海

前言

GraphQL是一种由‌Facebook开发的‌API查询语言,通过声明式数据获取机制实现精准高效的数据交互,现已成为现代前端开发的重要技术方案。

本篇文章来看看GraphQL的实现以及可能存在的安全问题。

GraphQL的优点

GraphQL在前端开发中的应用优势

‌‌灵活字段选取‌

允许前端开发者精准指定所需数据字段,避免‌REST接口的过度获取或数据不足问题。‌‌

GraphQL 的灵活性体现在客户端可以完全自主地决定需要获取的数据结构和字段。这意味着,无论前端应用是一个简单的展示页面,还是一个复杂的单页应用(SPA),都可以根据自身的需求,精确地从服务器获取数据,而无需受到固定数据结构的限制。

减少网络请求‌

通过单次查询即可获取多层级关联数据,有效解决传统‌REST接口的多次请求问题。‌‌

在传统的 RESTful API 中,为了获取多个相关资源的数据,客户端往往需要多次发起 HTTP 请求。这不仅增加了网络开销,还可能导致页面加载缓慢,影响用户体验。而 GraphQL 通过允许在一次请求中获取多个资源的数据,有效地减少了网络请求次数,提高了数据获取的效率。

强类型校验‌

内置‌类型系统支持自动生成文档,提升前后端协作效率。‌‌

GraphQL提供了强类型的schema机制,从而天然确保了参数类型的合法性。

GraphQL与REST安全对比

与传统的 RESTful API 不同,GraphQL 允许客户端精确地请求所需的数据,避免了数据的冗余传输和多次请求的问题。它就像是一个灵活的数据点菜系统,客户端可以根据自己的需求,从服务器这个 “菜单” 中选择特定的数据 “菜品”,而不是像 RESTful API 那样,只能接受固定的 “套餐”。

在传统的 RESTful API 架构中,客户端获取数据时,可能需要向多个不同的端点发送请求。例如,在一个社交媒体应用中,客户端想要获取用户的基本信息(如用户名、头像)以及该用户最近发布的 5 条动态,可能就需要分别向/users/{id}端点获取用户基本信息,再向/posts/user/{id}端点获取用户动态,并且由于 RESTful API 返回的数据结构通常是固定的,客户端可能会获取到一些不需要的数据,造成带宽浪费,或者获取不到某些需要的数据,还得再次请求。

语法详解

查询

在 GraphQL 中,查询是获取数据的主要方式 。查询语句的结构非常直观,它以一个根字段开始,后面跟着需要获取的子字段,就像在 JSON 对象中访问嵌套属性一样。例如,获取文章和评论的信息

{    article(aid:1) {        title        content        author {            uid            name        }    },    comment {        content,        author {            uid            name        }    }}

变更

变更操作主要用于修改服务器上的数据,比如添加、更新和删除数据。它的语法结构与查询类似,但通常会使用mutation关键字来标识这是一个变更操作。

添加数据时,以添加用户为例,假设我们有一个User类型,包含name和email字段:

addUser是自定义的变更操作名称,后面的参数name和email是要添加用户的属性值。返回值部分指定了我们希望在添加用户成功后返回的字段,这里包括新用户的id、name和email。

mutation {addUser(name: "John Doe", email: "[email protected]") {idnameemail}}

更新

这里updateUser是更新操作,id参数指定要更新的用户,email是新的邮箱值。

mutation {updateUser(id: "1", email: "[email protected]") {idnameemail}}

删除

deleteUser操作根据id删除用户,返回值success用于表示删除操作是否成功。

mutation {deleteUser(id: "1") {success}}

订阅

订阅允许客户端实时监听服务器端数据的变化。当服务器端数据发生特定事件时,会主动推送更新给订阅了相关事件的客户端。例如,在一个聊天应用中,用户可以订阅新消息事件,这样每当有新消息到达时,客户端就能立即收到通知并获取新消息内容。

假设我们有一个Message类型,包含id、text和sender字段,订阅新消息的示例如下:

subscription {newMessage {idtextsender}}

在服务器端,需要配置相应的解析器和事件触发器,当有新消息产生时,触发订阅的解析器,将新消息数据推送给客户端。订阅在实时数据展示、实时通知等场景中非常有用,能为用户提供更及时、流畅的体验。

内省查询

GraphQL的内省查询是一种用于获取GraphQL服务端提供的模式信息的特殊查询,通过内省查询客户端可以动态地查询和探索GraphQL模式,了解可用的类型、字段、关联和其他模式相关的元数据,GraphQL的内省查询使用特殊的元字段schema和type来执行,下面是对GraphQL内省查询的详细介绍和示例

通过__schema查询所有可用对象:

{  __schema {    types {      name    }  }}

通过__type查询指定对象的所有字段:

{  __type(name: "Film") {    name    fields {      name      type {        name        kind        ofType {          name          kind        }      }    }  }}

服务发现

在我们对网站进行安全评估时我们可以多多注意下列路径,这将有助于我们发现关联的接口来确定目标站点支持graphql的查询方式

altairexplorergraphiqlgraphiql.cssgraphiql/finlandgraphiql.jsgraphiql.min.cssgraphiql.min.jsgraphiql.phpgraphqlgraphql/consolegraphql-explorergraphql.phpgraphql/schema.jsongraphql/schema.xmlgraphql/schema.yamlplaygroundsubscriptionsapi/graphqlgraphv1/altairv1/explorerv1/graphiqlv1/graphiql.cssv1/graphiql/finlandv1/graphiql.jsv1/graphiql.min.cssv1/graphiql.min.jsv1/graphiql.phpv1/graphqlv1/graphql/consolev1/graphql-explorerv1/graphql.phpv1/graphql/schema.jsonv1/graphql/schema.xmlv1/graphql/schema.yamlv1/playgroundv1/subscriptionsv1/api/graphqlv1/graphv2/altairv2/explorerv2/graphiqlv2/graphiql.cssv2/graphiql/finlandv2/graphiql.jsv2/graphiql.min.cssv2/graphiql.min.jsv2/graphiql.phpv2/graphqlv2/graphql/consolev2/graphql-explorerv2/graphql.phpv2/graphql/schema.jsonv2/graphql/schema.xmlv2/graphql/schema.yamlv2/playgroundv2/subscriptionsv2/api/graphqlv2/graphv3/altairv3/explorerv3/graphiqlv3/graphiql.cssv3/graphiql/finlandv3/graphiql.jsv3/graphiql.min.cssv3/graphiql.min.jsv3/graphiql.phpv3/graphqlv3/graphql/consolev3/graphql-explorerv3/graphql.phpv3/graphql/schema.jsonv3/graphql/schema.xmlv3/graphql/schema.yamlv3/playgroundv3/subscriptionsv3/api/graphqlv3/graphv4/altairv4/explorerv4/graphiqlv4/graphiql.cssv4/graphiql/finlandv4/graphiql.jsv4/graphiql.min.cssv4/graphiql.min.jsv4/graphiql.phpv4/graphqlv4/graphql/consolev4/graphql-explorerv4/graphql.phpv4/graphql/schema.jsonv4/graphql/schema.xmlv4/graphql/schema.yamlv4/playgroundv4/subscriptionsv4/api/graphqlv4/graph

安全风险

过度获取数据(Over-fetching)与数据泄露

客户端可以自由指定查询字段,可能导致返回过多数据,包括本应隐藏的敏感信息(如密码、内部ID)。可以结合内省查询枚举所有数据结构

如下,正常查询包含下面的字段

通过内省查询,可以发现存在postPassword字段

直接添加该字段发送,可以获取密码密文

深度嵌套查询 (N+1 查询问题)

客户端可构造深度嵌套查询(如多层关联),导致服务器执行指数级数据库查询,引发资源耗尽(N+1查询问题)。‌

query IAmEvil {  author(id: "abc") {    posts {      author {        posts {          author {            posts {              author {                # 可无限深度嵌套!              }            }          }        }      }    }  }}

权限问题

GraphQL很常见的一个就是权限问题了,目前很多的接口要么是采用业务逻辑鉴权,要么就是使用RBAC基于角色的鉴权,很多角色在创建之初并没有进行细微的权限划分,导致后期随着业务的开发越来越多的角色添加进来,而接口尚并未通过添加注解进行鉴权或者还有一种就是对鉴权逻辑存在设计缺陷,导致整改鉴权体系混乱,出现一大批的越权漏洞。

内省开启导致的敏感信息泄漏

GraphQL内省是一个特殊查询,其支持的内省查询有两个__schema、__type。内省查询的作用是提供详细接口信息,简单的来说就是可以通过内省查询来获取GraphQL的接口文档,如对象定义、接口参数等信息。

可以使用插件查看完全的信息如下

GraphQL注入

有语法就会有解析,有解析就会有结构和顺序,有结构和顺序就会有注入。

# 查询query GetUser($id: ID!) {  user(id: $id) { name }}# 正常变量{ "id": "1" }# 注入变量{ "id": "1' OR '1'='1" }

Burp插件使用-InQL

InQL提供的主要工具是一个可自定义的扫描程序,主要用于分析GraphQL端点或本地内省模式文件,它生成所有可能的查询和突变并以有组织的视图显示它们以进行彻底分析,扫描结果可以发送到Burp的中继器或入侵者工具进行进一步测试,同时它也引入了GQLSpection,它是一个多功能的CLI工具并以无头模式发送内省查询、解析结果、生成查询和运行兴趣点扫描,我们可以在Burpsuite的”Extensions->BApp Store”中选择插件并进行安装

将发现的GraphQL发送到插件,可以自动识别支持的查询

参考链接

https://blog.csdn.net/xiaoyingxixi1989/article/details/149260049

https://xz.aliyun.com/news/13173

https://blog.csdn.net/lxcxjxhx/article/details/152776056


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:信安路漫漫 信安路漫漫 信安路漫漫《GraphQl详解以及攻击面分析》

评论:0   参与:  0