At one of my previous jobs we had a client who's organisation was crazy about security of the customer data, such as credit card numbers or billing info. They wanted to make their online store to be PCI compliant. Payment Card Industry Data Security Standard (PCI DSS) is a worldwide standard that was created to increase control of around cardholder data to reduce credit card fraud via its exposure. However it does not mean that this standard makes merchants more secure. In fact there are some new vulnerabilities that I am going to show you in this article.
In this article I am going to perform security analysis of the Drupal Commerce website that uses Authorize.net to accept payments. Drupal Commerce is a popular Drupal distribution, which is a competitor to Magento or Zen Cart. If fact, this vulnerability is not a problem of the certain eCommerce platform, however it is the problem of the PCI standard itself. I am running Drupal Commerce shop on my local machine and it does not send any real requests to the Authroize.net. Also it uses some random keys, IDs and hashes, which is enough to show you this vulnerability. In this example we will assume, that the attacker knows the Authorize.net MD5 Hash, which he or she got somehow (which is a not hard thing to do).
The official PCI Compliance manual of the Authrize.net recommends to use Server Integration Method (SIM). If using SIM, payment is processed on the Authorize.net website to ensure cardholder data isn't processed or stored by the merchant. There is also a Drupal module that provides an extension for Drupal Commerce to work with the Authorize.net SIM. The following image gives a good explanation of how SIM works with a Drupal website.
And the next image illustrates an attack to the merchant that uses SIM. This attack is possible if an attacker knows the Authnet MD5 Hash. And this is the only thing he or she needs to know. An attacker can sniff all other important information (except the MD5 Hash of course) during a POST request to the Authorize.net. Then an attacker sends a POST request to the Drupal website. Fields of this request should be signed by the MD5 Hash. In fact an attacker can simulate a payment without the Authroize.net link in a checkout chain.
Now if we look inside Authnet SIM/DPM module, we can find that the processing of a final step of an order is done in the
commerce_authnet_simdpm_complete() function when the browser sends a POST request to the
And here is part of the code that performs a payment verification.
As we can see, an MD5 Hash is used to verify a signature. Same hash is used to sign a request, so it means that the Authorize.net uses a synchronous signing. If we know this MD5 hash, Authnet is no longer required link in a whole payment chain. We can form any packet with a forged signature and send this packet via POST request to the Drupal site.
All right, now it is time to hack the Authnet SIM/DPM module for the Drupal Commerce.
1. Grab the MD5 Hash
Let's check the Authnet configuration in our Drupal Commerce store. We can see that many keys are in use, however only API Login ID and MD5 Hash are involved into the payment verification process. In this example we just need to grab the MD5 Hash and save it for the future use.
2. Make an order
Now we should make an order and proceed to the checkout page. Then click the Checkout button.
3. Select a payment method
In our case we have a single option. Click the Continue to the next step button.
4. Submit the SIM form
On the next page we can see a SIM form that sends a POST request to the Authorize.net. Click the Submit Order button.
5. Sniff the POST request
I've used Burp Suite to sniff a POST request when the Submit Order button is clicked. Thus we can extract an important info such as API Login ID, order ID, amount, currency, etc. We will use this info to submit a fake request to the Drupal site.
6. Generate a fingerprint
To generate a fingerprint we need to know following info:
- API Login ID - which we sniffed.
- Amount - which we also sniffed.
- Transaction ID - which is usually generated by Authorize.net, however it could be a random string, anyway Drupal Commerce does not check it.
- MD5 hash - this is a unique hash for each merchant, which we should know in advance.
7. Send a fake POST request to the Drupal Commerce site
Having all this info we can generate a fake POST request to our store. We will make the Drupal Commerce to think that the payment was done by the Authorize.net. To generate a POST request I use Postman - REST Client, which is very nice Chrome extension.
8. Get the URL in the response HTML
Drupal Commerce returns a URL. This URL is used to complete an order.
9. Open the URL in a browser window
Make sure to replace
& with & in the URL. You'll be redirected to the Order Complete page.
Here you are, we just cheated the Drupal Commerce!
- Authorize.net Direct Post Method (DPM) has the same vulnerability as it notifies the Drupal Commerce via POST request.
- CyberSource payment gateway, which has been bought by the VISA recently, has the same kind of vulnerability. They have an analogue of Authnet SIM, known as Secure Acceptance Web/Mobile.
- You can actually cheat the Drupal Commerce even if you don't even know the MD5 Hash! You simply need to intercept a POST request to the Authorize.net and modify the currency. And cause this request is done by your browser, it is quite easy to intercept and modify it. So you can buy 5 USD item for a 5 RUB. Of course you should no do so :)
- And at last you can send Drupal Commerce the fingerprint from the previous order that you or someone else did. And Drupal Commerce will accept it!
The whole bunch of vulnerabilities casts doubt on the benefits of using the PCI compliance, as most of it's implementations can actually heart merchants.
How to protect yourself?
This is a good question. As the solutions that comes our of the box has vulnerabilities, you need to perform various approaches to defend from such attacks.
- Always check that the Transaction ID for any order matches Transaction IDs stored in Authorize.net. Fortunately Drupal Commerce logs this info for every payment.
- Check that the amount and currency of a payment match amount and currency of an order.
- Check that the payment signature never repeats.
- 1 - 3 could be automated to generate you a list of suspicious orders.
I will note once again that this article was created for the developers and merchants to make sure they know about vulnerabilities that their online stores may have. I will probably write more articles like this, investigating different Shopping Carts or different vulnerabilities. Please share you thoughts and feel free to post a comment!
In reality Authorize.net sends POST request directly to the Drupal Commerce website and then redirects you to the order confirmation step.