承接前文:前面我们完成了 API 静态测绘、动态状态机逆向、批量赋值对象劫持三类核心漏洞挖掘。本篇进入 API 业务逻辑漏洞第四阶段:服务器端参数污染(SSPP)

不同于 XSS、SQL 注入这类前端输入过滤缺陷,SSPP 是微服务架构通信层面的深层逻辑漏洞。核心成因是网关与内网服务的通信契约被破坏,攻击者利用协议解析差异篡改后端内部请求,实现越权查询、参数覆盖、状态劫持,隐蔽性极强、危害极高。

一、漏洞本质:微服务代理转发的信任裂痕

现代微服务架构普遍采用「外网网关 + 内网业务服务」分层架构。用户请求仅触达前置网关,网关会二次组装参数,对内网真实接口发起服务端请求,完成数据查询与权限校验。

正常业务流程示例: 用户请求:GET /userSearch?name=peter 网关内部拼接请求:GET /internal/api/users?name=peter&publicProfile=true

SSPP 漏洞的核心根源:网关直接使用原始用户输入硬拼接 URL,未做强制 URL 编码过滤。攻击者可注入 #、&、= 等 URL 特殊字符,直接破坏内网请求结构,篡改服务端调用逻辑。

二、协议层截断利用:基于 RFC3986 规范的请求逃逸

SSPP 最基础、最核心的利用方式为参数截断逃逸,原理完全遵循 RFC3986 URI 官方解析规范,属于协议层面的底层利用。

在 URI 标准中,# 被定义为片段标识符,作用是标记页面锚点。协议强制规定:# 及其后续内容不会被带入 HTTP 请求报文,仅在本地客户端解析

实战截断流程: 攻击者传入参数:username=administrator%23 网关拼接后内网 URL:/internal/api/users?username=administrator#&field=email 网关底层 HTTP 客户端(HttpClient、cURL)严格遵循协议规范,直接丢弃 # 后面的所有参数。最终内网服务仅收到 username=administrator,丢失了 field 等必填安全参数。

参数缺失会触发后端报错(Field not specified),这也是我们判定存在 SSPP 漏洞、可控截断内网请求的核心探针信号。

补充解答问题 1

很多人会产生疑问:# 本身就是截断后方内容,为何服务端会直接抛出 field not specified? 原因分为两点:

  1. # 的定位就是片段起点:按照 RFC3986 规范,解析器一旦识别到 #,就会将该符号判定为URI 片段标识符的起始位置,从这个位置往后的所有字符,都属于仅用于前端页面定位的本地片段,不属于发往服务端的请求参数;
  2. 截断的完整影响:网关拼接的 &field=email 处在 # 之后,会被整体截断、剥离在 HTTP 请求之外。内网接口设计要求 field 为必填项,请求中缺失该参数,业务逻辑无法正常执行,因此返回字段未指定的报错。简单来说:# 的作用就是彻底切断它后方的所有内容,导致网关附加的安全参数完全失效。

简单来说:攻击者利用标准协议特性,物理层面抹除了网关追加的安全限制参数,彻底绕过前置校验逻辑。

三、黑盒逆向:内部参数结构盲测与高价值字段挖掘

通过截断报错确认漏洞存在后,可进一步利用 %26(&) 注入新参数,逆向内网 API 的数据契约结构。

标准探测载荷username=administrator%26field=x%23 该载荷可以补齐被截断的参数结构,让请求语法合法。若服务返回 Invalid field,说明参数名合法、参数值非法,证明我们可控内网接口的指定字段。

补充解答问题 2

