I wrote previous article Hacking Drupal Commerce site that accepts payments through the Authorize.net SIM and got some healthy criticism from a maintainer of the Drupal Commerce. Actually in that article I described how to hack Commerce Authnet SIM/DPM module used in a pair with the Drupal Commerce, and it was true if you knew the Authnet MD5 Hash.
In this article I am going to show you how to cheat the Drupal Commerce. I will make 2 orders: one for $1000 and another for $30. Due to weaknesses in the Authorize.net SIM/DPM and the way Commerce Authnet SIM/DPM module processes payments I would be able to pay $30 for a $1000 order. All I need is just a modern browser with an HTML Inspector. As in previous time I am running Drupal Commerce on my local machine, and Authorize.net sandbox account.
Here are steps to reproduce this hack.
1. Make an order on a $1000
Then click checkout and follow further steps until you reach a payment form.
2. Skip submitting a SIM form
On this step Drupal Commerce order has turned order into the Checkout: Payment phase and this is what we needed. We can also check the Order ID, which is equal to 26. You simply skip submitting this form, as we don't want to pay a $1000 in this example :)
3. Make another order on a small amount
Then click checkout and follow steps until you reach a payment form. In this example $15 will be added for the delivery.
4. Submit a SIM form
As we can see Order ID is incremented and is equal to 27. On this step we should submit a hidden form which will us to the Authorize.net checkout page.
5. Change an Order ID hidden field before submitting a payment
This is a place where the magic happens. Open Browser Inspector and change values of hidden fields order_id and x_invoice_num from 27 to 26. Then fill payment info and submit a form. Actually it would also work, if we had modified values of hidden fields on the previous step.
6. Check that the order is complete
Here we are, order #26 on a $1000 goes to the next phase which is Pending.
There is still a way to check an amount which was paid and it is something easy noticeable by an admin. Also Drupal Commerce has a Checkout Completion Rules, which could only be triggered upon an order is paid in full.
It very looks like this vulnerability existed since the time this module was created, which is about 3 years. I would say this vulnerability has medium severity and some of the sites could be affected by it.
How to fix it
According to the official SIM/DPM docs, Order ID should be stored in fp_sequence field posted to the Authorize.net. This will work, because fp_sequence is a field that is used to generate a fingerprint. And here is the patch! It is also recommended to sign other fields, so we can make sure all merchant fields could not be changed.