识别标记特有的 XSS 攻击向量,并部署 HTML 的原生防御手段:sandbox、noopener 和内容安全策略(CSP)。
在 Kodokon 中打开本课转义的上下文决定了一切:一个在文本节点中无害的值,在属性中却会变得可执行。未加引号的属性是最糟糕的情况:注入数据中的一个空格就足以创建一个新属性,例如一个 onmouseover 处理器。即便正确地加了引号,一个值在敏感的汇聚点(sinks)中仍然危险:href 和 src 接受 javascript: 协议,formaction 会劫持表单的提交,而 srcdoc 在其实体被解码后会把它们当作 HTML 来解释。
<!-- userName = x onmouseover=alert(1) -->
<img src="avatar.png" alt=x onmouseover=alert(1)>
<!-- The unquoted attribute lets a handler in -->一个 iframe 的 sandbox 属性会剥夺所有权限,然后你再逐个把它们授予回来:allow-scripts、allow-forms、allow-popups……如果没有 allow-same-origin,被嵌入的文档会获得一个不透明来源(opaque origin):没有 cookie、没有存储、无法访问父页面的 DOM —— 即便它是从你自己的域名提供的。
<iframe
src="https://widget.example.com"
sandbox="allow-scripts allow-forms"
referrerpolicy="no-referrer">
</iframe>一个 target=_blank 链接在历史上会给被打开的页面一个指向你标签页的 window.opener 引用:它可以把你的页面重定向到一个钓鱼克隆站,这种攻击被称为标签劫持(tabnabbing)。现代浏览器如今会在 target=_blank 上隐式地应用 noopener,但明确写出它对于 JavaScript 中的 window.open 以及表明意图仍然至关重要;再加上 noreferrer 还能同时抑制 Referer 头。
<a href="https://external.example"
target="_blank"
rel="noopener noreferrer">
View the external resource
</a>内容安全策略(Content Security Policy)会限制可执行代码的来源,并中和大多数 XSS,即便注入已经成功。通过 <meta http-equiv> 标签声明时,它仍有盲点:frame-ancestors、report-uri 和 sandbox 指令在那里会被忽略,需要 HTTP 头。相比于域名白名单,更应优先使用每次响应都重新生成的 nonce,何况 strict-dynamic 指令本就使白名单变得过时。
<meta http-equiv="Content-Security-Policy"
content="default-src 'self';
script-src 'self' 'nonce-r4nd0m'">allow-scripts 和 allow-same-origin 会使 sandbox 作废?rel=noopener 防范的是哪种攻击?window.opener 把你的标签页重定向到一个钓鱼站点<meta http-equiv> 声明时,哪个指令会被忽略?