安全测试-05-文件上传、XSS 与 CSRF 这些高频漏洞怎么测
安全测试里有一类问题很典型:
- 这些问题本身都不陌生
- 资料也很多
- 但一到真实项目里,还是会反复出现
最典型的就是这三类:
- 文件上传
- XSS
- CSRF
它们之所以值得长期固定检查,不是因为概念经典,而是因为它们非常贴近日常业务功能:
- 头像上传
- 附件上传
- 富文本内容
- 搜索框、备注、评论
- 后台配置页面
- 审批、删除、修改资料这类表单动作
这篇文章不打算讲漏洞定义百科,而是讲更实用的问题:
在真实业务测试里,这三类问题到底怎么测,怎么判断问题是否真的成立。
一、先说结论:这三类问题最怕“只测表面”
这三类问题在现场都很容易被测偏。
常见误区是:
- 文件上传只看前端后缀限制
- XSS 只在输入框里随手塞个
alert(1) - CSRF 只看有没有 token 字段
这些都不够。
真正要确认的是:
- 文件最终有没有按危险方式被保存和暴露
- 恶意脚本最终有没有进入真实渲染上下文并执行
- 关键动作最终能不能在用户不知情的情况下被跨站触发
所以这三类问题都不能只停留在“请求能发出去”,而要看到最终影响。
二、文件上传最值得优先看的,不是“能传文件”,而是“系统最终怎么处理文件”
文件上传问题最容易被低估,因为功能视角往往只看:
- 能不能上传成功
- 页面能不能看到附件
安全视角还要继续往下问:
- 服务端按什么规则识别文件类型
- 文件名、扩展名、路径有没有被可信处理
- 上传后的文件最终放到哪里
- 访问下载时是按静态资源直接暴露,还是经过安全处理
1. 最值得优先测的几个点
- 只校验前端后缀,后端不校验
- 只看
Content-Type,不看实际文件内容 - 文件名可控,路径拼接不严谨
- 上传目录可直接访问
- 富文本或附件允许上传带脚本的可执行内容
2. 一套最小执行骨架
通常至少会做这几组动作:
- 改后缀
- 改
Content-Type - 改文件名
- 上传包含脚本或危险内容的文件
- 上传成功后直接访问文件 URL
例如会重点试这些组合:
test.jpg.phpshell.jsp.png- SVG 中带脚本
- HTML 文件伪装成图片
3. 重点不只是看“传进去了”,还要看“后面怎么被访问”
这一步很关键。
有些系统虽然把危险文件传进去了,但最终:
- 下载时强制附件方式返回
- 不在公网目录暴露
- 做了文件重命名和隔离
这时风险和“直接可执行、可访问”完全不是一个量级。
所以文件上传测试最终要回答的是:
- 能不能绕过校验
- 绕过之后能不能形成实际可利用路径
三、XSS 最怕只测输入,不看最终渲染上下文
对 XSS 的测试停留在:
- 输入
<script>alert(1)</script> - 页面没弹框
- 于是判断没问题
这太粗了。
真正要看的问题是:
- 输入内容最终落到了哪里
- 是进入 HTML、属性、脚本还是 URL 上下文
- 页面渲染前有没有正确转义
- 富文本场景有没有做白名单过滤
1. 哪些位置最值得优先看
通常优先看这些地方:
- 评论、备注、简介、公告
- 富文本编辑器
- 搜索框回显
- 用户昵称、头像说明、工单内容
- 后台运营配置项
- 报表标题、导出名称、消息模板
因为这些位置经常满足两个条件:
- 输入来源是用户可控的
- 输出位置是其它用户会看到的
2. 一套更实用的测试顺序
第一步:先确认输入能否原样保存
例如输入:
1 | <img src=x onerror=alert(1)> |
先看保存后再打开详情页、列表页、管理页时,这段内容是否被原样带出来。
第二步:再确认它落在什么上下文
同样一段内容,落在不同上下文风险完全不同:
- 普通文本节点
- HTML 属性
- JavaScript 字符串
- URL 参数
这一步决定了后面 payload 应该怎么调整。
第三步:最后再判断是否真的执行
不要只在输入瞬间看结果。
要同时看:
- 详情页
- 列表页
- 审核页
- 后台管理页
- 导出预览页
很多 XSS 不是在用户自己提交时触发,而是在别人查看、审核、管理时触发。
四、CSRF 最怕只看 token 字段,不看关键动作是否真的可跨站触发
CSRF 在 里会被简单理解成:
- 看请求里有没有
_csrf - 如果有,就算安全
这不严谨。
真正要问的是:
- 关键动作是不是完全依赖浏览器自动带上的身份
- 有没有额外防护机制
- 恶意页面能不能诱导浏览器替用户发出有效请求
1. 哪些动作最值得优先看
我优先看这些动作:
- 修改邮箱、手机号、密码
- 新增管理员、调整角色
- 审批通过、删除、封禁
- 收货地址修改、提现申请、退款确认
因为这些动作一旦被跨站触发,业务后果通常很直接。
2. 一套最小执行骨架
CSRF 的最小测试,通常可以按这几步来:
- 先确认目标动作是否依赖 Cookie 或浏览器自动身份
- 再看请求是否要求额外 token、验证码、二次确认
- 构造一个简单表单或请求页面
- 在受害者已登录状态下访问这个页面
- 看关键动作是否真实生效
如果动作真实生效,问题才算真正成立。
3. 重点不要只看“请求能发”,要看“动作是否落地”
有些接口跨站请求能发出去,但:
- 被 SameSite 拦住了
- 被 token 校验挡住了
- 被二次确认挡住了
这时风险要按真实结果判断,而不是按“理论能发请求”判断。
五、一套适合业务测试的统一检查表
如果要把这三类问题沉淀成稳定动作,建议至少固定下面这张检查表。
| 类型 | 优先场景 | 首测动作 | 关键确认点 |
|---|---|---|---|
| 文件上传 | 头像、附件、富文本、后台上传 | 改后缀、改类型、改文件名 | 是否可访问、可执行、可传播 |
| XSS | 评论、备注、富文本、后台配置 | 提交带脚本内容 | 是否进入渲染上下文并执行 |
| CSRF | 修改、审批、删除、授权 | 构造跨站请求 | 用户已登录情况下动作是否真实落地 |
这张表的价值是让测试不要只停留在“看到一个输入框就试一下”,而是先把高风险位置和验证目标对齐。
六、最容易踩的几个坑
1. 文件上传只看前端限制
前端限制通常价值很有限。
真正要看的是后端是否信了这些信息,以及文件最终如何落盘和暴露。
2. XSS 只在单一页面测一次
很多输入在提交页不执行,但会在:
- 列表页
- 审核页
- 管理后台
- 邮件通知预览
这些地方触发。
3. CSRF 只看有没有 token 字段
有 token 不等于安全。
还要看:
- token 是否真的校验
- 是否能被重用
- 是否只做了表面字段校验
4. 只看技术现象,不看业务影响
例如一个 XSS 只能影响用户自己的草稿页,风险和“能打到管理员审核页”的 XSS 完全不是一个级别。
七、真实案例:为什么一个“备注字段”最后打到了管理员后台
场景
一个工单系统里,提交工单时有个“问题备注”字段。
业务同学觉得这只是普通文本,风险不高。
功能测试时,这个字段表现正常:
- 能保存
- 能在工单详情页查看
- 管理员后台也能看到
执行
我在备注里填入了一段更偏事件型的内容:
1 | <img src=x onerror=alert('xss')> |
然后我按这几个位置逐个验证:
- 提交人自己的详情页
- 工单列表页
- 管理员后台审核页
现象
结果很有代表性:
- 提交人详情页里,这段内容被普通文本显示,没有执行
- 但管理员后台审核页里,备注内容被直接拼进了富文本区域
- 管理员打开该工单时,脚本真正执行了
也就是说,这不是一个“用户自己看自己页面”的低风险问题,而是一个能打到高权限审核后台的存储型 XSS。
排查
顺着前后端实现看,问题链路很清楚:
- 提交接口没有过滤危险标签
- 前台详情页做了 HTML 转义
- 但后台审核页为了保留格式,直接使用了未转义内容
本质上不是“系统没有任何防护”,而是:
- 不同页面对同一字段处理不一致
- 高权限页面恰好走了最危险的渲染方式
修复
最后给研发的修复建议不是简单一句“过滤 script”,而是分层做:
- 对富文本和普通文本字段分开处理
- 对后台审核页统一做安全渲染或白名单清洗
- 建立一组固定 payload 回归用例
- 把“普通用户输入 -> 管理员查看”的链路列为长期回归项
这个案例很典型地说明:
XSS 的关键从来不只是“用户能不能输入”,而是“高权限用户最终怎么渲染这段内容”。
八、怎么把这类问题持续沉淀下来
更合适的做法是把这三类检查做成固定的专项清单。
第一层:手工检查清单
每个高风险模块固定检查:
- 上传文件后最终如何访问
- 富文本、备注、评论是否在多页面回显
- 关键表单动作是否依赖浏览器自动身份
- 高权限页面是否会渲染低权限用户输入
第二层:自动化或半自动化验证
适合沉淀成脚本或固定数据集的包括:
- 文件上传测试样本集
- 一组固定 XSS payload
- 关键修改/审批动作的 CSRF 复现页面
这样后续系统改版、编辑器替换、上传链路调整时,问题不会完全靠人工再发现一遍。
九、写在最后
文件上传、XSS、CSRF 这些问题之所以一直值得测,不是因为老,而是因为它们总是躲在最普通的业务功能里。
真正有效的做法,不是背很多 payload,而是把三个问题都落到真实影响上看:
- 文件最终怎么存、怎么访问
- 输入最终在哪里、以什么方式被渲染
- 动作最终能不能在用户不知情的情况下被跨站触发
只要把这三件事看清楚,很多表面上“看起来没什么”的问题,风险级别就会一下子变得很明确。