浅识GraphQL安全问题

浅识GraphQL安全问题

GraphQL介绍

GraphQL 是一种数据查询和操作语言,用于API的查询和操作。与传统的REST API不同,GraphQL它是一个中间人,它通过解析器(Resolver)把各方的数据来源(数据库、API、缓存等)整合为一个数据目录树,通过树的机构进行查询,允许客户端精确指定所需的数据结构,然后把需要查询的字段发送给后端,后端再访问数据库返回相应的数据,也兼备把一些分散的数据进行集合的作用,它的精确字段查找也避免了过度获取或不足获取数据的问题,可以看待为Rest API的一个升级版

不过它也不同于Restful API,它并不绑定数据库,它的交互逻辑是

客户端 —— GraphQL(API层) —— 后端代码(解析器/服务层) —— 数据源(数据库、API、缓存等)

GraphQL 本身并不直接与数据库交互,而是通过解析器(Resolvers)调用后端代码,由后端代码完成对数据源(如数据库、第三方API等)的操作,而Rest API的交互逻辑是

客户端 —— 后端代码(控制器/服务层) —— 数据库

一个在线的GraphQL实例,https://swapi-graphql.netlify.app/

下面是查询展示

image-20250131153251758

GraphQL查询形式

image-20250131155243850

其中id、name字段是需要查询的数据,(id: “1”, personID: “1”),则是与sql的id指定查询雷同,还是比较好理解。

GraphQL内省查询

什么为内省查询?GraphQL其实内置了一个接口文档,可以通过内省的方法获取里面的信息,例如对象定义、接口参数,也就是上述提及到的数据目录。它也特意用一些原字段来用于自省查询。

例如:当使用者不知道某个GraphQL接口中的类型哪些是可用的,可以通过**__schema字段来向GraphQL查询哪些类型是可用的**

我们使用下述查询,查询存在的类型

1
2
3
4
5
6
7
{
__schema{
types{
name
}
}
}

image-20250131160458014

还有__type元字段,用于查询特定类型的详细信息,如字段、参数、返回类型等

1
2
3
4
5
6
7
8
9
10
11
{
__type(name: "查询类型名(区分大小写)") {
name
fields {
name
type {
name
}
}
}
}

image-20250131162914777

__typename返回查询对象的类型名称

1
2
3
4
5
6
{
person(personID: "1", id: 1) {
__typename
name
}
}

image-20250131162140131

我们也可以一把梭哈:

内省查询payload(把请求包的json请求,切换为下述),可以查询出所有的接口信息:

1
{"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  }"}

实现脱数据目录的效果

image-20250131163430526

然后对字段进行进一步查询,就可以实现脱裤咯

自动化测试

使用名为inql的burp插件

项目地址:https://github.com/doyensec/inql

直接丢一个GraphQL节点过去分析即可!即可全盘托出数据目录。

image-20250131165240413

1


浅识GraphQL安全问题
http://example.com/2025/01/31/浅识GraphQL安全问题/
作者
Yf3te
发布于
2025年1月31日
许可协议