vlambda博客
学习文章列表

发现GraphQL端点和SQL注入漏洞

  翻译文章,原文:Discovering GraphQL endpoints and SQLi vulnerabilities[1]



GraphQL


介绍

GraphQL 是一个开源的数据查询语言(DQL)和数据处理语言(DML).最初,GraphQL由Facebook于2012年左右开发并于2015年公开发布。其主要优点之一是为其他Web服务体系结构(如REST)提供了一种更高效,更强大的替代方案。

结构

需要指出的一件有趣的事是GraphQL并没有绑定到任何特定的数据库(或与此相关的存储引擎),而是由现有代码支持。这是什么意思呢?不同于REST APIs(客户端首先与程序员编写的任意代码进行交互,然后此代码到达数据库);客户端首先与GraphQL进行交互,后者又与任意代码进行交互,并最终结束与数据库的对话。描述这种情况的更有用的图是:


发现GraphQL端点和SQL注入漏洞

Image credits: http://bearcatjs.org/graphql-versus-rest-api/.


架构的这种变化具有很多优势,例如,可以在单个请求中获得客户端所需的所有数据(而REST API需要执行多个请求)。

基础

对象类型和字段

{ films { id, name, genre, rating }}

在这个例子中,我们要求提供与films对象相关的idnamegenrerating字段。我们可以得到的标准答案是:

{ "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),并询问namegenre字段:

{ "data": { "film": { "name": "The Shawshank Redemption", "genre": "drama" } }}

GraphQL还有很多功能(别名,片段,变量等)。我显然不会描述所有这些内容;该文档[2]详细介绍了所有内容,并且非常易于阅读。

GraphQL 端点

如果刚开始审核的网络服务器似乎没有GraphQL端点,不要泄气。常见的GraphQL端点路径可以是(以及其他):

/graphql//graphql/console//graphql.php/graphiql//graphiql.php[...]

另外,请记住GraphQL端点可以像这样描述:


发现GraphQL端点和SQL注入漏洞

GraphiQL endpoint (fully interactive).


或是像这样的简单描述:


发现GraphQL端点和SQL注入漏洞

A not-so descriptive GraphQL endpoint.


一个好的方法确认是否为GraphQL,我们可以给一个我们认为的GraphQl端点发送一个无效的查询,例如:


发现GraphQL端点和SQL注入漏洞

Take a look at the query parameter, we are forcing the endpoint to produce a syntax error.


如果在发出上述请求后,我们得到类似·"Syntax Error: Expected Name, found }”的信息,那么我们可以安全地确认我们正在处理GraphQL端点。

要考虑的另一件重要事情是,其中一些仅允许某些HTTP请求(GET / POST /等),因此请尝试首先使用不同的方法:


发现GraphQL端点和SQL注入漏洞

POST method not allowed.



发现GraphQL端点和SQL注入漏洞

GET method allowed.


检查

我们发现了一个GraphQL端点,并且可以与其进行交互。非常棒!之后怎么办?我们的下一步将是查询模式,以便知道如何与之对话。GraphQL通过使用其 Introspection[3] 来允许此操作。有了它,我们可以获得有关服务器可用查询,类型,字段,突变等的信息。

如果要获取所有可用信息,可以使用GraphQL-JS中的 built-in introspection query[4]。如果我们有一个完全交互式的GraphiQL端点(在此示例中,我使用的是该 项目[5] 的修改版),我们可以简单地转到<Docs节,构造有效查询所需要的一切都在这里:


发现GraphQL端点和SQL注入漏洞

Documentation explorer in GraphiQL (Schema).



发现GraphQL端点和SQL注入漏洞

Documentation explorer in GraphiQL (RootQueryType).


现在我们知道可以要求一个特定的bacon对象(以id作为参数),也可以要求不同的bacon对象(以typeprice为参数)。一些例子:


发现GraphQL端点和SQL注入漏洞

Showing all bacons (notice that no arguments are specified).



发现GraphQL端点和SQL注入漏洞

Filtering bacons by its price.



发现GraphQL端点和SQL注入漏洞

Getting a bacon by its id.


如果;但是,我们没有交互式端点,我们还有其他几种选择来获取模式:

手动发出内省查询,并通过读取响应找出所有内容(痛苦,我知道)。如果您想走这条路, 这里[6] 是完整的URL-encoded payload。用 graphql-ide[7] (它将自动获取所有内容)用 GraphQL_Introspection.py[8](Doyensec 写的非常优秀的Python脚本)

SQL注入

如前所述,GraphQL最终与程序员编写的任意代码进行交互。GraphQL本身无法阻止任何类型的攻击,因此,如果他们犯了错误(例如,未使用参数化查询),则该应用程序可能会受到SQL注入攻击。


发现GraphQL端点和SQL注入漏洞

SQL injection vulnerability in a GraphQL query.


请记住,应用程序可能不会引发错误,但仍然容易受到 blind,time-based甚至out-of-band SQL注入攻击。同样,不要愚蠢地认为 scalar types [9] 不会很容易受到攻击;在很多情况下,我们只需将其用双引号 "" 引起来并在其中注入:


发现GraphQL端点和SQL注入漏洞

SQLi in a scalar type (wrapped around double quotes).


剩下的就是历史了;我们可以保存HTTP请求并启动sqlmap或手动构造SQLi并在数据库中获取我们能够到达的所有内容:


Exploiting the SQLi (by hand).



Exploiting the SQLi (sqlmap).


其他漏洞

基于GraphQL的Web应用程序(和端点)可能容易受到许多其他类型的漏洞的攻击。从绕过访问控制到敏感的数据公开,NoSQL注入等等。如果您想阅读这些示例和实际案例,我强烈建议 例子[10],例子[11]例子[12]

参考

https://en.wikipedia.org/wiki/GraphQLhttps://graphql.org/learn/http://bearcatjs.org/graphql-versus-rest-api/https://blog.doyensec.com/2018/05/17/graphql-security-overview.htmlhttps://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-idehttps://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/