CVE-2019-14977: Rejection of vulnerability report on Instamojo's plugin for WooCommerce

A security vulnerability report was recently published in public domain stating Instamojo’s plugin for WooCommerce was vulnerable to URL parameter tampering which lets the buyer pay a lesser amount than what a merchant expected and get the payment to be successful.
The full content of the report can be viewed at https://nvd.nist.gov/vuln/detail/CVE-2019-14977
In this post, we will explain why this is a false positive, and that the vulnerability described does not exist.
Below contains technical details & examples that helps in understanding why the reported vulnerability is invalid. The below details are intended for a technical audience. 
The report claims that signature in a POST endpoint can be swapped with signature of another order of lower amount and Instamojo’s systems still allows the payment to go through. Lets look at some examples:
Original endpoints (without any tampering)
GET request of the iframe for an order of Rs. 1010
$ curl -I -X GET 'https://cde.instamojo.com/card/pay/c11a44fd-8593-4180-b60e-ea252df8ea85/?amount=1010.00&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&card_id=11&return_url=https%3A%2F%2Fwww.instamojo.com&sign=e0a4740180dc1a4ca422bacff3d8c16e85ccbce4&&newWindow=true'

HTTP/2 200

date: Tue, 03 Sep 2019 10:10:39 GMT

content-type: text/html; charset=utf-8

content-length: 49131

set-cookie: csrftoken=TrQZ7TrHaUhnSsiQkBI81Q2OAUy4BaoMdyfJZ8cELD3XNwajoybRZM5PmIZfN3dk; expires=Tue, 01-Sep-2020 10:10:39 GMT; HttpOnly; Max-Age=31449600; Path=/; Secure
POST request of the iframe for an order of Rs. 1010
$ curl -i -X POST -H 'Referer: https://cde.instamojo.com/' 'https://cde.instamojo.com/card/pay/c11a44fd-8593-4180-b60e-ea252df8ea85/?amount=1010.00&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&card_id=11&return_url=https%3A%2F%2Fwww.instamojo.com&sign=e0a4740180dc1a4ca422bacff3d8c16e85ccbce4&&newWindow=true' -d 'csrfmiddlewaretoken=GhLxCR1ol1I5Ne6GAewDPG47Sbjh7aVqMBcgMNd5HSyUN01yKmj28FiJxYSvCFex&amount=1010.00&card_id=11&sign=e0a4740180dc1a4ca422bacff3d8c16e85ccbce4&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&save_card=None&return_url=https%3A%2F%2Fwww.instamojo.com&account_number=4242+4242+4242+4242&expiry_month=01&expiry_year=20&security_code=111'

HTTP/2 200

date: Tue, 03 Sep 2019 10:34:01 GMT

content-type: text/html; charset=utf-8

content-length: 2320
GET request of the iframe for an order worth Rs. 20
$ curl -I -X GET 'https://cde.instamojo.com/card/pay/d48c0978-eb0d-4816-8f3c-c0c2e35751e1/?amount=20.00&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&card_id=11&return_url=https%3A%2F%2Fwww.instamojo.com&sign=e3cb0092a0deacce79f23a9aa10deb27ea8a08b7&&newWindow=true'

HTTP/2 200

date: Tue, 03 Sep 2019 10:13:23 GMT

content-type: text/html; charset=utf-8

content-length: 49126

set-cookie: csrftoken=c3brmpXwP3q8b4QWreXlrmKzUxhuSMcE1WQRM84CrVII6wK8nkaOAOIvFqsdQQNt; expires=Tue, 01-Sep-2020 10:13:23 GMT; HttpOnly; Max-Age=31449600; Path=/; Secure
POST request of the iframe for an order worth Rs. 20
$ curl -i -X POST -H 'Referer: https://cde.instamojo.com/' 'https://cde.instamojo.com/card/pay/d48c0978-eb0d-4816-8f3c-c0c2e35751e1/?amount=20.00&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&card_id=11&return_url=https%3A%2F%2Fwww.instamojo.com&sign=e3cb0092a0deacce79f23a9aa10deb27ea8a08b7&&newWindow=true' -d 'csrfmiddlewaretoken=nEQA1HpftQStUzrdvYcxomMdM0InEmuUtYhjbDBWPHIiUlm5F6ZWHl0PrNhB9RN1&amount=20.00&card_id=11&sign=e3cb0092a0deacce79f23a9aa10deb27ea8a08b7&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&save_card=None&return_url=https%3A%2F%2Fwww.instamojo.com&account_number=4242+4242+4242+4242&expiry_month=01&expiry_year=20&security_code=111'

HTTP/2 200

date: Tue, 03 Sep 2019 10:41:44 GMT

content-type: text/html; charset=utf-8

content-length: 2320
Note: The above examples use a dummy card number & dummy CVV code.
Observations:
  1. Signature used for order worth Rs. 1010 is e0a4740180dc1a4ca422bacff3d8c16e85ccbce4
  2. Signature used for order worth Rs. 20 is e3cb0092a0deacce79f23a9aa10deb27ea8a08b7
  3. For GET requests, signature is present in URL parameters
  4. For POST requests, signature is present in both URL & POST body
