学徒-访问私有GraphQL帖子
# 实验室:访问私有GraphQL帖子
# 题目
此实验室的博客页面包含一个隐藏的博客帖子,帖子中具有密码。若要解决实验室问题,请找到隐藏的博客文章并提交密码。
我们建议你在尝试此实验之前安装 InQL 扩展。InQL 可以更轻松地在 Repeater 中修改 GraphQL 查询,并使你能够扫描 API 模式信息。
有关使用 InQL 的更多信息,请参阅在 Burp Suite 中使用 GraphQL (opens new window)。
- name: 实验室-学徒
desc: 访问私有GraphQL帖子 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/graphql/lab-graphql-reading-private-posts
bgColor: '#001350'
textColor: '#39d50c'
2
3
4
5
6
# 实操
点击 “ACCESS THE LAB” 进入实验室。
一个博客站点。
启用 BurpSuite 代理并刷新网页,看看能否捕获到有关于 GraphQL 的查询请求。
在 HTTP 历史记录中看到一个眼熟的路径/graphql/v1
,其中包含了标准的 GraphQL 查询。
将数据包转发至 Repeater 功能模块,在响应中可以看到 4 篇博客文章的信息,文章 ID 分别为 1、2、4、5。
诶?那博客文章 3 去哪了?很明显,我们要找到这篇文章,就像题目中所说的那样。
如果你安装了 InQL 扩展,则会在 Repeater 窗口中看到一个新的选项卡 “GraphQL”,点击进入。
切换至 Repeater 的 “GraphQL” 选项卡,这是由 InQL 扩展提供的功能界面,可以很方便地查看或修改 GraphQL 查询。
query getBlogSummaries {
getAllBlogPosts {
image
title
summary
id
}
}
2
3
4
5
6
7
8
根据理论知识所学,我们在对象的后面添加一对括号()
,然后传递参数id: 1
,尝试获取 ID 为 1 的博客文章信息。
query getBlogSummaries {
getAllBlogPosts(id: 1) {
image
title
summary
id
}
}
2
3
4
5
6
7
8
响应返回了错误信息,没有找到参数 “id”。
我们右键数据包,选择 “Generate queries with InQL Scanner”,这将会把数据包转发至 InQL 扩展,并自动探测 GraphQL API 端点的内省,以获取 API 的模式信息。
切换至 “InQL” 选项卡,成功探测内省,并列出了目标站点的 API 模式信息。
从中可以看到两个查询对象,分别是getAllBlogPosts
和getBlogPost
。
getAllBlogPosts
是一次性查询所有博客文章的信息,其中没有定义 “id” 参数。
而对象getBlogPost
则是获取单篇博客文章的信息,其中定义了 “id” 参数,并通过运算符!
标记为必填字段。
那就好办了,回到 Repeater 功能模块,将原有的查询对象getAllBlogPosts
修改为getBlogPost
,并添加对应的参数id: 3
query getBlogSummaries {
getBlogPost(id: 3) {
image
title
summary
id
}
}
2
3
4
5
6
7
8
成功获得博客文章 3 的信息,但是其中并没有密码。
那是因为缺少对应的查询字段,在 InQL 扩展中,复制可用于该对象的所有字段,然后粘贴到 GraphQL 查询中。
query getBlogSummaries {
getBlogPost(id: 3) {
author
date # Timestamp scalar
id
image
isPrivate
paragraphs
postPassword
summary
title
}
}
2
3
4
5
6
7
8
9
10
11
12
13
发送带有全部字段的getBlogPost
对象查询请求,在响应中的postPassword
字段可以找到密码。
复制密码,点击实验室首页上方的 “Submit solution” 打开提交输入框,粘贴密码并点击 “确定”。
密码提交正确,实验完成。