利用 URN 绕过 URL 检查
0x00 前言
最近痴迷于看 RFC 及各类规范文档,从中发现一些有趣的利用。刚好前段时间发现了一处有趣的特性,成功绕过了某个知名站点的 XSS 防御,最终执行 XSS 攻击。本来以为只是一个小 trick,后来被某偶像拿来出了道 CTF 题目,觉得有必要分享一下。
0x01 一个真实 case 及其绕过
几个月前发现某网站上有类似于下面的逻辑,会从 URL 中取 next
参数的值,并解析出 pathname
部分,执行跳转。
const getParam = (key) => {
return new URL(location).searchParams.get(key)
}
const nextURL = getParam('next')
if (nextURL) {
const u = new URL(nextURL)
location.href = "" + u.pathname
}
老司机应当可以发现,如果 u.pathname
能够以 javascript:
开头,那么就可以执行 XSS 攻击了。然而,pathname 会多带一个 ‘/’ ,导致利用失败,无法 XSS。
爱折腾的人怎么会止步于此呢,这个问题的突破点在于 new URL(M).pathname
。根据规范,如果cannot-be-a-base-URL
为 true
,那么 pathname
等价于 path[0]
。
刚好规范中就给出了满足这类条件的 case,如下图所示
因此,只要构造 ?next=urn:javascript:alert(location.origin)
即可绕过改限制并执行 XSS 攻击。
0x02 举一反三
经偶像指点,发现除了使用 URN 协议外,任意符合格式的 URI 都可以利用,如下所示。
new URL('a:javascript:alert(1)').pathname
0x03 总结
- 规范、RFC 中有许多非常有趣的特性,没准可以拿来做一些绕过
- 偶像🐂🍺