Bypassing Payment Portals through Response Modification

Endure Secure Knowledge Base
Table of Contents
< All Topics

Bypassing Payment Portals through Response Modification


There are several methods out there which have allowed attackers in the past to bypass payment, which usually involves modifying the request to the payment provider. This could entail changing the amount so that the product can be purchased for less than the intended price. Prior to writing this KB article, I did some quick googling to see if others had discovered similar issues to what I had discovered, and while I didn’t find any other people who had done similar writeups, there is a good article which shows common bypass techniques, which are achieved through request modification. The article can be found at While the author uses some pretty amateur wording, the three attacks are good to be aware of.

If you want somewhere to learn how to exploit weaknesses in payment gateways, PentesterLab has some fantastic modules under their API badge, that teach payment gateway security.

The Concept

Now before continuing, I don’t want to relay information about how payment gateways work, but to understand why this attack can work, the basic flow is important to know. The following section is copied from the link above, as I couldn’t explain it better myself.

A payment gateway focuses on securing the sensitive information given by the user throughout the payment process. It encrypts data such as card information and bank account details to ensure security for the user. The following are the basic steps showing how a typical payment gateway works:

  1. A customer places his or her order and then presses the Submit or Checkout button, or its equivalent button, on the website.
  2. Once this happens, the website or the e-commerce platform takes the customer to a payment gateway where he or she enters all the relevant information about the bank or the card they are using to pay. The PG then takes the user directly to the page of the issuing bank or a 3D secure page, asking for the transaction to be authorized.
  3. Once the payment gateway gets the approval for the transaction, the bank then checks whether the customer has sufficient balance in the account to make this transaction success or not.
  4. The payment gateway sends a message to the merchant accordingly.
    • If the reply from the bank is a “No’”, then the merchant subsequently sends an error message to the customer, telling them about the issue with the card or the bank account.
    • If the response is a “Yes” from the bank portal, then the merchant seeks the transaction from the bank.
  5. The bank settles the money with the payment gateway, which in turn settles the money with the merchant.

Once this process is completed, the customer gets a confirmation message that the order is placed.

The Attack

There is only one thing from the underlying concept that needs to be understood really, sometimes in a single request, and sometimes in multiple, the client makes a series of requests to the payment gateway, to understand if the card details are valid, if the funds are there, and ultimately if the transaction is approved. Relying on a response as whether to proceed with the customer interaction or block them at the payment portal. So why not modify the response and see what we can do? Most web application attacks, such as those in the OWASP top 10, are exploited by modifying the request. There are some instances of OWASP Top 10 vulnerabilities where you may exploit them by altering the response. But in my experience, this isn’t often the case. If you want a quick brush up on how to intercept requests and responses, portswigger has a YouTube video on this.

When testing an application, I noted that it would take your payment details, and then make calls to Stripe using client-side code. Which meant I could see the requests being made from the application to Stripe. I decided to try paying using a test Visa card. A list of which can be found here. The request below depicts a request to the Stripe API, containing the test Visa card number.

I intercepted the response to this request, which revealed an error was about the be returned to the client, on account that Stripe knew it was a test card and therefore invalid.
I decided to simply change the response code to “200 OK”, and remove the body, and to my surprise the transaction was approved.
My guess is that the client-side code, simply checked for the response code, either that it didn’t equal 402, or was equal to 200. Either way, the application didn’t even attempt to look at the payload, as upon success a payload would have also been returned. I didn’t investigate the client-side code too much.

Closing Thoughts and Remediation Advice

If you have this type of implementation, even with client-side code checking for a valid response, client-side code can be easily manipulated by an attacker. An attacker could intercept an earlier response with modified JavaScript that can undermine whatever you’re trying to do. However, if you have to provide a response, you can always check out API documentation for the payment gateway, which will tell give you all the information you’ll need to provide a valid response.

The easiest way to avoid this, is to avoid this type of implementation, either redirect the user to the payment gateway’s website, which should then in-turn, redirect to the original website, upon successful completion, or the more preferred way, which is handle the transaction API calls, to the payment gateway, via server-side code.

Stripe API Documentation: