[安全测试] 浅谈参数污染测试
2026/6/6 2:15:36 网站建设 项目流程

原创内容,未获授权禁止转载、转发、抄袭。

接口测试时,我们经常会测必填、类型、长度、边界值。但有一类问题很容易被忽略。
就是参数污染

下面的示例只适用于授权测试环境。

1. 什么是参数污染

HTTP 参数污染,简称 HPP。

简单说,就是攻击者在同一个请求里传多个同名参数,利用后端对参数解析方式的差异,影响业务逻辑。

比如:

username=test_user&username=admin

或者 JSON 请求体里出现重复字段:

{"username":"test_user","username":"admin","password":"******"}

重点不是请求能不能发出去。

而是后端最终取了哪个值。

这类测试最好用 Burp、Charles、Postman raw body 或curl构造原始请求。

不要只在可视化参数表格里改。

有些工具会自动去重,导致测试请求根本没把重复字段发出去。

核心原理

Query、Form 这类参数层面,同名参数可能会被传到服务端。

JSON 重复字段则更依赖解析器和框架实现。

不同后端框架,对重复参数或重复字段的处理方式不一样。

  • 有的取第一个值
  • 有的取最后一个值
  • 有的拼接成字符串
  • 有的解析成数组

如果业务代码没有显式校验,就可能出现非预期结果。

参数污染本身不一定是漏洞。

但如果影响登录、支付、退款、权限、金额,就是高风险问题。

危害场景

常见风险主要有两类。

第一类是业务逻辑漏洞。

比如登录成错误用户、支付金额被篡改、退款金额异常、订单状态被错误更新。

第二类是绕过安全机制。

比如绕过输入校验、绕过权限判断,或者配合其他漏洞扩大影响范围。

下面用两个例子说明。

2. 例子1:登录接口参数污染

正常登录请求大概是这样:

{"username":"test_user","password":"******","institutionId":"ORG_ID"}

测试时,可以把请求体改成:

{"username":"test_user","username":"admin","password":"******","institutionId":"ORG_ID"}

这时不要只看接口是否返回成功。

要继续验证最终登录身份。

  • token 里是谁
  • 当前用户接口返回是谁
  • 页面展示的用户是谁
  • 会话表保存的是谁
  • 操作日志记录的是谁

如果用普通用户密码,最后登录成了管理员。

这就不是普通参数问题。

这是身份认证逻辑缺陷。

进一步验证

还要把两个username的顺序调换:

{"username":"admin","username":"test_user","password":"******","institutionId":"ORG_ID"}

如果调换顺序后,登录身份也跟着变化。

说明后端很可能采用了“第一个值”或“最后一个值”的解析策略。

测试结论不要写:

登录接口返回成功。

而要写:

登录接口存在重复 username 参数解析风险,调换字段顺序后登录身份发生变化,可能导致身份认证被绕过。

漏洞原理分析

这里通常有几种可能。

第一种,覆盖策略。

后端取最后一个username,导致前面的值被覆盖。

第二种,首值策略。

后端只取第一个username,后面的值被忽略。

第三种,数组策略。

解析器把重复字段处理成数组。

如果业务代码期望字符串,但实际拿到数组,又没有做类型校验,就可能出现异常逻辑。

测试时要把解析策略写清楚。

不要只记录“成功”或“失败”。

3. 例子2:支付接口金额污染

支付接口更危险。

因为参数污染一旦影响金额,就可能造成直接经济损失。

正常支付请求:

{"orderId":"ORDER_ID","model":1,"paymentDetailList":[{"type":"PAY_TYPE","actualAmount":99.00,"changeAmount":0}]}

污染后的请求:

{"orderId":"ORDER_ID","model":1,"paymentDetailList":[{"type":"PAY_TYPE","actualAmount":99.00,"actualAmount":1.00,"changeAmount":0}]}

还可以继续验证极端金额场景。

比如 0 元、负数、小数精度异常等。

这类场景要重点验证:

  • 实际支付金额是多少
  • 支付流水金额是多少
  • 订单原始金额是否被改动
  • 订单状态是否变成已支付
  • 财务记录是否一致
  • 是否出现低价买入、0 元购、倒贴金额

支付接口不能信任前端传来的金额。

服务端必须重新计算订单金额。

漏洞根因

这类问题一般不是单点原因。

常见根因有三个。

第一,后端解析逻辑没有做重复参数检查。

比如框架把 JSON 自动绑定成对象时,默认接受了重复字段。

publicclassPaymentRequest{privateList<PaymentDetail>paymentDetailList;}publicclassPaymentDetail{privateBigDecimalactualAmount;}

如果actualAmount重复出现,框架可能取第一个,也可能取最后一个。

第二,金额验证缺失。

后端没有把前端传入金额和服务端订单金额做比对。

第三,业务流程设计有问题。

比如:

  1. 创建订单时,后端计算金额为 99.00
  2. 用户发起支付时,前端提交金额被篡改为 1.00
  3. 后端只判断支付成功,没有校验支付金额是否等于订单金额
  4. 订单状态直接变成已支付

这就是典型的业务一致性问题。

4. 安全危害

参数污染的危害,取决于它影响了哪个业务字段。

如果影响登录,可能导致账户接管。

如果影响权限,可能导致越权访问。

如果影响金额,可能导致直接经济损失。

如果影响订单状态,可能导致业务流程错乱。

尤其是这些字段,需要重点关注:

  • username
  • userId
  • roleId
  • tenantId
  • orderId
  • amount
  • actualAmount
  • couponId
  • status

这些字段一旦被污染,影响的通常不是页面展示。

而是身份、金额、权限和数据归属。

5. 修复建议

第一,严格输入校验。

同一个字段只允许出现一次。

发现重复参数,直接拒绝。

400 Bad Request

第二,关键参数不要信任客户端。

金额、折扣、优惠、订单状态,必须由服务端计算。

第三,身份和权限从服务端获取。

用户身份应该来自 token 或服务端会话。

不能信任前端传入的userIdusernameroleId

第四,支付流程要做双重校验。

  • 支付前校验订单状态
  • 支付前校验订单金额
  • 支付后校验支付流水
  • 异步任务核对订单和支付记录
  • 监控异常金额订单

第五,保留审计日志。

支付、退款、权限变更类接口,要记录原始请求、解析后参数和最终业务结果。

总结

参数污染测试,不是看接口能不能接收重复参数。

而是看重复参数有没有改变业务结果。

登录场景,要追最终身份。

支付场景,要追订单、流水和财务记录。

权限场景,要追真实数据访问范围。

只要参数能影响身份、金额、权限,就不能只看接口返回。

要一直追到数据库、日志和最终业务状态。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询