Social Media
Challenge
A social app with a password reset. The flag is reachable by taking over the admin account. The token generator is the whole challenge.
| |
Every reset token, including the admin’s, comes from one shared java.util.Random. That generator is a 48-bit linear congruential PRNG, and here it is seeded from only 40 bits (urandom(5)). RandomStringUtils.random just pulls from it, so the tokens are a predictable stream.
Approach
RandomStringUtils.random(20, 0, 0, true, true, ...) rejection-samples bytes in [32, 122] and keeps letters and digits. Because the generator is shared and never reseeded, any tokens I can observe are consecutive draws from the same sequence. Recover the internal state from a couple of known outputs and you can roll forward to whatever token the server hands out next, which includes the admin reset token.
The recovery is a search over the LCG state matched against observed characters. The C cracker reproduces java.util.Random.
| |
The Java helper does the same with the real library to confirm a recovered seed reproduces the token stream.
| |
Solution
Trigger resets to collect tokens you are allowed to see, feed them to the cracker to recover the PRNG state, then advance the sequence to predict the admin’s reset token. Submit that token to /do_reset for the admin email, which sets the password and drops you into the admin session with flag access.
We were the only team to solve this during the competition!