freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

GraphQL API渗透测试指南
2023-09-05 16:17:13

GraphQL 简介

GraphQL 是一种面向数据的 API 查询风格。传统的 API 拿到的是前后端约定好的数据格式,GraphQL 对 API 中的数据提供了一套易于理解的完整描述,客户端能够准确地获得它需要的数据,没有任何冗余,也让 API 更容易地随着时间推移而演进。

RESTful VS GraphQL

GraphQL API与Rest API最大的区别在于:GraphQL 通过将数据查询和数据修改分离开来,使得客户端能够更灵活地控制所需数据的粒度和类型,并且在多个资源之间建立关系。GraphQL只需一次请求就能够获取全部所需要的数据,而不是像RESTful API那样,要想获取所有数据就必须发起多次API请求。

1693901218_64f6e1a202750ad42debb.png!small?1693901219080

前置知识

GraphQL查询方式

GraphQL是一种用于API的查询语言,首先我们就需要知道GraphQL有哪些查询方式

主要有

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

其中最为常见的是QueryMutationSubscription这三种,Query用于向服务端查询指定数据、Mutation用于在服务端修改或添加数据,具体可参考官方文档进行了解:https://graphql.org/learn/

GraphQL内省查询

简单来说就是,GraphQL内查机制,通常是内部可用,通过内省的方法获得相关信息,如对象定义、接口参数等信息。一般查询前面带有双下划线的就表示内省的一部分,比如:__Schema,__Type,__TypeKind,__Field,__InputValue,__EnumValue,__Directive等,官方文档:https://graphql.org/learn/introspection/

GraphQL API发现

当我们在测试时,如何发现GraphQL API?下面介绍几种有效的方法。

  • 常见的GraphQL路径判定

GraphQL API与Restful API不同,一般来说它的URL比较固定,这也是它的特性之一,从单个请求中获取应用程序所需的所有数据。

常见的GraphQL路径如下:

/graphql
/graphiql
/v1/graphql
/v2/graphql
/v3/graphql
/v1/graphiql
/v2/graphiql
/v3/graphiql
/api/graphql
/api/graphiql
/graphql/api
/graphql/console
/console
/playground
/gql
/query
/graphql-devtools
/graphql-explorer
/graphql-playground
/graphql.php
/index.php?graphql
......
  • 通用查询探测

由于GraphQL API中存在一个__typename的保留字段,该字段会以字符串形式返回查询对象的类型,所以我们可以向未知API发送query{__typename},如果响应中返回{"data": {"__typename": "query"}},那么就可以确定该API为GraphQL API。

1693901241_64f6e1b91a11e576dc076.png!small?1693901241784

  • 内省查询

向未知API发送__schema字段使用自省来发现架构信息,该字段在所有查询的根类型上都可用。

query {__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}

可以查询到所有类型、字段、参数以及参数类型

1693901251_64f6e1c36922acd60d194.png!small?1693901253388

  • 改变请求方法/报错信息判断

利用不同的请求方法(GET、POST)发起请求也能够进行GraphQL API的辨别,因为对于一些仅允许某种请求方法的GraphQL API而言,不同的请求方法返回的格式和内容也不同。

除此之外,根据报错信息可以判断是否为GraphQL API,

主要特征是Syntax Error: Expected Name, found

1693901292_64f6e1ec2bc643025e0ad.png!small?1693901294163

GraphQL API攻击面

内省查询攻击

通过了解GraphQL的内省查询机制,其实我们可以发现在相关系统没修改默认配置的情况下,我们可以通过__schema或者__type等来进行系统级别的查询,以获取服务器上定义的所有类型、字段、敏感信息等

通过内省查询,我们获取到系统所有相关字段及信息,如下图:

1693901308_64f6e1fcd3ff59faf0caf.png!small?1693901310638

然后利用voyager工具将查询结果可视化

1693901318_64f6e20650a53db51e073.png!small?1693901320477

获取数据结构以便进一步利用

1693901327_64f6e20fd4f3ddf999cfa.png!small?1693901328578

