WordPress is ubiquitous. It powers roughly 43% of websites on the Internet (Source). As security consultants, it is vital that we know the potential attacks that can be performed against it. The most dangerous of these attacks is code execution, which can be performed after obtaining WordPress administrator credentials. The usual process of achieving this can be rather laborious.  

Generally, the steps are as follows: 

  1. Log into the administrative interface at /wp-admin. 
  2. Click “Plugins”. 
  3. Click “Add New”. 
  4. Click “Upload Plugin” 
  5. Click “Browse” and select the PHP file you wish to execute. 
  6. Click “Install Now”. 
  7. Locate the uploaded file at /wp-content/uploads/[current year]/[current month]/[file name] and browse to it or call it with cURL. 

There have been previous attempts to automate this process. For example, Metasploit has the “exploit/unix/webapp/wp_admin_shell_upload” module. However, this module isn’t very reliable (in my experience) and requires quite a few steps to configure. Furthermore, attack signatures have been developed to detect it. 

Using an intercepting proxy to look at the requests that WordPress uses to facilitate the upload, it is clear that you only need three calls to make it happen: one for the session cookie, one for the nonce, and one for the upload. Add one more to the file itself and you’ve got execution!  

After getting a better understanding of this process, I became interested in creating a script to automate the process. I had been working on a HackTheBox lab that required this technique as a first step into the network and I didn’t want to go through it manually every time. I started throwing in a couple of convenience features and other niceties and eventually the little script turned into something a bit closer to a full-fledged exploitation tool.

Wopper is an easy-to-use webshell uploader with an emphasis on speed and stealth. Its name stands for “WordPress Privilege Escalation Rapidly”. 

With valid admin credentials, you can use Wopper to do the following things: 

  • Upload PHP files 
  • Execute PHP files 
  • Delete PHP files 
  • Obfuscate PHP files 
  • Convert other PHP files to be self-destructing 
  • Convert Linux shell commands into self-destructing PHP files 
  • Any combination of the above 

All of these things can be done in a single command depending on which options you specify. An obfuscated PHP file can be created, uploaded, executed, and deleted in seconds while any long-running commands launched by it will survive in the background. Not only are self-destructing PHP droppers more efficient and harder to detect, they’re also more fun! 

Default Mode 

The default mode of operation simply uploads and, optionally, executes a PHP file. This mode is useful if you want to upload a persistent webshell like Weevely. It will also come in handy to execute custom scripts or scripts that Wopper has created and saved previously. This test file will simply log some basic host information to a text file in the same directory. 

Test File #1: 

<?php system('uname -a > test.txt'); ?> 

The testing environment used in this article has the WordPress root directory path set to /wordpress. This path must be present in the URL when running Wopper and can be determined by checking if any directories come before /wp-login.php on the target site. Wopper should handle most URLs quite well. They can include ports, trailing slashes, or neither, as well as http or https. 

The site being tested is a current CTF challenge, so the username and password are substituted using shell variables in this article to avoid spoilers. The only other option required is -f. This option is used in most other modes and specifies the file to use as input, or in this case, the file to upload.

Wopper will return status messages indicating whether the upload, execution, and/or deletion of a file has succeeded. If the Default Mode is used, the location of the uploaded file will be returned. Using w3m, a text-based web browser, the upload can be confirmed by browsing to the returned URL. 

For the demonstration purposes, the rest of the commands have been prefixed with the “time” utility in order to show how long Wopper takes to execute. The “real” time is the one that matters here. Between each upload, we’ll run this command to reset the upload directory. See the Command Mode section for more information about the -c flag. 

Default Mode also allows the -x flag, which specifies that the uploaded file be executed. If you want to automatically upload and execute a file without deleting it, use this command. 

Scrub Mode

Scrub Mode is one of three ways that Wopper implements automatic deletion. Scrub does this by uploading and executing a second file which runs “rm -f $file scrub.php”, where $file is the name of the first file given by the -f flag. This ensures that both files are deleted without having to perform any modifications on the original file. Additionally, the -t flag can be used to set a timeout on execution and the -v flag (verify) can be used in the Scrub, Inject, and Command modes to double check that the file was deleted. If the script is still running and the timeout hasn’t passed, Wopper will wait. Deleting the script at this point would prevent creation of the text file.

Test File #2:

<?php system('sleep 30 && uname -a > test.txt'); ?> 

Checking the upload directory shows that the file is still present at this point. 

After roughly 30 seconds, Wopper will confirm deletion and the upload directory will now contain only the resulting text file, as both the timeout and the sleep command have finished.

Inject Mode

Inject Mode allows the user to add self-destruction capabilities to an existing PHP file by Base64-encoding it and injecting it into a self-deleting wrapper script. This has the pleasant side effect of adding a bit of obfuscation to the original script. 

Converting Files with Inject Mode: 

cat test.php  

<?php system('sleep 30 && uname -a > test.txt'); ?>  

wopper -f test.php -i wrapper.php  

cat wrapper.php  