Tampering Attempts
Using signature of cheaper order in URL & body of expensive order (POST)
$ curl -i -X POST -H 'Referer: https://cde.instamojo.com/' 'https://cde.instamojo.com/card/pay/c11a44fd-8593-4180-b60e-ea252df8ea85/?amount=1010.00&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&card_id=11&return_url=https%3A%2F%2Fwww.instamojo.com&sign=e3cb0092a0deacce79f23a9aa10deb27ea8a08b7&&newWindow=true' -d 'csrfmiddlewaretoken=GhLxCR1ol1I5Ne6GAewDPG47Sbjh7aVqMBcgMNd5HSyUN01yKmj28FiJxYSvCFex&amount=1010.00&card_id=11&sign=e3cb0092a0deacce79f23a9aa10deb27ea8a08b7&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&save_card=None&return_url=https%3A%2F%2Fwww.instamojo.com&account_number=4242+4242+4242+4242&expiry_month=01&expiry_year=20&security_code=111'

HTTP/2 400

date: Tue, 03 Sep 2019 11:00:35 GMT

content-type: text/html; charset=utf-8

content-length: 16


Invalid request.
As expected, the request has been rejected because of signature tampering
Using signature of cheaper order in POST body of expensive order URL (POST)
In this case, signature in URL is unchanged.
$ curl -i -X POST -H 'Referer: https://cde.instamojo.com/' 'https://cde.instamojo.com/card/pay/c11a44fd-8593-4180-b60e-ea252df8ea85/?amount=1010.00&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&card_id=11&return_url=https%3A%2F%2Fwww.instamojo.com&sign=e0a4740180dc1a4ca422bacff3d8c16e85ccbce4&&newWindow=true' -d 'csrfmiddlewaretoken=GhLxCR1ol1I5Ne6GAewDPG47Sbjh7aVqMBcgMNd5HSyUN01yKmj28FiJxYSvCFex&amount=1010.00&card_id=11&sign=e3cb0092a0deacce79f23a9aa10deb27ea8a08b7&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&save_card=None&return_url=https%3A%2F%2Fwww.instamojo.com&account_number=4242+4242+4242+4242&expiry_month=01&expiry_year=20&security_code=111'

HTTP/2 400

date: Tue, 03 Sep 2019 11:02:14 GMT

content-type: text/html; charset=utf-8

content-length: 16
Invalid request.
This is as expected. Request has been rejected because of signature tampering in POST body. 
Using signature of cheaper order in expensive order URL (GET)
$ curl -i -X GET 'https://cde.instamojo.com/card/pay/c11a44fd-8593-4180-b60e-ea252df8ea85/?amount=1010.00&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&card_id=11&return_url=https%3A%2F%2Fwww.instamojo.com&sign=e3cb0092a0deacce79f23a9aa10deb27ea8a08b7&&newWindow=true'

HTTP/2 400

date: Tue, 03 Sep 2019 10:17:40 GMT

content-type: text/html; charset=utf-8

content-length: 16
Invalid request.
This is as expected. Request has been rejected because of signature tampering in URL.
Using signature of cheaper order in expensive order URL (POST)
In this case, signature in POST body is left unchanged.
$ curl -i -X POST -H 'Referer: https://cde.instamojo.com/' 'https://cde.instamojo.com/card/pay/c11a44fd-8593-4180-b60e-ea252df8ea85/?amount=1010.00&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&card_id=11&return_url=https%3A%2F%2Fwww.instamojo.com&sign=e3cb0092a0deacce79f23a9aa10deb27ea8a08b7&&newWindow=true' -d 'csrfmiddlewaretoken=GhLxCR1ol1I5Ne6GAewDPG47Sbjh7aVqMBcgMNd5HSyUN01yKmj28FiJxYSvCFex&amount=1010.00&card_id=11&sign=e0a4740180dc1a4ca422bacff3d8c16e85ccbce4&api_key_id=4bde5349-6e91-4aad-a4e5-c120ab51b3b4&save_card=None&return_url=https%3A%2F%2Fwww.instamojo.com&account_number=4242+4242+4242+4242&expiry_month=01&expiry_year=20&security_code=111'

HTTP/2 200

date: Tue, 03 Sep 2019 10:58:53 GMT

content-type: text/html; charset=utf-8

content-length: 2320
Even though the signature is tampered in URL parameter (while still keeping the signature in body unchanged), the request will go through as expected since our servers considers the signature in POST body only (not URL parameter). For this endpoint, the URL parameters are ignored for POST requests and only POST data is considered.
For the above request, the payment processed is for Rs. 1010 only (not Rs. 20). Check the screenshot below (using a real card):
hdfc.png
These examples demonstrate that the vulnerability as described in the report is a false positive
Instamojo’s APIs are validating the signature as expected to prevent amount tampering on client-side.
Start Exploring
Was this article helpful?
2 out of 2 found this helpful
Have more questions? Submit a request