拒绝服务

  • 批量查询

GraphQL支持请求批处理,并且会对请求一个一个处理,这就导致可以利用批量查询来实施Dos攻击

示例:

请求body:
{"query":"query {\n systemUpdate\n}","variables":[]}, 
{"query": "query {\n systemUpdate\n}","variables":[]}, 
{"query":"query {\n systemUpdate\n}","variables":[]} 
  • 深度递归查询

当查询类型相互引用时,通过构建一个循环查询,来实现Dos攻击

query { 
  Pastes { 
    Owner { 
      Pastes { 
        Owner { 
          Pastes { 
  Owner 
            { 
              Pastes { 
                Owner { 
                  Pastes { 
                    Owner { 
                      Pastes { 
                        Owner { 
                          name 
                        } 
                      } 
                    } 
                  } } 
} 
                } 
              } 
            } 
          } 
        } 
      } 
    }

随着查询呈指数级增长,最终导致服务器崩溃。

1693901354_64f6e22a52678b29d61ed.png!small?1693901354929

  • 字段重复查询

由于GraphQL API不会对重读字段进行去重处理,所以还可以通过查询重复字段进行Dos攻击。

query {
  pastes {
    owner {
      pastes {
            ipAddr # 1
            ipAddr # 2
            ipAddr # 3
            ipAddr # 4
            ......
            ipAddr # 1000
          }
        }
      }
}

越权查询/信息泄露

通过内审查询获取到相关信息后,可以进一步利用,GraphQL API作为单路由API接口在查询过程中往往会忽略一些鉴权问题,这可能导致越权漏洞的出现,并且泄露敏感信息。

例如在查询到存在id参数。

1693901372_64f6e23c6d127f01e242c.png!small?1693901373799

通过修改id参数进行水平越权,获取想要的敏感信息。

1693901383_64f6e24728006d3bb2ca4.png!small?1693901384211


1693901392_64f6e2508a40f71a1c010.png!small?1693901393542

命令执行

由于GraphQL API没有充分验证输入或者没有严格过滤,导致在一些查询中可以通过链接的形式拼接 UNIX 命令,达到命令执行的目的。

1693901404_64f6e25c6552b4db78de4.png!small?1693901404781

或者是通过systemDiagnostics接受某些 UNIX 二进制文件作为调试目的的参数,例如whoamips等,在获取相关凭证或者权限之后,可以进行拼接来达到命令执行的目的。

1693901413_64f6e26532f3e469430b9.png!small?1693901413552

SQL注入

GraphQL API同样会可能存在SQL注入漏洞,可以对查询结构体中的一些参数进行SQL注入尝试。

1693901428_64f6e27458881f965e5fc.png!small?1693901428724

这里对“test”参数进行SQL注入尝试。

1693901439_64f6e27fe05204033b681.png!small?1693901441296

加上单引号后返回报错信息。

1693901450_64f6e28a8575c363c5988.png!small?1693901451538

后续直接利用sqlmap进行后续操作。

1693901460_64f6e29478c851938db44.png!small?1693901461886

graphql注入

类似于SQL注入拼接字符串,在GraphQL API进行相关查询时,可以通过拼接的方式进行注入来获取数据或者改变查询逻辑。

正常查询:

mutation {
  create(content: "test", id: 1) {
      name
      password
      title
   }
}

graphql注入:

mutation {
  editPaste(content: "test", id: 1) {      name      title    }     changePassword(password: "admin123") {
      name
      password
      title
   }
}

XSS

GraphQL API同样也会遭受xss攻击,其实针对任何存在系统而言,如果没有相应的防御手段,没有对输入性参数进行过滤都可能遭受一些输入型漏洞攻击。

1693901478_64f6e2a67778be1eb60f9.png!small?1693901478883

攻击载荷成功解析,此外也可以利用上传功能上传HTML脚本进行攻击测试。

1693901487_64f6e2af82c3fd5a7b91c.png!small?1693901489683

SSRF