这里先解释核心概念:field 是什么?为什么需要爆破?

  1. field 的含义:该参数是内网接口约定的查询字段指令。内网 API 先通过 username 定位到数据库里对应的用户数据行,再依靠 field 的取值,指定需要返回该用户实体中的某一个具体字段,比如邮箱、角色、密码哈希、重置令牌等;
  2. 爆破的必要性:黑盒测试场景下没有接口文档,我们无法提前获知后端用户数据表包含哪些字段,也不清楚 field 支持哪些合法取值,因此只能依靠字典枚举进行盲测;
  3. email、reset_token 响应 200 的原因:当我们枚举的取值(email、reset_token)恰好和后端数据库实体、接口规则中定义的字段名完全匹配时,ORM 框架可以正常解析指令、查询并返回对应数据。接口逻辑完整执行,没有参数错误、字段不存在等异常,服务端就会返回 HTTP 200 OK 状态码。借助这个响应特征,我们就能判断枚举命中了有效字段,同时拿到邮箱、密码重置令牌等高敏感数据。

内部字段爆破原理: 内网 API 通过 username 定位数据库实体,通过 field 参数指定需要返回的实体字段。在无文档黑盒场景下,可枚举常见高敏感字段:email、role、permissions、reset_token、password_hash

当枚举命中后端真实实体字段时,ORM 框架正常完成数据映射,接口返回 200 状态码并带出敏感数据。借此可完整逆向内网接口参数结构,直接越权读取管理员重置令牌、密码哈希等核心数据。

四、高阶利用:异构解析导致的参数覆盖绕过

除了参数新增、截断逃逸,SSPP 高阶攻击为同名参数覆盖。HTTP 协议对重复参数无统一解析标准,不同后端框架存在解析歧义,形成安全边界绕过漏洞。

攻击载荷示例name=peter%26name=administrator 内网最终请求:?name=peter&name=administrator

不同框架解析逻辑完全不同:

  1. PHP/Apache:后置参数覆盖前置,最终取值 administrator
  2. Express/Node.js:优先取第一个参数,或转为数组触发异常;
  3. ASP.NET:多参数拼接为字符串。

攻击者可根据目标框架特性,利用解析差异绕过前端参数校验,在内网服务层覆盖原始参数,实现权限绕过与数据篡改。

五、终极利用:Token 劫持与完整账户接管

通过 SSPP 越权获取到管理员 reset_token 后,可直接实现完整账户接管,其核心原理依赖 Web 无状态鉴权机制。

  1. HTTP 协议本身无状态,无法记录用户会话上下文;
  2. 密码重置 Token 本质是绑定用户 UID、有效期的临时特权凭证,等同于临时登录会话;
  3. 后端鉴权逻辑仅校验 Token 的真实性与有效期,不校验请求来源、登录状态。

补充解答问题 3

这里解答关键疑问:为什么拿到 Token 后,直接拼接到 URL 中就能进入密码重置页面? 现代密码重置功能基于无状态令牌鉴权设计,整套逻辑不依赖登录会话:

  1. 当管理员发起忘记密码操作时,后端会生成唯一的 reset_token,并将该令牌、对应用户 ID、过期时间绑定存储在数据库中;
  2. 整个鉴权逻辑只校验两件事:Token 是否存在、是否在有效期内,不会校验访问者身份、登录状态、IP 来源
  3. 攻击者将窃取到的 Token 拼接进重置接口 URL 并发起请求,后端查询数据库确认令牌合法有效后,就会默认当前访问者为令牌归属的合法用户,直接放行并跳转到密码重置页面。这也是仅靠一串 Token 就能完成账户接管的核心原因。

攻击者携带泄露的 Token 访问重置接口,后端校验通过后,直接赋予高权限操作身份,无需原始密码、无需登录会话,即可完成密码重置、账户全权接管。

六、漏洞总结与防御方案

SSPP 漏洞并非单一代码缺陷,而是微服务通信架构设计不规范、参数拼接机制不安全、协议解析认知缺失导致的复合型逻辑漏洞。其核心危害在于:可以直接击穿内网信任边界,绕过所有前置安全校验。

标准化防御方案

  1. 禁止原生字符串硬拼接 URL,统一使用官方 URI Builder 工具类组装内网请求;
  2. 所有用户可控输入,传入内网请求前强制完成完整 URL 编码;
  3. 内网服务不无条件信任网关请求,增加参数白名单校验与权限二次核验;
  4. 统一后端参数解析规则,杜绝多框架异构解析带来的绕过风险。
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