One part of the preparation for my upcoming talk at BSides RI involved shuffling some cash from my bank account to make it available on my credit card. While in this process, something struck me as rather odd, as seen on the following Burp output:
As we can see, the URL query string contains a parameter identified as “KortNo”. And this just so happens to contain what is in fact my credit card number. So the question becomes, is this a big deal? Well, this had me wondering and looking at it from a PCI perspective; I think there may be some cause for concern.
Access logs, browser history
It’s of course common practice for companies to keep access logs for all HTTP servers in the event of a system breach for forensic purposes. PCI has a mandate for companies to retain at least 1 year worth of “logs”. Because PCI mandates logs are kept, you are 99% likely as a bank to keep your HTTP logs, including the URL requested. In this instance, we make a request with data that PCI has a strong view upon the storage of, including the very explicit requirement of encrypting the PAN(Primary account number), CVV2, expiration date, and any other personally identifiable information if you store the 3 former.
So what happens when you make a HTTP GET request containing data which PCI mandates the encryption of, and it goes into a standard IIS log? Well, you are storing data in violation of PCI compliance. You will only need to get your hands on the access logs from the server to now access a lot of credit card data. This is rather unfortunate.
Even more likely, is that your personal browser history will now contain your credit card number and hang on to it. Of course, this requires some social engineering to be relevant. However, if this is not made known to the user, then this is a cause for concern.
Of course, when you run a web site, you like to track user behavior on your site. Who doesn’t? Banks do, and in this case, the above concerns are amplified when I noticed this request having been made by my browser at the same time:
What you see here is a standard Google analytics callback. We see that our query string containing data that PCI mandates that you must ensure is stored correctly is now sent off to a third-party. That is Google in this case. Ok, we may trust Google, but it also means that anybody with access to the Google analytics account now can view this credit card data. That means that this bank will now have to explicitly have made a contract with Google to verify that they will safe-keep this PCI data.
Is that likely? Not really. This is just an unfortunate side-effect of the bad practice of using the straight up PAN(Credit card number) as a part of the request through a query-string.
Putting it into perspective
When I discovered this, I rushed over to my other bank account(with a different back) to check if a similar problem existed over there. I observed that they had made the seemingly explicit design decision of not using the credit card number. Rather, they used a hash and a GUID to identify my credit card. While they were using a third-party analytics service, it did not contain personal information to the extent the above did as a result, which mitigates potential concerns in this regard.
- 13/05/2013 – Advisory sent to CERT
- 13/05/2013 – CERT confirms receipt of advisory, promises to provide contact at vendor
- 14/05/2013 – CERT still searching for appropriate vendor point of contact
- 15/05/2013 – CERT provides point of contact
- 15/05/2013 – Advisory sent to vendor
- 15/05/2013 – Vendor response confirming issue
- 15/05/2013 – Vendor deploys fix
- 16/05/2013 – Advisory published
It should be noted that the bank in question was quick to respond and fix the privacy concern in a professional manner. I’ve redacted the name of the bank as the goal of this was to highlight a potential pitfall that others may fall into, and hopefully this may encourage other banks to ensure that this is not a concern in their systems as well.