发现GraphQL端点和SQL注入漏洞
翻译文章,原文:Discovering GraphQL endpoints and SQLi vulnerabilities[1]
介绍
GraphQL 是一个开源的数据查询语言(DQL)和数据处理语言(DML).最初,GraphQL由Facebook于2012年左右开发并于2015年公开发布。其主要优点之一是为其他Web服务体系结构(如REST)提供了一种更高效,更强大的替代方案。
结构
需要指出的一件有趣的事是GraphQL并没有绑定到任何特定的数据库(或与此相关的存储引擎),而是由现有代码支持。这是什么意思呢?不同于REST APIs(客户端首先与程序员编写的任意代码进行交互,然后此代码到达数据库);客户端首先与GraphQL进行交互,后者又与任意代码进行交互,并最终结束与数据库的对话。描述这种情况的更有用的图是:
架构的这种变化具有很多优势,例如,可以在单个请求中获得客户端所需的所有数据(而REST API需要执行多个请求)。
基础
对象类型和字段
{
films {
id,
name,
genre,
rating
}
}
在这个例子中,我们要求提供与films
对象相关的id
,name
,genre
和rating
字段。我们可以得到的标准答案是:
{
"data": {
"films": [
{
"id": "1",
"name": "Blade Runner",
"genre": "sci-fi",
"rating": 8.2,
},
{
"id": "2",
"name": "Back to the Future",
"genre": "sci-fi",
"rating": 8.5,
},
{
"id": "3",
"name": "The Shawshank Redemption",
"genre": "drama",
"rating": 9.3,
}
]
}
}
有趣的是,我们得到的响应与请求具有相同的形状(使用GraphQL的另一个好处,我们总是知道会发生什么)。
争议
这是开始变得有趣的地方,如果底层代码允许,我们可以发出这样的请求:
{
film(id: 3) {
name,
genre
}
}
本质上,我们在这里要做的是指示要获取的条目(id:3),并询问name
和genre
字段:
{
"data": {
"film": {
"name": "The Shawshank Redemption",
"genre": "drama"
}
}
}
GraphQL还有很多功能(别名,片段,变量等)。我显然不会描述所有这些内容;该文档[2]详细介绍了所有内容,并且非常易于阅读。
GraphQL 端点
如果刚开始审核的网络服务器似乎没有GraphQL端点,不要泄气。常见的GraphQL端点路径可以是(以及其他):
•/graphql/
•/graphql/console/
•/graphql.php
•/graphiql/
•/graphiql.php
•[...]
另外,请记住GraphQL端点可以像这样描述:
或是像这样的简单描述:
一个好的方法确认是否为GraphQL,我们可以给一个我们认为的GraphQl端点发送一个无效的查询,例如:
如果在发出上述请求后,我们得到类似·"Syntax Error: Expected Name, found }”
的信息,那么我们可以安全地确认我们正在处理GraphQL端点。
要考虑的另一件重要事情是,其中一些仅允许某些HTTP请求(GET / POST /等),因此请尝试首先使用不同的方法:
检查
我们发现了一个GraphQL端点,并且可以与其进行交互。非常棒!之后怎么办?我们的下一步将是查询模式,以便知道如何与之对话。GraphQL通过使用其 Introspection[3] 来允许此操作。有了它,我们可以获得有关服务器可用查询,类型,字段,突变等的信息。
如果要获取所有可用信息,可以使用GraphQL-JS中的 built-in introspection query[4]。如果我们有一个完全交互式的GraphiQL端点(在此示例中,我使用的是该 项目[5] 的修改版),我们可以简单地转到<Docs
节,构造有效查询所需要的一切都在这里:
现在我们知道可以要求一个特定的bacon
对象(以id
作为参数),也可以要求不同的bacon
对象(以type
和price
为参数)。一些例子:
如果;但是,我们没有交互式端点,我们还有其他几种选择来获取模式:
•手动发出内省查询,并通过读取响应找出所有内容(痛苦,我知道)。如果您想走这条路, 这里[6] 是完整的URL-encoded payload。•用 graphql-ide[7] (它将自动获取所有内容)•用 GraphQL_Introspection.py[8](Doyensec 写的非常优秀的Python脚本)
SQL注入
如前所述,GraphQL最终与程序员编写的任意代码进行交互。GraphQL本身无法阻止任何类型的攻击,因此,如果他们犯了错误(例如,未使用参数化查询),则该应用程序可能会受到SQL注入攻击。
请记住,应用程序可能不会引发错误,但仍然容易受到 blind,time-based甚至out-of-band SQL注入攻击。同样,不要愚蠢地认为 scalar types [9] 不会很容易受到攻击;在很多情况下,我们只需将其用双引号 ""
引起来并在其中注入:
剩下的就是历史了;我们可以保存HTTP请求并启动sqlmap或手动构造SQLi并在数据库中获取我们能够到达的所有内容:
其他漏洞
基于GraphQL的Web应用程序(和端点)可能容易受到许多其他类型的漏洞的攻击。从绕过访问控制到敏感的数据公开,NoSQL注入等等。如果您想阅读这些示例和实际案例,我强烈建议 例子[10],例子[11]和例子[12]
参考
•https://en.wikipedia.org/wiki/GraphQL•https://graphql.org/learn/•http://bearcatjs.org/graphql-versus-rest-api/•https://blog.doyensec.com/2018/05/17/graphql-security-overview.html•https://labs.detectify.com/2018/03/14/graphql-abuse/•http://www.petecorey.com/blog/2017/06/12/graphql-nosql-injection-through-json-types/•https://github.com/doyensec/graph-ql/•https://github.com/andev-software/graphql-ide•https://github.com/YuLeven/nodejs-graphql-mysql-example
References
[1]
Discovering GraphQL endpoints and SQLi vulnerabilities: https://medium.com/@localh0t/discovering-graphql-endpoints-and-sqli-vulnerabilities-5d39f26cea2e[2]
文档: https://graphql.github.io/learn/[3]
Introspection: https://graphql.org/learn/introspection/[4]
built-in introspection query: https://github.com/graphql/graphql-js/blob/master/src/utilities/introspectionQuery.js#L21[5]
项目: https://github.com/YuLeven/nodejs-graphql-mysql-example[6]
这里: https://gist.github.com/localh0t/240a8037922a0b168ea85fd8fef7bded[7]
graphql-ide: https://github.com/andev-software/graphql-ide[8]
GraphQL_Introspection.py: https://github.com/doyensec/graph-ql/[9]
scalar types : https://graphql.org/learn/schema/#scalar-types[10]
例子: https://blog.doyensec.com/2018/05/17/graphql-security-overview.html[11]
例子: https://labs.detectify.com/2018/03/14/graphql-abuse/[12]
例子: http://www.petecorey.com/blog/2017/06/12/graphql-nosql-injection-through-json-types/