输出编码
输出编码是将输入字符串中可能使其危险的字符进行转义的过程,因此它们被视为文本而不是 HTML 等语言的一部分。
当您希望将输入视为文本时,这是一个合适的选择,例如,因为您的网站使用将输入插入内容的模板,如以下 Django 模板摘录
django
You searched for {{ search_term }}.
大多数现代模板引擎都会自动执行输出编码。例如,Django 的模板引擎执行以下转换
< 转换为 <
> 转换为 >
' 转换为 '
" 转换为 "
& 转换为 &
这意味着如果您将 传递到上面的 Django 模板中,它将转换为 <img src=x onerror=alert('XSS!')>,并显示为以下文本
您搜索了 。
类似地,如果您使用 React 进行客户端渲染,嵌入在 JSX 中的值会自动编码。例如,考虑以下 JSX 组件
jsximport React from "react";
export function App(props) {
return
}
如果我们将 传递给 props.name,它将渲染为
你好,!
防止 XSS 攻击最重要的部分之一是使用性能良好且执行可靠输出编码的模板引擎,并阅读其文档以了解其提供的保护的任何注意事项。
文档上下文
即使您使用自动编码 HTML 的模板引擎,您也需要了解在文档的哪个位置包含不受信任的内容。例如,假设您有一个 Django 模板如下
django
在此上下文中,输入位于
但是,假设模板如下
django
在此上下文中,浏览器会将 my_input 变量视为 HTML 属性。由于 Django 对引号进行编码(" → ",' → '),因此有效载荷 onmouseover="alert('XSS')" 将不会执行。然而,像 onmouseover=alert(1)(或使用反引号 onmouseover=alert(`XSS`))这样的未加引号的有效载荷仍然会执行,因为属性值不需要加引号,并且反引号默认不被转义。
浏览器使用不同的规则来处理网页的不同部分——HTML 元素及其内容、HTML 属性、内联样式、内联脚本。需要进行的编码类型取决于插入输入的上下文。
在一个上下文中安全的内容在另一个上下文中可能不安全,因此有必要理解您包含不受信任内容的上下文,并实现此上下文所需的任何特殊处理。
HTML 上下文:插入到大多数 HTML 元素标签之间(除了