
这个实验的核心是利用批量赋值 (Mass Assignment) 漏洞,这是Portswigger提供的所需的理论知识。

接下来我们从核心理论知识和靶场具体解题步骤来解决靶场
一、核心理论知识:批量赋值 (Mass Assignment)
1、什么是批量赋值?
想象一下你在网上注册一个账户,填写了用户名、邮箱和密码。当你点击"提交"时,后端服务器需要把这些信息保存到数据库里的一个用户对象(User Object)中。
为了方便,许多现代 Web 框架(如 Ruby on Rails, Node.js, Django 等)提供了一个便捷功能:它们可以自动将你提交的 JSON 数据或表单数据"批量"地绑定(或赋值)到代码中的对象属性上。
- 正常情况 :你提交
{"username": "wiener", "password": "peter"}
,框架自动更新用户对象的username
和password
属性。这很高效。 👍
2、漏洞是如何产生的?
问题出在当这个"自动绑定"的过程过于信任用户提交的数据时。如果后端代码不加区分地绑定了所有 收到的参数,攻击者就可以提交一些前端表单中本不存在、但后端对象中确实存在的隐藏属性。
-
漏洞利用:假设后端的 User 对象还有一个 isAdmin(是否为管理员)的属性,默认是 false。正常用户注册时,前端不会提交这个字段。但攻击者可以手动构造一个请求,加入这个字段:
{"username": "attacker", "password": "password123", "isAdmin": true}
如果后端不加验证地全盘接受,那么攻击者创建的账户就会被直接赋予管理员权限!😱
在这个靶场中,漏洞点不是 isAdmin
,而是一个与折扣相关的隐藏参数 chosen_discount
。
3、如何发现和验证这种漏洞?
-
侦察线索 🕵️ :比较获取数据的请求(如
GET /api/user/1
)和修改数据的请求(如POST /api/user/1
)。如果GET
请求的响应中包含一些敏感或有趣的字段,而POST
请求的模板中却没有这些字段,那么这些多出来的字段就是我们的重点怀疑对象。 -
探测验证 🔬:
-
将你发现的隐藏参数添加到修改数据的请求中(例如,使用 Burp Repeater)。
-
先用一个无害的值发送,看服务器是否报错。如果不报错,说明服务器可能接受这个参数。
-
再尝试发送一个错误数据类型的值(比如把一个期望是数字的参数改成字符串)。如果服务器返回了特定的错误信息(如 "Invalid number format"),这就强烈暗示了后端正在处理这个参数,漏洞存在的可能性极大!
-
最后,尝试一个能带来好处的值来利用它。
-
二、靶场具体解题步骤
按照这个思路,我们来一步步解决这个靶场。
1. 登录并尝试购买
首先,使用题目给出的凭证 wiener:peter
登录。然后找到那件 "Lightweight l33t Leather Jacket",将它加入购物车,并尝试"Place order"(下单)。你会发现因为信用额度不足,购买失败。这是我们预期要解决的问题

2. 抓包并分析 API 请求
在 Burp Suite 的 Proxy > HTTP history
标签页中,找到与结账相关的 API 请求。你会重点关注两个请求:
-
GET /api/checkout
:这个请求用于获取购物车和结算信息。 -
POST /api/checkout
:这个请求用于提交订单。
3. 发现隐藏参数 🎯
这是最关键的一步。
-
查看
GET /api/checkout
请求的响应 (Response) 。你会看到一个 JSON 结构,里面包含了当前的商品和总价等信息。仔细观察,你会发现一个名为chosen_discount
的参数,它的值可能是null
或0
。 -
现在,查看
POST /api/checkout
请求的请求体 (Request Body) 。你会发现它的 JSON 结构中只包含了chosen_products
,并没有chosen_discount
这个参数。
这个差异就是漏洞的线索!前端页面不让我们选择折扣,所以提交订单时自然不会包含 chosen_discount
。但后端既然在 GET
响应里返回了这个结构,说明它很可能认识这个参数。
4. 在 Burp Repeater 中重构请求
-
在 HTTP 历史记录中,找到
POST /api/checkout
这个请求。 -
右键点击它,选择 "Send to Repeater"(发送到 Repeater)。
-
切换到 Repeater 标签页。

5. 验证并利用漏洞 ✅
现在,我们要手动把 chosen_discount
参数添加到 POST
请求的 JSON 数据中。
-
初步添加 :将 JSON 修改为如下结构,先给一个
0%
的折扣,测试服务器是否接受这个新参数。bash{ "chosen_discount":{ "percentage":0 }, "chosen_products":[ { "product_id":"1", "quantity":1 } ] }
点击 "Send" 发送请求。你会发现服务器正常响应,没有报错。这说明我们的猜测是正确的。
-
探测确认 (可选但推荐) :为了进一步确认,可以把
percentage
的值改成一个非法的字符串,比如"x"
。"percentage":"x"
发送后,服务器会返回一个错误,提示数据类型不正确。这百分百证明了后端代码正在处理我们提交的这个隐藏参数。
-
最终利用 :现在,我们把折扣改成我们想要的值:
100
。{ "chosen_discount":{ "percentage":100 }, "chosen_products":[ { "product_id":"1", "quantity":1 } ] }
-
点击 "Send" 发送这个最终的请求。由于应用了 100% 的折扣,总价变为 0,你的信用额度就足够了。订单成功提交,实验也就解决了!
三、成功通关
