JavaScript安全防护实战指南:从XSS到加密API

1. XSS攻击与防御

概念解析

XSS(跨站脚本攻击)是攻击者向网页注入恶意脚本的攻击方式,主要分为三类:

  • 存储型XSS:恶意脚本永久存储在服务器(如评论区)
  • 反射型XSS:恶意脚本来自当前HTTP请求(如钓鱼链接)
  • DOM型XSS:客户端脚本不安全地操作DOM
// 典型XSS示例
const userInput = "<script>alert('XSS')</script>";
document.getElementById("output").innerHTML = userInput;

防御方案

  1. 输入过滤

    function escapeHtml(unsafe) {
      return unsafe
     .replace(/&/g, "&amp;")
     .replace(/</g, "&lt;")
     .replace(/>/g, "&gt;")
     .replace(/"/g, "&quot;")
     .replace(/'/g, "&#039;");
    }
  2. 输出编码
  3. 文本内容:textContent代替innerHTML
  4. HTML属性:setAttribute代替字符串拼接
  5. URL参数:encodeURIComponent

实践建议

  • 使用DOMPurify库净化HTML
  • 在React中使用dangerouslySetInnerHTML时要特别小心
  • 在Vue中使用v-html指令时确保内容可信

2. CSRF防护

SameSite Cookie属性

图1

SameSite三种模式:

  • Strict:完全禁止第三方Cookie
  • Lax:允许安全方法(GET)的顶级导航
  • None:允许所有(需配合Secure)

CSRF Token机制

// 服务端生成并存储Token
const csrfToken = crypto.randomBytes(32).toString('hex');
sessionStorage.setItem('csrfToken', csrfToken);

// 客户端发送请求时携带
fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': csrfToken
  }
});

实践建议

  • 关键操作使用POST/PUT/DELETE方法
  • 重要Cookie设置HttpOnly+SameSite
  • 敏感操作增加二次验证

3. CSP内容安全策略

基础配置示例

Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'unsafe-inline' cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src * data:;
  connect-src https://api.example.com;
  frame-ancestors 'none';
  form-action 'self';

关键指令说明

指令作用推荐值
script-src控制JS加载源'self' 非必要不用'unsafe-inline'
style-src控制CSS加载源'self' 'unsafe-inline'
connect-src限制AJAX请求源明确API域名
report-uri违规报告地址生产环境建议配置

实践建议

  1. 逐步实施CSP:先使用Content-Security-Policy-Report-Only
  2. 使用nonce或hash替代'unsafe-inline'
  3. 禁止内联事件处理程序(如onclick)

4. 沙箱机制(Sandbox)

iframe沙箱实现

<iframe 
  sandbox="allow-scripts allow-same-origin"
  src="untrusted.html"
></iframe>

可用权限:

  • allow-forms:允许表单提交
  • allow-popups:允许弹出窗口
  • allow-scripts:允许执行脚本
  • allow-same-origin:保留同源策略

Web Worker沙箱

// 主线程
const worker = new Worker('untrusted.js');

// untrusted.js
self.onmessage = (e) => {
  // 受限环境,无法访问DOM
  const result = heavyCalculation(e.data);
  postMessage(result);
};

实践建议

  • 第三方组件使用Shadow DOM隔离
  • 插件系统采用Worker沙箱
  • 动态代码使用new Function()而非eval

5. 加密API(Web Crypto)

常见操作示例

生成密钥对

const keyPair = await crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 2048,
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    hash: "SHA-256"
  },
  true,
  ["encrypt", "decrypt"]
);

数据加密

const encrypted = await crypto.subtle.encrypt(
  {
    name: "RSA-OAEP"
  },
  publicKey,
  new TextEncoder().encode("敏感数据")
);

哈希计算

const hashBuffer = await crypto.subtle.digest(
  'SHA-256',
  new TextEncoder().encode('待哈希数据')
);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');

实践建议

  1. 前端加密不能替代HTTPS
  2. 密码存储使用PBKDF2等慢哈希算法
  3. 敏感操作使用时间安全比较

    // 安全比较
    function safeCompare(a, b) {
      const aBuf = new TextEncoder().encode(a);
      const bBuf = new TextEncoder().encode(b);
      if (aBuf.length !== bBuf.length) return false;
      
      let result = 0;
      for (let i = 0; i < aBuf.length; i++) {
     result |= aBuf[i] ^ bBuf[i];
      }
      return result === 0;
    }

综合防御策略

  1. 深度防御原则

    • 输入验证 + 输出编码 + 运行时防护
    • 前端防护 + 后端校验
  2. 安全头配置

    X-Content-Type-Options: nosniff
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    Referrer-Policy: strict-origin-when-cross-origin
  3. 监控与响应

    • CSP违规报告收集
    • 关键操作日志审计
    • 定期安全扫描

通过组合这些安全措施,可以构建多层次的JavaScript应用防护体系,有效抵御常见Web攻击。记住:安全不是一次性的工作,而是需要持续关注和改进的过程。

评论已关闭