如果在GraphQL相关查询操作允许本地主机或其他服务器不限制输入,就可能遭受服务端请求伪造攻击

漏洞案例:

1693901507_64f6e2c38bc774c679007.png!small?1693901509265

1693901518_64f6e2ce26518856c60b9.png!small?1693901519146

保护机制绕过

在GrapQL API中如果存在相关恶意输入保护机制,可以利用修改请求投参数进行绕过。例如下面使用IDE时,进行命令执行时,存在保护机制。

1693901532_64f6e2dcd91e6a4724c60.png!small?1693901534418

发现Cookie中存在明显的disable字段。

1693901540_64f6e2e4ac450e354f786.png!small?1693901542958

修改disableenable

1693901575_64f6e3071a032da286283.png!small?1693901576037

成功绕过保护机制。

1693901561_64f6e2f90a51eff8e418e.png!small?1693901561693

登陆爆破

在GraphQL API通过可以实现弱密码爆破来碰碰运气,不过还得分无登陆次数限制和有登陆次数限制两种情况。

无登陆次数限制

如果无登陆次数的限制,直接可进行弱密码爆破。

1693901592_64f6e318bff1c9171ad0b.png!small?1693901593395

1693901603_64f6e32335e3578119894.png!small?1693901604230

1693901614_64f6e32e4ad3681a2c322.png!small?1693901614814

有登陆次数限制

如果一些网站存在登陆次数的限制,比如下面在爆破过程中。

1693901633_64f6e34137a7d7015a25c.png!small?1693901634583

会提示过多登陆尝试

GraphQL对象不能够包含多个同名的属性,所以我们可以利用别名来实现多个同属性的操作,这样如果系统只限制了API请求速率,那么也可以通过别名查询来实现登陆爆破。

1693901643_64f6e34b08f405661eba9.png!small?1693901643788

1693901673_64f6e369a90af065036ad.png!small?1693901674442

JWT令牌伪造

可以通过相关工具获取GraphQL API的数据结构,这里我们就发现了存在新建用户的操作。

1693901682_64f6e372dd9c0a48eccb1.png!small?1693901683939

利用这个接口创建一个新用户。

1693901690_64f6e37a3dbdf83b2c6e6.png!small?1693901691458

发现登陆操作。

1693901721_64f6e399b20b07c3c5840.png!small?1693901722831

利用新建用户成功查询到accessToken

1693901734_64f6e3a64418963ab1e3e.png!small?1693901735485

发现可以利用token进行管理员敏感信息查询。

1693901744_64f6e3b00caab3e04e0f3.png!small?1693901744845

尝试用刚才的token进行尝试,发现还是新建用户的信息。

1693901752_64f6e3b82fc2de004bf6d.png!small?1693901752625

伪造JWT,把新用户的token解析后,修改为admin。

1693901759_64f6e3bfde27e94658a85.png!small?1693901760648

成功查询到管理账号密码。

1693901767_64f6e3c7a427d51071911.png!small?1693901768133

目录穿越/任意文件写入

在GraphQL API中相关文件上传/下载操作也可能存在目录穿越、任意文件读取、任意文件写入等漏洞

例如通过目录穿越成功任意文件写入。

1693901776_64f6e3d0915bf6fc668de.png!small?1693901776950

成功上传至tmp目录。

1693901785_64f6e3d9961a9e1e37c1a.png!small?1693901785871

工具:

除了传统的渗透测试工具以外,使用GraphQL API的工具也变得十分重要。

inql:GraphQL测试工具, 可以独立使用,也可作为Burp扩展使用,https://github.com/doyensec/inql

voyager:GraphQL API交互可视化工具,https://github.com/graphql-kit/graphql-voyager

GraphQLmap:GraphQL API渗透测试脚本引擎,https://github.com/swisskyrepo/GraphQLmap

graphiql:基于浏览器的GraphQL IDE工具https://github.com/graphql/graphiql

# 渗透测试 # web安全 # 系统安全 # 数据安全 # 网络安全技术
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录