安全测试-04-登录、会话与权限模型的安全验证方法
做安全测试时,会把注意力优先放在明显的漏洞名字上,比如:
- XSS
- SQL 注入
- 文件上传绕过
这些当然重要,但如果从业务系统的真实风险角度看,更常优先盯的是三件更基础的事:
- 登录链路稳不稳
- 会话状态管得严不严
- 权限模型是不是只停留在页面层
因为很多问题最后都不是“没做登录”,而是:
- 登录成功后身份边界没有守住
- 退出、改密、角色变更后旧会话还活着
- 页面按钮控住了,但服务端动作权限没有控住
这篇文章就聚焦这三条主线,讲一套更贴近业务测试的验证方法。
一、为什么这三件事最值得优先测
如果一个系统有下面这些特征,那登录、会话和权限模型就一定值得先看:
- 有多角色,比如普通用户、审核员、管理员
- 有审批、退款、封禁、授权这类高风险动作
- 有导出、下载、查看详情这类数据边界动作
- 有移动端、Web、后台多端共存
- 有单点登录、角色切换、组织架构同步
因为只要这些东西存在,你就很难绕开几个问题:
- 当前登录身份到底是如何建立的
- 登录后身份到底用什么维持
- 一个动作到底由谁说了算
- 身份变化后,旧权限是否还残留
二、登录安全最值得看的不是“能不能登录”,而是“怎么登录成功的”
很多测试把登录验证停留在:
- 正确账号密码能登录
- 错误密码不能登录
这远远不够。
更关注登录链路里的几个问题:
- 登录成功凭证是什么
- 凭证是否只在正确条件下发放
- 登录失败时是否有边界保护
- 登录态是否和设备、时间窗、风险动作有关联
1. 先明确系统用什么维持身份
常见做法包括:
- Session + Cookie
- Access Token + Refresh Token
- 单点登录票据
- 自定义签名 + 会话态
这一步必须先弄清楚。
因为如果连身份载体是什么都不清楚,后面的会话验证很容易测偏。
2. 再看登录失败有没有最基本边界
例如:
- 连续输错密码有没有限制
- 验证码是不是形同虚设
- 异常频率登录有没有风控
- 同一账号在异常时间窗里是否有保护
这类问题不一定都要做到风控级别,但至少不能完全裸奔。
3. 再看登录成功后有没有不合理放宽
例如:
- 登录后长期不失效
- 高风险操作不做二次校验
- 异地登录、设备切换没有任何提醒和限制
这类问题功能上常常“完全没错”,但安全上边界会很松。
三、会话管理最容易出问题的 5 个地方
很多系统问题不是出在登录,而是出在登录之后。
最常检查的会话问题有这 5 类。
1. 退出登录后旧会话是否真正失效
这个是最基本的。
验证方式通常很简单:
- 先正常登录并抓取一个关键请求
- 执行退出登录
- 用退出前的原请求直接重放
如果还能继续查数据、改数据、做动作,就说明会话失效机制有问题。
2. 修改密码后旧会话是否仍然可用
这个问题经常被漏掉。
因为很多系统只更新了密码,却没有同步失效所有旧 Session 或旧 Token。
结果就是:
- 密码虽然变了
- 但原设备、原浏览器、原脚本还能继续访问
3. 角色变化后旧权限是否还保留
例如:
- 管理员被降权为普通用户
- 审批人被从当前节点移除
- 用户部门变更导致数据权限收窄
这时如果旧 Token 还能继续拿着原权限操作,就是典型问题。
4. 多端登录、多设备登录的状态是否一致
例如:
- Web 登录后,App 旧会话是否继续有效
- 新设备登录后,旧设备是否应该下线
- 管理后台和业务前台是否共用同一会话体系
这类问题最怕的是系统行为不一致,导致某些端口会话异常宽松。
5. 敏感动作是否需要额外确认
例如:
- 修改手机号
- 重置密码
- 提现、退款
- 权限分配
登录态存在,不代表所有敏感动作都可以直接做。
很多系统需要补一层:
- 短信校验
- 二次密码
- 一次性确认 token
如果完全没有,风险通常会比较高。
四、权限模型最容易测偏的地方:把“按钮权限”当成“动作权限”
权限模型验证里,最常见的误区是:
- 普通用户看不到按钮
- 所以普通用户一定做不了
这完全不成立。
真正要验证的是:
- 当前用户有没有权查看某资源
- 当前用户有没有权修改某资源
- 当前用户有没有权执行某动作
- 这些判断是不是都在服务端重新做过
1. 先把权限拆成三层
通常可以按下面三层去看:
- 页面权限:能不能看到入口
- 数据权限:能不能看到这份数据
- 动作权限:能不能对这份数据执行操作
很多系统只做了第一层,第二层和第三层其实很空。
2. 再把角色和资源关系理清楚
至少要明确:
- 哪些角色能访问哪些模块
- 哪些角色能看哪些数据范围
- 哪些角色能做哪些动作
- 哪些动作还要叠加资源归属关系
例如“审批人可以审批”,这句话本身还不够。
还必须补一句:
只能审批当前分配给自己的任务。
3. 最后用实际账号做交叉验证
至少准备:
- 普通用户 A
- 普通用户 B
- 审核员或主管 C
- 管理员 D
然后验证:
- A 能不能看 B 的数据
- A 能不能做 C 的动作
- C 能不能看不属于自己流程节点的数据
- D 的高权限接口是否真的只有 D 可用
五、一套可执行的最小验证骨架
如果你要把这块长期做稳,建议至少固定下面这套最小骨架。
1. 登录链路检查表
| 检查项 | 目标 |
|---|---|
| 正常登录 | 确认正确身份建立 |
| 错误密码多次尝试 | 确认失败边界 |
| 验证码/风控 | 确认异常登录是否有限制 |
| 异常设备/异常时间 | 确认是否有额外保护 |
| 登录成功凭证获取 | 明确后续会话验证对象 |
2. 会话失效检查表
| 场景 | 验证动作 | 预期 |
|---|---|---|
| 退出登录 | 重放旧请求 | 应拒绝访问 |
| 修改密码 | 重放旧请求 | 应拒绝访问 |
| 角色降权 | 重放高权限请求 | 应拒绝访问 |
| 新设备登录 | 旧设备继续请求 | 依据产品策略校验 |
3. 权限模型检查表
| 接口/动作 | 普通用户 A | 普通用户 B | 审核员/管理员 | 关注点 |
|---|---|---|---|---|
| 查看详情 | 只能看自己 | 只能看自己 | 视角色策略而定 | 数据隔离 |
| 修改资料 | 只能改自己 | 只能改自己 | 可受限修改 | 资源归属 |
| 审批通过 | 不可执行 | 不可执行 | 可执行 | 动作权限 |
| 导出数据 | 受范围限制 | 受范围限制 | 可扩展范围 | 数据边界 |
这三张表一旦固定下来,后面每个新模块都可以直接套。
六、测试时最容易踩的几个坑
1. 只测登录成功,不测身份变更后的残留问题
很多问题都发生在:
- 退出后
- 改密后
- 降权后
- 切角色后
如果只测“能不能登录”,问题会漏很多。
2. 只测页面,不测接口
页面层很容易显得“权限控制很好”,但真正动作往往还得在接口层重放一次才知道。
3. 不准备干净的角色和资源关系
如果账号、部门、审批链、数据归属关系本来就没配清楚,最后很容易把共享数据误判成越权。
4. 忽略多端和多系统边界
很多系统问题不是单点接口的问题,而是:
- Web 端失效了
- App 端没失效
- 后台系统降权了
- 前台接口缓存的旧权限还在
七、真实案例:为什么管理员被降权后,旧浏览器还能继续删用户
场景
一个后台管理系统里,管理员账号可以执行高风险动作,比如:
- 删除用户
- 调整角色
- 导出全量报表
某次组织调整后,一个管理员账号被降为普通运营角色。
按产品预期,这个账号之后只能做基础查询,不能继续删用户。
执行
先用管理员身份登录后台,抓到了删除用户接口:
1 | POST /admin/user/delete |
然后做了这几步:
- 在后台把该账号角色降为普通运营
- 不刷新当前浏览器,直接重放原删除请求
- 再在新浏览器重新登录同一账号,对比两边行为
现象
结果非常典型:
- 新浏览器重新登录后,删除按钮已经消失
- 新会话直接调删除接口会返回无权限
- 但旧浏览器里的原 Session 继续重放删除请求,仍然可以删除用户
这说明权限收回只影响了新登录会话,没有影响已存在的旧会话。
排查
顺着代码和日志看,问题链路是这样的:
- 登录成功时,系统把角色权限快照写进了 Session
- 后续接口校验直接使用 Session 里的角色信息
- 角色变更时,只更新了数据库里的角色关系
- 没有同步使旧 Session 失效,也没有在关键动作处重新校验当前角色
本质上是两个问题叠在一起:
- 会话失效没收回来
- 高风险动作没做实时权限校验
修复
最后给出的修复建议分成 4 条:
- 角色变化后主动失效该账号所有在线会话
- 高风险管理动作必须实时查当前权限,而不是只信 Session 快照
- 管理后台增加会话版本号或权限版本号校验
- 增加自动化回归用例:
- 高权限账号登录
- 中途降权
- 旧请求重放
- 预期高风险动作立即失效
这个案例很典型地说明了一点:
权限模型不只是“现在是什么角色”,还包括“旧身份什么时候必须失效”。
八、怎么把这类验证持续沉淀下来
更合适的做法是把这块沉淀成固定回归项,而不是靠人工临场判断。
第一层:上线前固定检查
高风险模块至少固定看:
- 退出后旧会话是否失效
- 改密后旧会话是否失效
- 角色变化后旧权限是否失效
- 关键动作是否做服务端动作权限校验
- 数据权限是否按资源归属隔离
第二层:自动化回归
最值得固化成脚本的包括:
- 退出登录后重放关键请求
- 改密后重放关键请求
- 降权后重放高权限请求
- 普通账号重放审批、删除、导出等高风险动作
这些脚本不一定很复杂,但价值很高,因为这类问题非常容易被后续改动重新带回来。
九、写在最后
登录、会话和权限模型这三块之所以值得长期固定检查,是因为它们决定了业务系统最基本的身份边界。
说到底,这些问题最终都在回答同一件事:
- 这个人到底是谁
- 这个身份现在还算不算有效
- 这个身份当前到底能做什么
如果这三个问题没有在系统里被严谨回答,前面看起来再完整的功能流程,安全上都可能是空的。