WordCamp London 2019 - CLI Tools and Shells


WordCamp London (WCLDN) was held at the London Metropolitan University on 5th - 7th April 2019. The first day was to promote contributing to the WordPress project, followed by a two day conference. I attended both days of the conference.

The conference was comprised of three tracks which ran in parallel, each with talks lasting approximately 40 mins. I went to several talks over the two days and was very impressed with the quality of content and how well organised the event was.

I thought it would be interesting to take a look at some of the command line tools and shells that were referenced in the talks that I attended. This is not intended to be a deep dive but rather a brief summary of each tool/shell based on what I learnt at the conference and any hands-on experience I’ve gained since then.

CLI Tools and Shells

WPScan and WordPress Exploit Framework (wpxf)

These tools are not related but compliment each other, hence why I’ve grouped them. WPScan checks for the presence of vulnerabilities and WordPress Exploit Framework exploits them.

WPScan is written in Ruby, it attempts to discover things such as the WordPress version and details of any installed plugins and themes. WordPress Exploit Framework is also written in Ruby, it is a framework for demonstrating exploits of known vulnerabilities, the purpose of which is to assist with penetration testing. Neither tool has to be run from the server on which a target WordPress site resides, they can both be run from anywhere.

I wanted to use both tools in conjunction to achieve the following workflow:

  1. Use WPScan to detect vulnerabilities in plugins.
  2. Search WordPress Exploit Framework for modules capable of exploiting the vulnerabilities discovered with WPScan.
  3. Use WordPress Exploit Framework to exploit the vulnerabilities where modules exist to do so.

NB: I never actually got to try step three because I didn’t have a WordPress site available to me with a vulnerability that was exploitable by the WordPress Exploit Framework. I’d like to explore the WordPress Exploit Framework in more depth in the future, what I really need is a sandboxed environment with an old version of WordPress installed and/or some old plugins.

These are just a few notes detailing how I went about achieving step two of the workflow…

The maintainers of WPScan (The WPScan Team) catalogue vulnerabilities found in WordPress core, plugins and themes in the WPScan Vulnerability Database. Each vulnerability recorded in the database has a unique ID. The default console output produced by WPScan includes the vulnerability name as recorded in the database but not the ID, however there is an option to output in JSON format which includes both the name and ID.

My plan was to extract the ID from WPScan for each vulnerability found and use this to search the WordPress Exploit Framework for modules capable of exploiting the vulnerability. I used PowerShell Core (6.2.0) to parse the JSON output. In the following example only one plugin was found to be susceptible to a vulnerability, PowerShell extracts the vulnerability ID, vulnerability name and the version of the plugin in which the vulnerability was addressed:

wpscan --url www.example.com --format=json --output ~/wpscan-www.example.com.json

$file = Get-Content ./wpscan-www.example.com.json | ConvertFrom-Json
$file.plugins | foreach-object {$_.psobject.properties.value.vulnerabilities | 
select-object @{Name='wpvdb_id'; Expression={$_.references.wpvulndb}}, @{Name='wpvdb_vulnerability_name'; Expression={$_.title}}, fixed_in}

wpvdb_id wpvdb_vulnerability_name                                                 fixed_in
-------- ------------------------                                                 --------
7652     Creative Contact Form <= 0.9.7 Shell Upload                              1.0.0 

It was my hope that the WordPress Exploit Framework could be searched using the WPScan Vulnerability Database ID but alas its search facility does not support this (I’ve opened an issue). However, there is another way… Behind the scenes each exploit module in the WordPress Exploit Framework is a separate Ruby file. These usually (the project’s wiki, says it’s not a mandatory requirement) contain the relevant WPScan Vulnerability Database ID (WPVDB) within the references section, EG:

