跨站点脚本 (XSS) 攻击是什么
跨站点脚本(Cross-Site Scripting,简称 XSS)攻击是一种注入攻击,其中恶意脚本被注入到受信任的网站中。攻击者使用 Web 应用程序向不同的最终用户发送恶意代码,通常以浏览器端脚本的形式。这些恶意脚本一旦被执行,可能导致各种安全问题,如数据泄露、会话劫持和网站篡改等。
防止跨站点脚本(XSS)攻击的方法
除了通用的输入验证外,以下方法可以有效防止 XSS 攻击:
1. 过滤输入
在用户输入到达服务器时,过滤掉危险字符,如:< , > , & , ’ , " , ’ , " , ( , ) , ; , + , CR(回车,ASCII 0x0d),LF(换行,ASCII 0x0a)。
2. 对输出数据进行编码
在将用户可控数据输出到 HTTP 响应时,进行适当的编码,防止其被解释为可执行内容。根据输出的上下文,可能需要应用 HTML、URL、JavaScript 和 CSS 等编码。
3. 使用适当的响应头
在 HTTP 响应中使用适当的 Content-Type 和 X-Content-Type-Options 标头,确保浏览器以安全的方式解释响应,防止非预期的 HTML 或 JavaScript 被包含在响应中。
代码示例
Java 代码示例:使用 OWASP Java Encoder 进行 HTML 标记消毒
OWASP Java Encoder 是一个简单易用的高性能编码器类,没有依赖关系,能够帮助 Java Web 开发者防御 XSS 攻击。
基本 HTML 上下文
<body><b><%= Encode.forHtml(UNTRUSTED) %></b>
</body>
HTML 内容上下文
<textarea name="text"><b><%= Encode.forHtmlContent(UNTRUSTED) %></b>
</textarea>
HTML 属性上下文
<input type="text" name="address" value="<%= Encode.forHtmlAttribute(UNTRUSTED) %>" />
URL 参数值编码
<a href="/search?value=<%= Encode.forUriComponent(UNTRUSTED) %>&order=1#top">
<a href="/page/<%= Encode.forUriComponent(UNTRUSTED) %>">
JavaScript 块上下文
<script type="text/javascript">var msg = "<%= Encode.forJavaScriptBlock(UNTRUSTED) %>";alert(msg);
</script>
JavaScript 变量上下文
<button onclick="alert('<%= Encode.forJavaScriptAttribute(UNTRUSTED) %>');">click me
</button>
CSS 上下文
<div style="width:<%= Encode.forCssString(UNTRUSTED) %>">
<div style="background:<%= Encode.forCssUrl(UNTRUSTED) %>">
JavaScript 代码示例:使用 DOMPurify 进行 HTML 标记消毒
DOMPurify 是一个用于 HTML、MathML 和 SVG 的高效 XSS 消毒器。它用 JavaScript 编写,可以在所有现代浏览器中运行。
包含 DOMPurify
使用未简化的开发版本:
<script type="text/javascript" src="src/purify.js"></script>
使用缩小和测试的产品版本:
<script type="text/javascript" src="dist/purify.min.js"></script>
清理字符串
let clean = DOMPurify.sanitize(dirty);
配置仅允许 HTML
let clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {html: true}});
异步加载
import DOMPurify from 'dompurify';var clean = DOMPurify.sanitize(dirty);
服务器端使用 Node.js
npm install dompurifyconst createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);const clean = DOMPurify.sanitize(dirty);
C# 代码示例:HTML 编码
使用 System.Text.Encodings.Web 命名空间中的默认编码器。
@using System.Text.Encodings.Web;
<h1>@HtmlEncoder.Default.Encode(age.StudentName)</h1>
如果需要,还可以使用其他编码器类,如 JavaScript 和 URL 编码器。
@JavaScriptEncoder.Default.Encode
@UrlEncoder.Default.Encode
通过依赖注入 (DI) 使用可配置的编码器:
public class HomeController : Controller
{HtmlEncoder _htmlEncoder;JavaScriptEncoder _javaScriptEncoder;UrlEncoder _urlEncoder;public HomeController(HtmlEncoder htmlEncoder,JavaScriptEncoder javascriptEncoder,UrlEncoder urlEncoder){_htmlEncoder = htmlEncoder;_javaScriptEncoder = javascriptEncoder;_urlEncoder = urlEncoder;}
}
参考链接
- OWASP Java Encoder:OWASP Java Encoder
- DOMPurify:DOMPurify GitHub
- System.Text.Encodings.Web:System.Text.Encodings.Web Documentation