How i was able to exploit a vulnerable payment system.

ZalparusZalparus
2 min read

Hello hackers and security enthusiasts, we are here again to serve you dinner in a 5-star hotel 😊. Hope you enjoy it !!!.

LITTLE BIO ABOUT ME

I’m David, a software developer and cybersecurity researcher who specializes in application security. I spend my time writing secure backend code, breaking stuff in CTFs (mostly on HackTheBox), and hunting bugs in real-world applications. My stack revolves around Python, PHP (Laravel), and JavaScript. I’ve got a thing for logic flaws and money-related vulnerabilities.

ABOUT THE PLATFORM.

So here’s the gist…

The platform is a basic E-commerce application — let’s call it redacted.com. It sells physical products, PDFs, and other digital content. Pretty standard stuff: registration/login pages, product listings, shopping cart, checkout… but there’s a digital wallet integrated into the platform.

Now that wallet system is where things start to get interesting — and vulnerable. 👀

Every user, on account creation, gets a wallet assigned to them. This wallet can be topped up via different payment gateways. Once the payment is confirmed, the backend adds the corresponding amount to the user’s wallet balance.

🔥 Now let’s get into the juice — a real-world insecure implementation I found:

After successful payment, the app hits a backend endpoint like this:

POST /api/wallet/topup
Content-Type: application/json

{
  "user_id": 124,
  "amount": 100.00
}

No token. No signature. No validation that the request actually came from the payment gateway.

That’s it. Just a raw unauthenticated endpoint that increases the balance based on whatever payload you throw at it.

So guess what? Once I saw that, I immediately fired up Burp Suite and replayed the same request over and over. 💰💰💰

Result? My wallet balance went up every single time.

This is what we call a logic flaw. The server blindly trusts that any incoming user_id and amount must be valid. It assumes the client only calls this endpoint after a legit payment — but it doesn’t actually verify that with the gateway or check for replay. I can actually tamper the user_id value and add balance to a different user, because from the look of things, the user_id is an incremental integer.

🔍 What Should’ve Been Done?

At the very least:

  • The endpoint should validate the payment with the third-party gateway (e.g., verify transaction ID with Paystack, Flutterwave, Stripe, etc.).

  • There should be server-side verification, not client-side trust.

  • Idempotency: each payment transaction should only be processed once.

  • Use proper auth & signatures to ensure requests originate from the gateway or trusted service.

😎

We break codes, not hearts. 💔💻❤️

0
Subscribe to my newsletter

Read articles from Zalparus directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Zalparus
Zalparus

I develop secured software and also perform actively in cybersecurity researches