references: [ 
       ['EDB', '35057'], 
       ['WPVDB', '7652'] 

The directory containing the exploit modules can be searched using a combination of grep and sed. In order to do this, you must first obtain the installation directory of the WordPress Exploit Framework. If you used the gem package manager to perform the installation then this can be achieved as follows:

gem environment 2>/dev/null | grep "\- INSTALLATION DIRECTORY:" | tr -d '[:space:]' | cut -d: -f2 | xargs -i sh -c 'ls -d1 {}/gems/wpxf*'

Once in possession of the installation directory, you can search it for modules containing a specific WPScan Vulnerability Database ID. The following example demonstrates a search for modules containing ID 7652, a single result is returned in the form of the module name Creative Contact Form Shell Upload:
(NB: In my case the WordPress Exploit Framework directory was /var/lib/gems/2.5.0/gems/wpxf-2.0.1, so that’s what I’ve used in the example.)

cd /var/lib/gems/2.5.0/gems/wpxf-2.0.1/lib/wpxf/modules/exploit
sudo grep -r -l "\['WPVDB'.*'7652'.*\]" ./ | xargs grep -m 1 "name:" | sed -e "s,[^']*'\(.*\)'.*,\1,"

Creative Contact Form Shell Upload


sqlmap is a penetration tool intended to detect and exploit SQL injection flaws.

I installed sqlmap by cloning the project’s dev branch on Github (as per the instructions on the project’s website). I was somewhat surprised that the script failed to execute under Python 3:

[21:39:32] [CRITICAL] incompatible Python version detected ('3.6.7'). To successfully run sqlmap you'll have to use version 2.6.x or 2.7.x (visit 'https://www.python.org/downloads/')

I did a quick search of the project’s Github repo expecting to find a Python 2 to Python 3 roadmap (Python 2’s End Of Life date is 2020-01-01) but instead I found this which suggests that there is no intention to provide support for Python 3. Anyway, I digress, the bottom line is you need to use Python 2.

After dabbling with sqlmap for a bit it became apparent that in order to gain familiarity with it I really needed a sandboxed site with known SQL injection vulnerabilities… I found two such candidates, bWAPP (buggy web application) and WebGoat which appears to be more actively maintained. Time permitting I’d like to return to sqlmap at a later date and try it against one of the aforementioned frameworks.


nghttp is an HTTP/2 command-line client, it is part of the nghttp2 suite of tools which is produced by the nghttp2.org project.

During Tom J Nowell’s talk entitled HTTP/2 Push for the Stars, he explained how the HTTP/2 Server Push technique can be used to send website assets to the user without waiting for the browser to request them. He went on to discuss a couple of ways in which HTTP/2 Server Push can be tested, one of which was using nghttp. The output of nghttp lists all requested resources and indicates which of those were pushed using an asterisk, he used his own website as an example:

$ nghttp -ans https://tomjn.com

***** Statistics *****

Request timing:
  responseEnd: the  time  when  last  byte of  response  was  received
               relative to connectEnd
 requestStart: the time  just before  first byte  of request  was sent
               relative  to connectEnd.   If  '*' is  shown, this  was
               pushed by server.
      process: responseEnd - requestStart
         code: HTTP status code
         size: number  of  bytes  received as  response  body  without
          URI: request URI

see http://www.w3.org/TR/resource-timing/#processing-model

sorted by 'complete'

id  responseEnd requestStart  process code size request path
  2   +188.81ms *  +149.53ms  39.28ms  200  33K /wp-includes/js/jquery/jquery.js?ver=1.12.4
  4   +190.15ms *  +149.73ms  40.42ms  200   3K /wp-includes/js/jquery/jquery-migrate.min.js?ver=1.4.1
  6   +190.64ms *  +149.76ms  40.87ms  200   3K /wp-content/uploads/2016/11/favicon.png
  8   +195.62ms *  +149.79ms  45.83ms  200   4K /wp-includes/js/wp-emoji-release.min.js?ver=5.1.1
 10   +196.09ms *  +149.82ms  46.27ms  200  753 /wp-includes/js/wp-embed.min.js?ver=5.1.1
 12   +196.46ms *  +149.85ms  46.61ms  200  639 /wp-content/plugins/jetpack/_inc/build/widgets/milestone/milestone.min.js?ver=20160520
 14   +198.00ms *  +149.88ms  48.12ms  200   4K /wp-includes/css/dist/block-library/style.min.css?ver=5.1.1
 13   +226.16ms       +790us 225.37ms  200   2K /
 16   +228.17ms *  +149.96ms  78.21ms  200  14K /wp-content/themes/tomjn/style.css?ver=5
 18   +247.23ms *  +150.21ms  97.02ms  200  27K /wp-includes/css/dashicons.min.css?ver=5.1.1

NB: The argument in the command above -ans is an amalgamation of three short arguments, -a, -n and -s. See the man page for an explanation of each (man nghttp).

When working with HTTP/2 you may encounter the abbreviations h2 and h2c. h2 is HTTP/2 over TLS and h2c is HTTP/2 over cleartext TCP. These are identifiers as specified in the protocol’s RFC. Browsers typically only support h2.

Firefox Web Developer Tools - Console

Although I’d used Firefox’s Web Developer tools (F12) many times, I’d never used its Console feature before. It is an interactive JavaScript console, into which you can enter JavaScript such as:

>> 1+2
<- 3
>> prompt('Give me a number');
<- "5"

PHP Interactive Shell

PHP ships with an interactive shell which is accessed using the -a parameter, EG: php -a.

This enables you to type PHP code, execute it and output the result, well, kind of… It doesn’t actually output anything to the console unless you prefix your code with echo, EG:

php > $name = "The CLI Guy";
php > echo "Hello $name";
Hello The CLI Guy


PsySH is like PHP’s native interactive shell with knobs on. It provides a read-eval-print loop (REPL), so there’s no need to prefix your PHP with echo in order to see the result, EG:

>>> $name = "The CLI Guy"
=> "The CLI Guy"
>>> "Hello $name"
=> "Hello The CLI Guy"

Furthermore, the more observant amongst you may have noticed that there’s no need to terminate each line with a semicolon.

3v4l.org - Online PHP Shell

3v4l.org is an online PHP shell which enables you to execute PHP code against any version of PHP released since 4.3.0. It also acts as a pastebin, once you press the eval(); button the browser’s address bar is populated with a unique link. I couldn’t find anything on the About page to indicate if these links were subject to a retention period (EG deleted after n days). I wrote to the author to ask if there was a retention period to which he replied there is not.

There is also an interactive shell, which at the time of writing (April 2019) uses PHP 7.3.0. The interactive shell is currently labelled as ‘beta’, it was only released in December 2018.


WP-CLI is the official command line interface for WordPress.

It’s possible to perform a complete installation of WordPress from the command line with the assistance of WP-CLI. These are the basic steps only, if deploying a publicly accessible WordPress site then always follow current best practices and security hardening steps. Some of the commands below require user interaction, so this snippet is not intended to be used in a non-interactive fashion.

# Download WP-CLI
wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar

# Make WP-CLI executable
chmod +x wp-cli.phar

# Move to an appropriate directory within PATH
sudo mv wp-cli.phar /usr/local/bin/wp

# Confirm WP-CLI is working
wp --info

# Download the latest WordPress version
mkdir ~/WP
cd ~/WP
wp core download

# Create WordPress database and user
mysql -uroot -p
CREATE USER 'wptestuser'@'localhost' IDENTIFIED BY 'foobar';
GRANT ALL PRIVILEGES ON wptestdb.* TO 'wptestuser'@'localhost';

# Create a wp-config file
wp config create --dbname=wptestdb --dbuser=wptestuser --prompt=dbpass

# Install WordPress - Creates the WordPress tables in the database using the 
# URL, title, and admin credentials details provided.
wp core install --url=example.com --title=Example --admin_user=supervisor --admin_email=info@example.com --prompt=admin_password --skip-email

A few notes about the above…
It was my intention to handle password input so that is was not captured in clear text in either the bash history log (~/bash_history) or MySQL history log (~/mysql_history).

The last thing I want to mention about WP-CLI is its interactive REPL PHP console: wp shell. As well as executing general PHP code, you can interact with the WordPress environment. For example you can call global WordPress functions:

wp> get_bloginfo();
=> string(7) "Example"
wp> site_url();
=> string(18) "http://example.com"
wp> wp_max_upload_size();
=> int(2097152)

Further Reading

The table below lists the talks I attended which inspired this blog post, it includes links to the tools as well as to the respective speakers websites.

Talk Speaker Tools Mentioned
Going To The Dark Side, They Have Cookies Tim Nash WPScan, WordPress Exploit Framework, sqlmap
HTTP/2 Push for the Stars Tom J Nowell nghttp
An Introduction to WP-CLI Pascal Birchler WP-CLI
I Tried Writing Some Code... You Won't Believe What Happened Next! Ross Wintle Firefox Web Developer Tools - Console, PHP Interactive Shell, PsySH, 3v4l.org, WP-CLI


Leaving comments has been disabled for this post.

Copyright © 2018 - 2022 thecliguy.co.uk
For details, see Licences and Copyright