56. 什么是 XSS、CSRF?如何从 JS 层面避免? 副本.md
来源:https://my.feishu.cn/file/PVHIbu1xqoQlYwxDZx0cwnOgnZe
采集状态:已完成正文采集;原文件源码视图逐行采集,行号 1 至 109 连续,滚动到底。
## XSS 与 CSRF 防御 技术笔记
### 1. 核心概念 (Core Concept)
**跨站脚本攻击 (Cross-Site Scripting, XSS)** 和 **跨站请求伪造 (Cross-Site Request Forgery, CSRF)** 是两种常见的 Web 安全漏洞。XSS 旨在向用户浏览器注入恶意脚本,利用用户的身份(权限)执行恶意操作或窃取信息;CSRF 则旨在利用用户已有的会话(认证)信息,在用户不知情或未经授权的情况下,伪造用户的请求执行非法操作。
### 2. 为什么需要它? (The "Why")
* **保护用户数据与隐私:** XSS 可用于窃取用户的 Cookie、会话信息、敏感输入等,导致用户账号被盗或隐私泄露。CSRF 可能导致用户的敏感操作(如修改密码、转账、删除数据)在用户未知情下执行。
* **维护网站声誉与数据完整性:** 受 XSS 或 CSRF 攻击的网站可能被用于传播恶意内容、进行钓鱼攻击,损害网站信誉,甚至破坏服务器数据。
* **符合安全合规性要求:** 许多行业的安全标准和法规要求 Web 应用具备基本的安全防护能力,防止这些常见攻击。
### 3. API 与用法 (API & Usage)
**注意:** XSS 和 CSRF 的防御主要依赖于后端、HTTP 协议特性以及浏览器安全策略。从 JavaScript 层面更多是配合实现防御策略,或者加固某些环节。以下将侧重于从 JS 层面可以配合或实现的常见防御措施。
#### 3.1 XSS 防御 (从 JS 层面配合)
XSS 主要是由于把用户输入的内容不加过滤地作为 HTML/JavaScript 代码执行导致的。关键在于对不可信数据的处理。
* **输入过滤与输出转义 (Input Filtering & Output Escaping):** 这是最核心的防御,即便从 JS 层面输入数据,也要假设其不可信。
* **输入过滤:** 在接收用户输入时,对数据进行验证和清洗,比如限制输入长度、字符类型等,但纯粹的过滤很难彻底防止 XSS。
* **输出转义:** 在将不可信数据插入到 HTML 页面时,根据插入位置(HTML Body, HTML 属性, JavaScript 代码, URL 等)进行相应的转义。这是防止 XSS 的关键。从 JS 层面,即使使用 `innerHTML` 或其他 DOM manipulation 方法,也要确保传入的数据经过了适当的转义。现代前端框架(如 React, Vue, Angular)通常内置了自动转义机制,但在手动操作 DOM 时需特别주의。
```javascript
// 错误示例:直接将用户输入插入到 DOM
// 假设 userInput = "";
document.getElementById('unsafeDiv').innerHTML = userInput; // 存在 XSS 风险
// 安全示例:使用 textContent 或进行转义(框架通常自动完成)
document.getElementById('safeDiv').textContent = userInput; // 作为纯文本插入
// 如果必须插入 HTML,使用成熟的第三方库进行清洗和过滤
// 示例 (使用 DOMPurify 库 - 需要引入):
// import DOMPurify from 'dompurify';
// const cleanHTML = DOMPurify.sanitize(userInput);
// document.getElementById('safeHTMLDiv').innerHTML = cleanHTML;
```
* **设置 HttpOnly 属性的 Cookie:** 带有 `HttpOnly` 标志的 Cookie 不能通过 JavaScript 的 `document.cookie` 接口访问。这可以防止 XSS 攻击者窃取用户的会话 Cookie,但不能阻止所有类型的 XSS 攻击。
* **内容安全策略 (Content Security Policy, CSP):** CSP 是一个 HTTP 响应头部,但也可以通过 `` 标签在 HTML 中定义。它允许开发者限制浏览器加载资源的来源(脚本、样式、图片等),以及限制行内脚本和 `eval()` 的使用,显著降低 XSS 风险。从 JS 层面可以配合 CSP,例如避免使用行内事件处理器 (`onclick="..."`) 和动态执行代码 (`eval()`)。
```html
```
#### 3.2 CSRF 防御 (从 JS 层面配合)
CSRF 的核心在于利用用户的会话凭证(通常是 Cookie)来伪造请求。防御的关键是让服务器能够验证请求是否来自用户合法的操作。
* **同源策略 (Same-Origin Policy):** 浏览器内置的安全机制,限制了来自不同源的脚本对 DOM 的访问和某些类型的请求。但 CSRF 攻击利用的不是脚本的跨域能力,而是浏览器发送请求时**自动带上同源 Cookie** 的特性。
* **使用 Anti-CSRF Token:** 这是最常用的 CSRF 防御手段。
* 服务器在渲染表单或页面时,生成一个唯一的、随用户会话变化的 Token,并将其嵌入到页面中(如隐藏字段或 JS 变量)。
* 用户提交请求时,前端(通常通过 JS)从页面中读取这个 Token,并作为请求数据的一部分(如请求体参数或自定义请求头)发送给服务器。
* 服务器接收请求后,验证携带的 Token 是否与服务器端存储的该用户会话对应的 Token 一致。如果一致,则认为是合法请求;否则,认为是伪造请求并拒绝。
```javascript
// 示例: 使用 Fetch API 发送带有 CSRF Token 的 POST 请求
// 假设在页面中有一个隐藏 input 或 JS 变量 csrfToken 存储了 Token
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); // 或从 JS 变量获取
fetch('/api/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken // 常见的自定义请求头
// 或者将 token 放到 request body 中
},
body: JSON.stringify({
data: 'some data'
// csrf_token: csrfToken // 另一种方式,放到 body
})
})
.then(response => {
// 处理响应
});
```
* **SameSite Cookie 属性:** 这是现代浏览器提供的一种重要的 CSRF 防御机制。它可以限制浏览器在进行跨站请求时是否发送 Cookie。
* `SameSite=Lax` (默认值): 跨站请求通常不携带 Cookie,但例外情况包括通过顶部导航(如 `` 或 `