<?php $cmd = 'og=$(echo c3lzdGVtKCdzbGVlcCAzMCAmJiB1bmFtZSAtYSA+IHRlc3QudHh0Jyk7Cg== | base64 -d); nohup php -r "$og" > /dev/null 2>&1 & rm -f wrapper.php'; exec("$cmd"); ?> 

An additional layer is provided by the -o flag (Obfuscation Mode), which currently just randomizes variable names. 

Using Obfuscation Mode: 

wopper -f wrapper.php -o  

cat wrapper.php  

<?php $4UtQr = 'JBc9P=$(echo c3lzdGVtKCdzbGVlcCAzMCAmJiB1bmFtZSAtYSA+IHRlc3QudHh0Jyk7Cg== | base64 -d); nohup php -r "$JBc9P" > /dev/null 2>&1 & rm -f wrapper.php'; exec("$4UtQr"); ?> 

In Inject Mode, no timeout is required for long-running commands, which will execute in the background and survive deletion. 

The uploaded file will delete itself immediately and the resulting text file will still appear after 30 seconds. 

Inject Mode can generate, upload, and execute a file in one command when a URL is given. 

Command Mode

One of the most useful modes is Command Mode. This mode will generate a self-destructing PHP file containing a chosen Linux shell command or even a whole script, as long as it’s all in one line. As shown in the Default Mode section, it can generate, upload, and execute a file with one command, just like Inject Mode. To see what the payloads look like, a local file can be generated with: 

wopper –c 'sleep 30 && whoami > whoami.txt' cmd.php 

And the resulting code will be: 

<?php exec("echo c2xlZXAgMzAgJiYgd2hvYW1pID4gd2hvYW1pLnR4dAo= | base64 -d | nohup sh > /dev/null 2>&1 & rm -f cmd.php"); ?> 

The generated file can then be uploaded and executed as before. 

Like Inject Mode, the provided commands will execute in the background and survive deletion. The ephemeral PHP file exists for a fraction of a second and the text file is still created long after it’s gone. This mode is perfect for dropper payloads that need some time to complete staging.

Usage notes for all of these modes can be viewed simply by running wopper without any arguments. 

Tool/Attack Detection Guidance 

To help the defenders, we’ve included some detection guidance for Wopper. 

Detection Opportunity #1: Default User-Agent header 

Data Source: Web server access log
Detection Strategy: Behavior
Detection Concept: Using the web server’s access log, detect on when the following User-Agent header: Wopper by NetSPI
Detection Reasoning: A threat actor may attempt to use Wopper without modifying the User-Agent header. This header has been set to an obvious default value to give defenders a head start.
Known Detection Consideration: Note that because the User-Agent header is easily modifiable, this should not be used as the sole means of detection. 

Detection Opportunity #2: File Creation 

Data Source: Filesystem events
Detection Strategy: Behavior
Detection Concept: On default WordPress configurations, Wopper will create files at /wp-content/uploads/[current year]/[current month]. Monitoring the creation of PHP files could be an effective strategy.
Detection Reasoning: Wopper must create a PHP file on the target filesystem in order to execute it.
Known Detection Consideration: It would be possible for attackers to modify Wopper to use file extensions other than .php, so this should be taken into account. The following grep command, for example, will match PHP files with the the extensions .php, .phps, .php0-9, .phtml, and .phar. 

grep -Ei '\.ph(p[0-9s]?|tml|ar)\b' 

Detection Opportunity #3: Process Creation 

Data Source: Process lists
Detection Strategy: Behavior
Detection Concept: In Command Mode, Wopper will run the specified commands under a new sh process. This sh process will be the child process of the web server process, such as apache2, httpd, or nginx.
Detection Reasoning: Monitoring for this relationship can detect Wopper, as it is anomalous for sh to be spawned by a web server process.
Known Detection Consideration: Other child shell processes, such as bash or zsh, should also be watched for. 

Detection Opportunity #4: Successful requests to /wp-admin/update.php 

Data Source: Web server access log
Detection Strategy: Behavior
Detection Concept: Wopper will make a request to /wp-admin/update.php?action=upload-plugin when uploading a PHP file. This request is likely uncommon on most installations and should therefore be easy to spot in the access log.
Detection Reasoning: This method would be very reliable, as a successful request to this endpoint is necessary for Wopper to execute code.
Known Detection Consideration: /wp-admin/update.php?action=upload-theme would function the same way and could easily be substituted for the upload-plugin action. Furthermore, care should be taken to avoid false positives when legitimate plugin installations are planned. 

Conclusion 

I like to imagine that Wopper could become more of a general webshell toolkit than a WordPress-specific exploit script over time. It would just be a matter of collecting the right requests for curl and adding the right logic for the operating system, framework, and programming language being targeted. Of course, we’d have to rename it at that point! Improvements could certainly be made to the obfuscation capabilities as well. Maybe an option to backdoor WordPress theme files instead of uploading files could be added. I also think that Wopper could make a good template for other web-based exploit scripts. Feel free to take it apart and use whatever bits work for your project!