NOTE: The technique I will discuss here is not new, but is still an interesting and often overlooked trick that might come in handy sometimes.
While I explored the web-facing endpoints for a private bug bounty program, I stumbled across a specific URL that looked like this:
https://target.com.br/checkout/v1/payment/redirect?data=<hex-encoded payload>. Navigating to this URL would redirect me to the details page for a specific product purchased on the store.
There was nothing that interesting to it at first, but as I didn’t found anything yet I decided to take a better look. Decoding the hex payload resulted in a string of random-looking bytes, which is an indicative of encrypted data. To try understand what was happening with this data, I tampered with it by changing the last byte and noticed that it would redirect me to a different location.
After some digging I identified that this data was encrypted using a block cipher in CBC mode and that the redirect location changed because it failed to decrypt the payload. I immediately recognized this as a classic padding oracle scenario, so I tried to exploit it.
The tool usually employed to exploit such vulnerabilities is padbuster which is great, but can be very slow. Luckily, I had previously written a Perl library specifically for this purpose as part of IPerl’s modules, that could be used through multiple threads, significantly increasing the speed of the attack.
However, the target had rate limit rules in place that prevented me from doing more than 2 requests a second on this endpoint. This presented an interesting challenge and because I’m a rater anxious person, I figured it would be better try to bypass this instead of waiting a longer time.
I tried a few things without much success, but in the end the solution I found was both simple and clever, as it abused the public-facing web infrastructure of the target in a way it was intended to work.
As it turns out, the company that runs the website in question is present in multiple countries and uses a different domain with a distinct cTLD for each of them, but they all run the same application. For example, they were using target.com.br in Brazil, target.com.mx in Mexico, target.com.ar for Argentina and so on, all sharing the same backend. However, the rate limit rules were set per-host as it is often the case for most applications behind a WAF, so each of those hosts would keep track of the request rate separately.
This allowed me to perform a bigger number of requests by distributing them across multiple hosts, without reaching the individual limits of them. I identified distinct domains for six countires where this store was available and by doing 2 requests a second for each (disconsidering network latency), I could try 12 different bytes at a time.
Now the amount of time needed to recover the encrypted data decreated to 1/12 of what it would normally take. This doesn’t look that impressive, but it means the difference between recovering the plaintext in 10 minutes instead of 2 hours :).
In the end, there was no sensitive information present in the decrypted data and I couldn’t find a way to escalate the severity of this attack, so my report was marked as informative, since there was no real impact as a result of this vulnerability. :(
Anyway, this was an interesting bug to exploit and allowed me to learn something new, so it was not a complete waste of time.