As a pentester is quite usual that for several reasons one might not find as many shiny beautiful critical bugs as one might want to. Some pentests entail just lousy apps wrote by security savvy developers which laugh at our faces as we desperately try to avoid the worst sin a pentester might do: An empty report.
TL;DR: They were using RandomStringUtils to generate password reset tokens. That library uses by default Random() in Java which is kept across the server instance. Used my own password reset token to gain cryptographic information, cracked the internal state and reset the administrator’s password. Below you can get the code I used. Of course if you keep reading, you get a free 0day…
The rule number one of pentesting: To never give in an empty report, no matter how small the scope is, no matter how perfect that app is, no matter how updated every single framework is. When stuff like that happens, we have to resort to ugly tactics such as reporting old SSL versions, useless information disclosures on error messages and other “chamuyo” as we say in argentinian slang (A close translation would be ‘bollocks’).
This time, I decided to take a bug I would usually report as “Insecure randomness” low rating bug, and make it a critical.
Now about this gig I was on, the scope was pretty small, a Java based login page with a bit of functionality inside; started doing the usual, grepping the code for usual keywords, doing some empirical testing on a few endpoints, throwing Burp’s active scan :).
During one of the greps, I saw that the app had a password reset feature, saw that they were using java’s RandomStringUtils to generate password reset tokens and I got that spidey sense of “This can’t be right” that every pentester gets. I took a quick look at my calendar and I had a few days left on the gig so I thought I’d gave it a chance. I started analyzing how RandomStringUtils works to try to predict another user’s reset password, and pwn their accounts 🙂
Of course I can’t show the real client’s original code. Instead, I’m going to show a 0day vulnerability in a common open source application, which let’s you go from regular user to full admin. Enjoy!
And guess what, if you reset your own password, then quickly the admin’s password, the internal PRNG’s state won’t have advanced too much. Using the code I created, you can crack the state in around 30 to 60 minutes offline, and then try with Burp’s intruder or a Python script the tool’s output as a reset token for the admin. This uses just CPU, if someone wants to implement GPGPU for it, it’ll probably be a matter of seconds.
This is of course possible because when we take into account that RandomStringUtils uses as a default source of randomness the Java Random class, which uses a non-cryptographically secure PRNG called a Linear Congruential Generator
So, to finish this post: POC | GTFO