写在前面的话
随着GraphQL技术的日益普及,我们总结了一些关于常见安全错误的文档和提示。
什么是GraphQL?
GraphQL是由Facebook开发并于2015年公开发布的数据查询语言。它是REST API的替代品。
即使你没有看到任何GraphQL在那里,很可能你已经在使用它,因为它是在一些大的科技巨头,Facebook, GitHub, Pinterest, Twitter, HackerOne更多。
这项技术的几个关键点
1.GraphQL提供了API中数据的完整和可理解的描述,并使客户能够精确地询问他们需要什么。返回可预测的结果。
2.典型的RESTAPI需要从多个URL进行加载,但GraphQLAPI可以在单个请求中获取应用程序所需的所有数据。
3.GraphQL api是按照类型和字段而不是端点来组织的,您可以从单个端点访问所有数据的全部功能。
4.GraphQL是强类型的,以确保应用程序只询问可能的情况并提供明确而有用的错误。
5.新的字段和类型可以添加到GraphQL API,而不会影响现有的查询。老化的字段可以被弃用,并且隐藏在工具中。
在开始深入研究GraphQL安全领域之前,下面简要回顾它的工作原理。该官方文档写得很好,是真正有用的。
一个GraphQL查询如下所示:
基本的GraphQL查询
query{
user{
id
email
firstName
lastName
}
}
尽管响应是JSON:
基本的GraphQL响应
{
"data": {
"user": {
"id": "1",
"email": "paolo@doyensec.com",
"firstName": "Paolo",
"lastName": "Stagno"
}
}
}
安全测试技巧
由于Burp Suite不太了解GraphQL语法,因此我建议使用graphql-ide,这是一个基于Electron的应用程序,允许您编辑和发送请求至GraphQL端点; 我还编写了一个小python脚本GraphQL_Introspection.py,它列举了一个GraphQL端点(带有内省),以便提取文档。该脚本对于检查GraphQL模式寻找信息泄露,隐藏数据和不可访问的字段非常有用。
该工具将生成类似于以下内容的HTML报告:
内省是用来要求一个GraphQL模式来获取关于它所支持的查询、类型等信息的信息。
作为一个渗透测试人员,我建议你去寻找发给“/ graphql”
或“/graphql.php”
的请求,因为这些是通常的GraphQL端点名称; 您还应搜索“/ graphiql”
,“graphql / console /”
,联机GraphQL IDE与后端交互,以及“/graphql.php?debug=1”
(带有附加错误报告的调试模式),因为它们可能会被留下由开发人员开放。
在测试应用程序时,验证是否可以在没有通常授权令牌标头的情况下发出请求:
由于GraphQL框架没有提供任何保护数据的手段,因此开发人员因按照文档中的说明实施访问控制:
“但是,对于生产代码库,将授权逻辑委托给业务逻辑层”。
任何事情都可能会出错,因此没有正确认证和或授权的用户是否可以从服务器请求整个底层数据库非常重要。
当使用GraphQL构建应用程序时,开发人员必须将数据映射到他们选择的数据库技术中的查询。这是易于引入安全漏洞的原因,导致 破坏访问控制,不安全的直接对象引用甚至SQL / NoSQL注入。
作为破坏实现的一个示例,以下请求 / 响应表明我们可以为平台的任何用户(通过ID参数循环访存)获取数据,同时转储密码哈希值:
询问
query{
user(id: 165274){
id
email
firstName
lastName
password
}
}
响应
{
"data": {
"user": {
"id": "165274",
"email": "johndoe@mail.com",
"firstName": "John",
"lastName": "Doe"
"password": "5F4DCC3B5AA765D61D8327DEB882CF99"
}
}
}
您需要检查的另一件事与尝试执行非法查询时的信息泄露有关:
信息披露
{
"errors": [
{
"message": "Invalid ID.",
"locations": [
{
"line": 2,
"column": 12
}
"Stack": "Error: invalid ID\n at (/var/www/examples/04-bank/graphql.php)\n"
]
}
]
}
虽然GraphQL是强类型的,但SQL / NoSQL注入仍然是可能的,因为GraphQL只是客户端应用程序和数据库之间的一个层。问题可能存在于为了查询数据库而从GraphQL查询中获取变量的层中,未正确清理的变量导致旧的简单SQL注入。在Mongodb的情况下,NoSQL注入可能并不那么简单,因为我们不能”juggle”类型(例如将字符串转换为数组,请参阅PHP MongoDB注入)。
GraphQL SQL注入
mutation search($filters Filters!){
authors(filter: $filters)
viewer{
id
email
firstName
lastName
}
}
{
"filters":{
"username":"paolo' or 1=1--"
"minstories":0
}
}
谨防嵌套查询!它们可以允许恶意客户端通过过度复杂的查询来执行DoS(拒绝服务)攻击,这些查询会占用服务器的所有资源:
嵌套查询
query {
stories{
title
body
comments{
comment
author{
comments{
author{
comments{
comment
author{
comments{
comment
author{
comments{
comment
author{
name
}
}
}
}
}
}
}
}
}
}
}
}
可能设置超时,最大深度或查询复杂度阈值来针对DoS进行简单补救
请记住,在PHP GraphQL实现中:
复杂性分析默认是禁用的
限制查询深度默认情况下处于禁用状态
自省是默认启用的。这意味着任何人都可以通过发送包含元字段类型和模式的特殊查询来完整描述您的模式
结尾
GraphQL是一项新的有趣的技术,可用于构建安全的应用程序。由于开发人员负责实施访问控制,因此应用程序很容易出现经典的Web应用程序漏洞,如Broken Access Controls,不安全的直接对象引用,跨站点脚本(XSS)和经典注入漏洞。就像任何技术一样,基于GraphQL的应用程序可能会像这个实际例子那样容易出现开发实现错误:
“通过使用脚本,整个国家(我用美国,英国和加拿大测试过的)可能的号码组合都可以通过这些URL运行,并且如果一个号码与Facebook帐户相关联,则它可以与名称和更多细节(图像等)。“
参考:
https://en.wikipedia.org/wiki/GraphQL
https://dev-blog.apollodata.com/the-concepts-of-graphql-bc68bd819be3
https://graphql.org/learn/
https://www.howtographql.com/
https://www.hackerone.com/blog/the-30-thousand-dollar-gem-part-1
https://hackerone.com/reports/291531
https://labs.detectify.com/2018/03/14/graphql-abuse/
https://medium.com/the-graphqlhub/graphql-and-authentication-b73aed34bbeb
http://www.petecorey.com/blog/2017/06/12/graphql-nosql-injection-through-json-types/
https://webonyx.github.io/graphql-php/
本文翻译:https://blog.doyensec.com/2018/05/17/graphql-security-overview.html