跨站脚本攻击预防 xss-prevention

这个技能专注于防止跨站脚本攻击,通过输入净化、输出编码、内容安全策略等方法,保护Web应用免受XSS攻击。适用于用户生成内容、富文本编辑器、网络安全场景。关键词包括XSS、网络安全、输入验证、输出编码、DOMPurify、CSP、跨站脚本、Web安全。

漏洞挖掘 0 次安装 0 次浏览 更新于 3/7/2026

名称: xss-预防 描述: 通过输入净化、输出编码、内容安全策略等方法预防跨站脚本攻击。适用于用户生成内容、富文本编辑器、Web应用安全,或遇到存储型XSS、反射型XSS、DOM操作、脚本注入错误时使用。

关键词: 净化, HTML编码, DOMPurify, CSP, 内容安全策略, 富文本编辑器, 用户输入, 转义, innerHTML, DOM操作, 存储型XSS, 反射型XSS, 输入验证, 输出编码, 可信类型, XSS攻击, 网络安全, 用户生成内容, 安全编码, 脚本注入, 基于DOM的XSS 许可证: MIT

XSS预防

概述

通过输入净化、输出编码、内容安全策略头和安全编码实践,实现全面的跨站脚本攻击预防。

使用时机

  • 用户生成内容展示
  • 富文本编辑器
  • 评论系统
  • 搜索功能
  • 动态HTML生成
  • 模板渲染场景

XSS攻击类型

类型 向量 防御
反射型 URL参数 输出编码
存储型 数据库内容 输入净化
基于DOM型 客户端JS 安全DOM API
突变型 HTML解析器特性 严格净化

输出编码 (Node.js)

function encodeHTML(str) {
  return str
    .replace(/&/g, '&')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;');
}

function encodeForAttribute(str) {
  return str.replace(/[^\w.-]/g, char =>
    `&#x${char.charCodeAt(0).toString(16)};`
  );
}

// 在模板中使用
app.get('/profile', (req, res) => {
  const username = encodeHTML(req.query.name);
  res.send(`<h1>欢迎, ${username}</h1>`);
});

DOMPurify净化

import DOMPurify from 'dompurify';

const config = {
  ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
  ALLOWED_ATTR: ['href', 'title'],
  ALLOW_DATA_ATTR: false
};

function sanitizeHTML(dirty) {
  return DOMPurify.sanitize(dirty, config);
}

// React组件
function RichContent({ html }) {
  return (
    <div dangerouslySetInnerHTML={{ __html: sanitizeHTML(html) }} />
  );
}

内容安全策略

// Express中间件
app.use((req, res, next) => {
  const nonce = crypto.randomBytes(16).toString('base64');
  res.locals.nonce = nonce;

  res.setHeader('Content-Security-Policy', [
    "default-src 'self'",
    `script-src 'self' 'nonce-${nonce}'`,
    "style-src 'self' 'unsafe-inline'",
    "img-src 'self' data: https:",
    "connect-src 'self' https://api.example.com",
    "frame-ancestors 'none'",
    "base-uri 'self'",
    "form-action 'self'"
  ].join('; '));

  next();
});

安全DOM API

// 危险 - 避免使用
element.innerHTML = userInput;        // XSS风险
element.outerHTML = userInput;        // XSS风险
document.write(userInput);            // XSS风险
eval(userInput);                      // 代码注入

// 安全 - 使用这些替代
element.textContent = userInput;      // 自动转义
element.setAttribute('data-id', id);  // 属性安全
document.createTextNode(userInput);   // 创建安全文本节点

URL验证

function isSafeURL(url) {
  try {
    const parsed = new URL(url);
    return ['http:', 'https:'].includes(parsed.protocol);
  } catch {
    return false;
  }
}

// 用法
const href = isSafeURL(userURL) ? userURL : '#';

上下文特定编码

不同上下文需要不同的编码方法:

  • HTML实体编码:用于文本内容的最安全选项
  • 属性编码:用于HTML属性
  • JavaScript转义:用于脚本上下文
  • URL编码:用于URL参数
  • CSS转义:用于样式表上下文

始终根据数据将渲染的特定上下文对输出进行编码。

其他实现

参见 references/python-sanitization.md 获取:

  • Python bleach库用法
  • Flask/Django模板转义
  • 服务器端验证模式

参见 references/nodejs-advanced.md 获取:

  • 包含所有方法的完整XSSPrevention类
  • Express中间件 (xssProtection)
  • React组件 (SafeText, SafeHTML, SafeLink, useSanitizedInput)
  • Helmet CSP配置

最佳实践

✅ 推荐做法:

  • 默认编码输出
  • 使用带自动转义的模板引擎
  • 实施CSP头
  • 使用允许列表净化富内容
  • 用协议白名单验证URL
  • 使用HTTPOnly Cookie
  • 进行定期安全测试
  • 利用安全框架

❌ 不建议做法:

  • 信任用户输入
  • 使用不安全函数 (eval, innerHTML)
  • 为便利性禁用安全功能
  • 仅依赖客户端验证
  • 使用阻止列表代替允许列表
  • 跳过上下文特定编码
  • 允许任意脚本执行

安全检查清单

  • [ ] 根据上下文编码所有输出 (HTML, 属性, JS)
  • [ ] 使用允许列表净化HTML (非阻止列表)
  • [ ] 实施严格的CSP头
  • [ ] 使用HTTPOnly Cookie进行会话
  • [ ] 验证和净化URL
  • [ ] 避免使用带用户内容的innerHTML
  • [ ] 定期安全测试

资源