浅识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/
下面是查询展示

GraphQL查询形式

其中id、name字段是需要查询的数据,(id: “1”, personID: “1”),则是与sql的id指定查询雷同,还是比较好理解。
GraphQL内省查询
什么为内省查询?GraphQL其实内置了一个接口文档,可以通过内省的方法获取里面的信息,例如对象定义、接口参数,也就是上述提及到的数据目录。它也特意用一些原字段来用于自省查询。
例如:当使用者不知道某个GraphQL接口中的类型哪些是可用的,可以通过**__schema字段来向GraphQL查询哪些类型是可用的**
我们使用下述查询,查询存在的类型
1 2 3 4 5 6 7
| { __schema{ types{ name } } }
|

还有__type元字段,用于查询特定类型的详细信息,如字段、参数、返回类型等
1 2 3 4 5 6 7 8 9 10 11
| { __type(name: "查询类型名(区分大小写)") { name fields { name type { name } } } }
|

__typename返回查询对象的类型名称
1 2 3 4 5 6
| { person(personID: "1", id: 1) { __typename name } }
|

我们也可以一把梭哈:
内省查询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 }"}
|
实现脱数据目录的效果

然后对字段进行进一步查询,就可以实现脱裤咯
自动化测试
使用名为inql的burp插件
项目地址:https://github.com/doyensec/inql
直接丢一个GraphQL节点过去分析即可!即可全盘托出数据目录。

1