WordPress, Bad Guys, and You

Mark Montague

mark@catseye.org

Many slides have notes with extra material:

This presentation is available at
http://www-personal.umich.edu/~markmont/wby/

A copy of this presentation can be downloaded from
http://www-personal.umich.edu/~markmont/wby.zip

Who I am

Who I am NOT


This presentation could be much scarier if done by either a security expert or a bad guy.

Both security experts and bad guys will have much more time and focus than a generalist such as I am.

Bad guys have access to malware, including very sophisticated toolkits to compromise web sites, "black hat" forums, and more. Toolkits and exploits are routinely bought and sold for Bitcoin or dollars on black market sites.

This presentation uses only "good guy tools" because I don't want to use untrustworthy software or wind up on a law enforcement agency's lists.

Demonstration - the target

http://myblog.catseye.org/ Screenshot of the blog we will be attacking

Demonstration - the target

Everything was set up according to the instructions at wordpress.org and ubuntu.com. The only extra things that were done were:

If WordPress is left at it's default — comments only appear if the commenter has a previously approved comment — the attack will still work: we just submit a legitimate comment first, wait for it to be approved, and then launch the attack.

We're using Ubuntu Server LTS because it is the most popular choice for people who run their own server.

Demonstration - the attacker

badguy.catseye.org

Screen shot from the Kali Linux web page

We're using the latest release: Kali Linux 1.0.6, which is based on Debian 7 "Wheezy".

Demonstration - the attacker

Kali Linux, http://www.kali.org/

Instead of using Kali Linux, we could just download and install WPScan and Metasploit. This requires only a tiny bit more technical knowledge than using Kali Linux, plus a bit more configuration work, and is very do-able. We're just being extra lazy.

Demonstration - WPScan

To find out how to use WPScan, run it with the --help option:

root@badguy:~# wpscan --help
_______________________________________________________________
        __          _______   _____                  
        \ \        / /  __ \ / ____|                 
         \ \  /\  / /| |__) | (___   ___  __ _ _ __  
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \ 
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team 
                        Version v2.2
     Sponsored by the RandomStorm Open Source Initiative
 @_WPScan_, @ethicalhack3r, @erwan_lr, @gbrindisi, @_FireFart_
_______________________________________________________________

Help :

Some values are settable in conf/browser.conf.json :
  user-agent, proxy, proxy-auth, threads, cache timeout and request timeout

--update   Update to the latest revision
--url   | -u <target url>  The WordPress URL/domain to scan.
--force | -f Forces WPScan to not check if the remote site is running WordPress.
--enumerate | -e [option(s)]  Enumeration.
  option :
    u        usernames from id 1 to 10
    u[10-20] usernames from id 10 to 20 (you must write [] chars)
    p        plugins
    vp       only vulnerable plugins
    ap       all plugins (can take a long time)
    tt       timthumbs
    t        themes
    vt       only vulnerable themes
    at       all themes (can take a long time)
  Multiple values are allowed : "-e tt,p" will enumerate timthumbs and plugins
  If no option is supplied, the default is "vt,tt,u,vp"

--exclude-content-based "<regexp or string>" Used with the enumeration option, will exclude all occurrences based on the regexp or string supplied
                                             You do not need to provide the regexp delimiters, but you must write the quotes (simple or double)
--config-file | -c <config file> Use the specified config file
--follow-redirection  If the target url has a redirection, it will be followed without asking if you wanted to do so or not
--wp-content-dir <wp content dir>  WPScan try to find the content directory (ie wp-content) by scanning the index page, however you can specified it. Subdirectories are allowed
--wp-plugins-dir <wp plugins dir>  Same thing than --wp-content-dir but for the plugins directory. If not supplied, WPScan will use wp-content-dir/plugins. Subdirectories are allowed
--proxy <[protocol://]host:port> Supply a proxy (will override the one from conf/browser.conf.json).
                                 HTTP, SOCKS4 SOCKS4A and SOCKS5 are supported. If no protocol is given (format host:port), HTTP will be used
--proxy-auth <username:password>  Supply the proxy login credentials (will override the one from conf/browser.conf.json).
--basic-auth <username:password>  Set the HTTP Basic authentication
--wordlist | -w <wordlist>  Supply a wordlist for the password bruter and do the brute.
--threads  | -t <number of threads>  The number of threads to use when multi-threading requests. (will override the value from conf/browser.conf.json)
--username | -U <username>  Only brute force the supplied username.
--help     | -h This help screen.
--verbose  | -v Verbose output.


Examples :

-Further help ...
ruby ./wpscan.rb --help

-Do 'non-intrusive' checks ...
ruby ./wpscan.rb --url www.example.com

-Do wordlist password brute force on enumerated users using 50 threads ...
ruby ./wpscan.rb --url www.example.com --wordlist darkc0de.lst --threads 50

-Do wordlist password brute force on the 'admin' username only ...
ruby ./wpscan.rb --url www.example.com --wordlist darkc0de.lst --username admin

-Enumerate installed plugins ...
ruby ./wpscan.rb --url www.example.com --enumerate p

-Enumerate installed themes ...
ruby ./wpscan.rb --url www.example.com --enumerate t

-Enumerate users ...
ruby ./wpscan.rb --url www.example.com --enumerate u

-Enumerate installed timthumbs ...
ruby ./wpscan.rb --url www.example.com --enumerate tt

-Use a HTTP proxy ...
ruby ./wpscan.rb --url www.example.com --proxy 127.0.0.1:8118

-Use a SOCKS5 proxy ... (cURL >= v7.21.7 needed)
ruby ./wpscan.rb --url www.example.com --proxy socks5://127.0.0.1:9000

-Use custom content directory ...
ruby ./wpscan.rb -u www.example.com --wp-content-dir custom-content

-Use custom plugins directory ...
ruby ./wpscan.rb -u www.example.com --wp-plugins-dir wp-content/custom-plugins

-Update ...
ruby ./wpscan.rb --update

-Debug output ...
ruby ./wpscan.rb --url www.example.com --debug-output 2>debug.log

See README for further information.

Exiting!
root@badguy:~#


Demonstration - WPScan

Let's look at http://arc.research.umich.edu/

root@badguy:~# wpscan --url arc.research.umich.edu
_______________________________________________________________
        __          _______   _____                  
        \ \        / /  __ \ / ____|                 
         \ \  /\  / /| |__) | (___   ___  __ _ _ __  
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \ 
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team 
                        Version v2.2
     Sponsored by the RandomStorm Open Source Initiative
 @_WPScan_, @ethicalhack3r, @erwan_lr, @gbrindisi, @_FireFart_
_______________________________________________________________

| URL: http://arc.research.umich.edu/
| Started: Sat Jan 25 17:24:11 2014

[+] robots.txt available under: 'http://arc.research.umich.edu/robots.txt'
[!] The WordPress 'http://arc.research.umich.edu/readme.html' file exists
[+] Interesting header: SERVER: Apache
[+] XML-RPC Interface available under: http://arc.research.umich.edu/xmlrpc.php
[+] WordPress version 3.5.1 identified from meta generator

[!] 8 vulnerabilities identified from the version number:
 |
 | * Title: Wordpress 3.4 - 3.5.1 /wp-admin/users.php Malformed s Parameter Path Disclosure
 | * Reference: http://seclists.org/fulldisclosure/2013/Jul/70
 | * Reference: http://osvdb.org/95060
 | * Fixed in: 3.5.2
 |
 | * Title: WordPress 3.4 - 3.5.1 DoS in class-phpass.php
 | * Reference: http://seclists.org/fulldisclosure/2013/Jun/65
 | * Reference: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-2173
 | * Reference: http://secunia.com/advisories/53676
 | * Reference: http://osvdb.org/94235
 |
 | * Title: WordPress Multiple XSS
 | * Reference: http://osvdb.org/94791
 | * Reference: http://osvdb.org/94785
 | * Reference: http://osvdb.org/94786
 | * Reference: http://osvdb.org/94790
 |
 | * Title: WordPress TinyMCE Plugin Flash Applet Unspecified Spoofing Weakness
 | * Reference: http://osvdb.org/94787
 |
 | * Title: WordPress File Upload Unspecified Path Disclosure
 | * Reference: http://osvdb.org/94788
 |
 | * Title: WordPress oEmbed Unspecified XML External Entity (XXE) Arbitrary File Disclosure
 | * Reference: http://osvdb.org/94789
 |
 | * Title: WordPress Multiple Role Remote Privilege Escalation
 | * Reference: http://osvdb.org/94783
 |
 | * Title: WordPress HTTP API Unspecified Server Side Request Forgery (SSRF)
 | * Reference: http://osvdb.org/94784

[+] WordPress theme in use: orci

 | Name: orci
 | Location: http://arc.research.umich.edu/wp-content/themes/orci/
 | Directory listing enabled: Yes

[+] Enumerating plugins from passive detection ... 
 |  6 plugins found:

 | Name: jquery-collapse-o-matic v1.5.1
 | Location: http://arc.research.umich.edu/wp-content/plugins/jquery-collapse-o-matic/
 | Directory listing enabled: Yes
 | Readme: http://arc.research.umich.edu/wp-content/plugins/jquery-collapse-o-matic/readme.txt

 | Name: jquery-colorbox v4.6
 | Location: http://arc.research.umich.edu/wp-content/plugins/jquery-colorbox/
 | Directory listing enabled: Yes
 | Readme: http://arc.research.umich.edu/wp-content/plugins/jquery-colorbox/readme.txt

 | Name: mailchimp v1.2.14
 | Location: http://arc.research.umich.edu/wp-content/plugins/mailchimp/
 | Directory listing enabled: Yes
 | Readme: http://arc.research.umich.edu/wp-content/plugins/mailchimp/readme.txt

 | Name: page-list v4.2
 | Location: http://arc.research.umich.edu/wp-content/plugins/page-list/
 | Directory listing enabled: Yes
 | Readme: http://arc.research.umich.edu/wp-content/plugins/page-list/readme.txt

 | Name: wp-paginate v1.2.4
 | Location: http://arc.research.umich.edu/wp-content/plugins/wp-paginate/
 | Directory listing enabled: Yes
 | Readme: http://arc.research.umich.edu/wp-content/plugins/wp-paginate/readme.txt

 | Name: youtube-shortcode v1.8.5
 | Location: http://arc.research.umich.edu/wp-content/plugins/youtube-shortcode/
 | Directory listing enabled: Yes
 | Readme: http://arc.research.umich.edu/wp-content/plugins/youtube-shortcode/readme.txt

[+] Finished: Sat Jan 25 17:24:52 2014
[+] Memory used: 5.039 MB
[+] Elapsed time: 00:00:41
Exiting!
root@badguy:~# 


This is a WordPress site I use a lot at work.

WPScan can tell that the server runs Apache, but not what version.

Despite the #1 thing for keeping people from breaking into your site being to always keep up-to-date with the latest versions of everything, this site is still running WordPress 3.5.1. That's very bad; unfortunately, it's not uncommon.

WPScan found eight security vulnerabilities. Many are probably not anything that would be useful to the casual attacker, but some might be. Read the details at each of the reference URLs that WPScan provides to find out more.

WPScan found one theme ("orci"), and six plugins. There are likely more which could be found by running WPScan with an exhaustive plugin search ("wpscan --enumerate ap").

Demonstration - WPScan

Now our site, http://wordpressannarbor.com/

root@badguy:~# wpscan --url wordpressannarbor.com
_______________________________________________________________
        __          _______   _____                  
        \ \        / /  __ \ / ____|                 
         \ \  /\  / /| |__) | (___   ___  __ _ _ __  
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \ 
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team 
                        Version v2.2
     Sponsored by the RandomStorm Open Source Initiative
 @_WPScan_, @ethicalhack3r, @erwan_lr, @gbrindisi, @_FireFart_
_______________________________________________________________

The plugins directory 'wp-content/plugins' does not exist.
You can specify one per command line option (don't forget to include the wp-content directory if needed)
Continue? [y/n] n
Exiting!
root@badguy:~#   # Hmm, let's pull up http://wordpressannarbor.com/ in a
root@badguy:~#   # web browser and view the page's HTML source.  Near the
root@badguy:~#   # top, we see that some things are under a directory named
root@badguy:~#   # 'wp'.  Let's run WPScan again and tell it that:
root@badguy:~# 
root@badguy:~# wpscan --wp-plugins-dir wp/wp-content/plugins --url wordpressannarbor.com
_______________________________________________________________
        __          _______   _____                  
        \ \        / /  __ \ / ____|                 
         \ \  /\  / /| |__) | (___   ___  __ _ _ __  
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \ 
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team 
                        Version v2.2
     Sponsored by the RandomStorm Open Source Initiative
 @_WPScan_, @ethicalhack3r, @erwan_lr, @gbrindisi, @_FireFart_
_______________________________________________________________

| URL: http://wordpressannarbor.com/
| Started: Sat Jan 25 17:28:46 2014

[+] robots.txt available under: 'http://wordpressannarbor.com/robots.txt'
[+] Interesting entry from robots.txt: /cgi-bin
[+] Interesting entry from robots.txt: /wp-admin
[+] Interesting entry from robots.txt: /wp-includes
[+] Interesting entry from robots.txt: /wp-content/plugins
[+] Interesting entry from robots.txt: /wp-content/cache
[+] Interesting entry from robots.txt: /wp-content/themes
[+] Interesting entry from robots.txt: /trackback
[+] Interesting entry from robots.txt: /comments
[+] Interesting entry from robots.txt: http://wordpressannarbor.com/wp-content/uploads
[+] Interesting header: LINK: <http://wp.me/2wcNs>; rel=shortlink
[+] Interesting header: SERVER: Apache
[+] Interesting header: SET-COOKIE: wooTracker=2H0UGV7DUT29; expires=Mon, 25-Jan-2016 22:28:57 GMT; path=/; domain=wordpressannarbor.com
[+] WordPress version 3.8.1 identified from meta generator

[+] WordPress theme in use: twentythirteen v1.1

 | Name: twentythirteen v1.1
 | Location: http://wordpressannarbor.com/wp-content/themes/twentythirteen/

[+] Enumerating plugins from passive detection ... 
 |  4 plugins found:

 | Name: advanced-recent-posts-widget v1.1a
 | Location: http://wordpressannarbor.com/wp/wp-content/plugins/advanced-recent-posts-widget/
 | Directory listing enabled: Yes
 | Readme: http://wordpressannarbor.com/wp/wp-content/plugins/advanced-recent-posts-widget/readme.txt

 | Name: jetpack v2.6
 | Location: http://wordpressannarbor.com/wp/wp-content/plugins/jetpack/
 | Directory listing enabled: Yes
 | Readme: http://wordpressannarbor.com/wp/wp-content/plugins/jetpack/readme.txt

 | Name: social-media-widget v4.0.2
 | Location: http://wordpressannarbor.com/wp/wp-content/plugins/social-media-widget/
 | Directory listing enabled: Yes
 | Readme: http://wordpressannarbor.com/wp/wp-content/plugins/social-media-widget/readme.txt

 | Name: w3-total-cache
 | Location: http://wordpressannarbor.com/wp/wp-content/plugins/w3-total-cache/
 |
 | * Title: W3 Total Cache - Username and Hash Extract
 | * Reference: http://seclists.org/fulldisclosure/2012/Dec/242
 | * Reference: https://github.com/FireFart/W3TotalCacheExploit
 | * Reference: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6079
 | * Reference: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6078
 | * Reference: http://osvdb.org/92742
 | * Reference: http://osvdb.org/92741
 | * Reference: http://www.metasploit.com/modules/auxiliary/gather/wp_w3_total_cache_hash_extract
 | * Fixed in: 0.9.2.5
 |
 | * Title: W3 Total Cache - Remote Code Execution
 | * Reference: http://www.acunetix.com/blog/web-security-zone/wp-plugins-remote-code-execution/
 | * Reference: http://wordpress.org/support/topic/pwn3d
 | * Reference: http://blog.sucuri.net/2013/04/update-wp-super-cache-and-w3tc-immediately-remote-code-execution-vulnerability-disclosed.html
 | * Reference: http://www.metasploit.com/modules/exploits/unix/webapp/php_wordpress_total_cache
 | * Fixed in: 0.9.2.9
 |
 | * Title: W3 Total Cache 0.9.2.9 - PHP Code Execution
 | * Reference: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-2010
 | * Reference: http://secunia.com/advisories/53052
 | * Reference: http://osvdb.org/92652
 | * Reference: http://www.exploit-db.com/exploits/25137/

[+] Finished: Sat Jan 25 17:29:20 2014
[+] Memory used: 4.379 MB
[+] Elapsed time: 00:00:33
Exiting!
root@badguy:~# 


Here is an example where we have to give WPScan a little extra help. But it's not hard — we just look at the HTML that the site sends our browser, figure out where the plugins reside (in wp/wp-content/plugins instead of wp-content/plugins) and run WPScan again with an extra command line option to tell it.

This site is running W3 Total Cache, but WPScan was not able to determine the version number (perhaps because someone deleted the plugin's readme.txt file, or disabled directory listing just for this one plugin?), so it's printing a list of potential security problems that could exist if the site is using an old version of the plugin. Let's hope it's not, since one of them is the same vulnerability we're planning on exploiting in a minute when we do our attack on http://myblog.catseye.org/.

Demonstration - WPScan

Finally, our intended target, http://myblog.catseye.org/

root@badguy:~# wpscan --url myblog.catseye.org
_______________________________________________________________
        __          _______   _____                  
        \ \        / /  __ \ / ____|                 
         \ \  /\  / /| |__) | (___   ___  __ _ _ __  
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \ 
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team 
                        Version v2.2
     Sponsored by the RandomStorm Open Source Initiative
 @_WPScan_, @ethicalhack3r, @erwan_lr, @gbrindisi, @_FireFart_
_______________________________________________________________

| URL: http://myblog.catseye.org/
| Started: Sat Jan 25 17:32:16 2014

[+] robots.txt available under: 'http://myblog.catseye.org/robots.txt'
[!] The WordPress 'http://myblog.catseye.org/readme.html' file exists
[+] Interesting header: SERVER: Apache/2.2.22 (Ubuntu)
[+] XML-RPC Interface available under: http://myblog.catseye.org/xmlrpc.php
[+] WordPress version 3.8.1 identified from meta generator

[+] Enumerating plugins from passive detection ... 
 |  1 plugins found:

 | Name: w3-total-cache v0.9.2.8
 | Location: http://myblog.catseye.org/wp-content/plugins/w3-total-cache/
 | Readme: http://myblog.catseye.org/wp-content/plugins/w3-total-cache/readme.txt
 |
| * Title: W3 Total Cache - Remote Code Execution | * Reference: http://www.acunetix.com/blog/web-security-zone/wp-plugins-remote-code-execution/ | * Reference: http://wordpress.org/support/topic/pwn3d | * Reference: http://blog.sucuri.net/2013/04/update-wp-super-cache-and-w3tc-immediately-remote-code-execution-vulnerability-disclosed.html | * Reference: http://www.metasploit.com/modules/exploits/unix/webapp/php_wordpress_total_cache | * Fixed in: 0.9.2.9 | | * Title: W3 Total Cache 0.9.2.9 - PHP Code Execution | * Reference: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-2010 | * Reference: http://secunia.com/advisories/53052 | * Reference: http://osvdb.org/92652 | * Reference: http://www.exploit-db.com/exploits/25137/
[+] Finished: Sat Jan 25 17:32:20 2014 [+] Memory used: 4.316 MB [+] Elapsed time: 00:00:04 Exiting! root@badguy:~#

WPScan was not only able to tell what web server software is being used, but also the version.

WPScan found the W3 Total Cache plugin, and, in this case (unlike the previous example) was able to determine (correctly) what version it is (likely because the plugin's readme.txt file is there and accessible). We'll make a note that this severe vulnerability exists for the site, and use that information in a little bit when we launch our attack.

Demonstration - Metasploit

http://www.metasploit.com/

Screen shot from the Metasploit website

Demonstration - Metasploit

Metasploit is available in four editions:

To run the Metasploit web interface under Kali Linux:

  service postgresql start
  service metasploit start

Then go to http://badguy.catseye.org:3790/

Everything we're doing in this presentation can work with Metasploit Framework or Metasploit Community. We have a 7 day trial license for the Pro edition, however, in case someone wants to see the additional functionality.

Demonstration - Metasploit

Basic steps:

  1. Create a Metasploit user account.
  2. Get a license key (Community, Express, Pro editions).

  3. Create a project.
  4. Do a discovery scan.
  5. Choose and run an exploit, breaking into the target's site.
  6. Do what you want to the target's site.

Steps 1 and 2 have already been done, we'll start with step 3.

A project is like a container that keeps track of systems that are being tested, and results of the tests.

The scan finds out what is available to be tested.

Demonstration - Metasploit

Metasploit web interface - main page:

Screenshot of the Metasploit web interface main page

This is the page a user gets after they create a Metasploit user account, request and enter a product key, and log in. The copy of Metasploit shown has been licensed with the 7 day free trial of the Pro edition, but the Community edition can do everything needed for this demonstration.

Click on the New Project button to begin.

Demonstration - Metasploit

Screenshot of the Metasploit web interface New Project page

Just enter a name for the project and either the networks or IP addresses you'll be testing and then click the Create Project button.

To speed things up, since we're working with a single target, we'll specify just its IP address instead of specifying a network.

Demonstration - Metasploit

Project overview page:

Screenshot of the Metasploit web interface project overview page

In order to try to exploit a vulnerability, we need to have a host (that is, server). Currently, we don't know about any hosts. Click the Scan button to scan the IP addresses or networks that we specified when we created the project and look for hosts.

Demonstration - Metasploit

Starting a scan:

Screenshot of the Metasploit web interface starting a scan

The IP address we specified when we created the project is automatically filled in for us, just click the Launch Scan button.

Demonstration - Metasploit

Scan results:

Screenshot of the Metasploit web interface after finishing a scan

The scan has finished and discovered the server we're interested in. Click "Overview" in the top menu bar to return to the project overview page.

Demonstration - Metasploit

Screenshot of the Metasploit web interface project overview page after discovering hosts

Now that we know about a host, we can do a lot more. The "Exploit" button will attempt to automatically break into the site. But, since we know from WPScan that this site is running a vulnerable plugin, to save time, click on "Modules" in the top menu and select "Search...". Then search for "wordpress".

We're actually using Metasploit far below the level of complexity for which it is intended, so many of the graphs and statistics wind up being overly simplistic.

Demonstration - Metasploit

List of Metasploit WordPress exploit modules:

Screenshot of the Metasploit exploit modules for WordPress

Click on "Wordpress W3 Total Cache PHP Code Execution".

WordPress has a lot of vulnerabilities that are not listed here. If we're interested in anything not shown, we can create an exploit module for it ourselves, or exploit it outside of Metasploit.

Demonstration - Metasploit

Screenshot of the Metasploit exploit modules for WordPress

There are a lot of options on this page. The only one we want to change is the payload, which should be changed from "Meterpreter" to "Command Shell". Then click the "Run Exploit" button, which is not shown in the screen shot but is at the bottom of the page.

The payload is the code to run on the compromised server after the exploit succeeds. It can be as simple as a single command or as complex as a large, sophisticated program that gives you full control over the computer.

The Meterpreter payload is actually a lot more impressive and has more features than the Command Shell payload, but the Command Shell is more appropriate for this demonstration.

Demonstration - Metasploit

Running the exploit:

Screenshot of the successful exploit

That's all there is to it! The web server has now been compromised.

Note that there is a (1) next to "Sessions" in the top menu, indicating that we now have an open session to the compromised server. Click on Sessions.

Demonstration - Metasploit

The session list:

Screenshot of the session list

Click on the session name in the left-most column to go to that session.

Demonstration - Metasploit

The session:

Screenshot of the session

Click the Command Shell button to get access to the remote shell that was started on the target server when the exploit succeeded.

There are a lot of information gathering tools available under the "Post-Exploitation Modules" tab, but we won't look at those here.

Demonstration - Metasploit

Screenshot of the shell, showing the root directory

Click the Command Shell button to get access to the remote shell that was started on the target server when the exploit succeeded.

This is the remote shell on the target server. Each command entered is executed separately, there is no context between commands as you would have in a real shell. This means, among other things, that you can't change directories (the current directory is the root directory, /).

Here we're taking a look at some directories on the compromised server.

Demonstration - Metasploit

More fun with the shell:

Screenshot of the shell, showing a user's home directory

The attacker will probably have access to a lot of things on the server that are not normally available via WordPress, such as the home directories of Linux users.

Demonstration - Metasploit

Screenshot of the shell, showing extraction of hashed passwords from the WordPress database

Here, we extract the database information from the wp-config.php file. If we didn't know where it was, we could look around using the ls command; or, the Meterpreter payload contains a point-and-click file browser that could be used.

Once we have the database information, we can connect to the database and dump all of the WordPress user account information, including hashed passwords. The hashed passwords can be run through a password cracking program which will often recover the original passwords from the hashes.

If we wanted to, we could modify the database — for example, to add a new admin user, letting us log in via the web interface and control the whole site. Or, we could create a new post or page just by writing to the database.

We can run any command we want as the user that the web server runs as (user www-data in this case), but we don't have administrative control of the server — we'd have to use a second exploit (if we could) to compromise the operating system and become the root user.

Demonstration - Metasploit

Let's set up an online store!

Screenshot of the shell, showing the WordPress directory and a download command

Demonstration - Metasploit

The changes for our store:

Screenshot of the shell, showing the results of the download (the modified WordPress directory)

Note the new directory named "store" which didn't exist before we ran the last command.

Demonstration - Metasploit

Screenshot of a web browser window showing the resulting 'store'

Demonstration - Metasploit

Screenshot of the blog comment posted by the exploit

Let's look at the side effects of the exploit.

Note the garbage comment posted by the exploit. The comment contained an HTML comment (not shown) that contained PHP code that was inappropriately executed due to the vulnerability in the W3 Total Cache plugin.

Comments like this may be evidence of a break-in (as this one is), but can also indicate an unsuccessful attempt to break into the site (if you were not running W3 Total Cache, or if the version you were running did not have the vulnerability).

If we were attempting the exploit by hand, rather than via Metasploit, we could make the comment seem legitimate, get around first-time comment moderation, or get around a CAPTCHA, if we want to go to the trouble of doing these things.

Window of vulnerability

The window of vulnerability is the amount of time from when anyone knows about the security problem until a fix for the problem is actually deployed for a specific WordPress site. For the W3 Total Cache remote execution vulnerability we just looked at,

This assumes that no one knew about the vulnerability privately before the plugin authors learned about it.

Some people who discover vulnerabilities will inform the authors in private; this is the best-case scenario, if the authors respond in a timely manner (many do not).

Sometimes vulnerabilities are publicly discovered when people start noticing that WordPress sites that are not vulnerable to any known attack are getting compromised anyway, and the vulnerability gets pieced together through log files and other forensic evidence. This is the worst-case scenario.

Window of vulnerability

How long a specific site was vulnerable depends on how often the site updates the plugins they use. If a site checks for updated plugins...

Currently, it's been 338 days since the vulnerability was publicly announced, but it's pretty likely that there are still many sites which have not updated yet.

These sorts of windows of vulnerability are not uncommon — in fact, they are fairly typical, which is why it's important to update frequently. I recommend updating at least once per week.

Note that since April 17th, four new versions of the W3 Total Cache plugin have been released: 0.9.2.9, 0.9.2.10, 0.9.2.11, and 0.9.3.

How bad is the situation?

A recent report (September 24th, 2013) examined over 42,000 of the most heavily visited WordPress sites worldwide. The good news:

The bad news:

Personally, I assume that if a site is popular (in the Alexa Top 1 Million), it gets a lot of content updates — perhaps even has a staff — and therefore would be more likely to get WordPress, theme, and plugin updates regularly than a small personal site would. This assumption may or may not be a valid one.

It's the last number above that is really concerning: 1 out of every 2 of the top WordPress sites in the world were significantly out of date.

How bad is the situation?

Software authors, security companies, and agencies collaborate to maintain a list of vulnerabilities, that are assigned CVE IDs. WordPress (including 3rd party themes and plugins) has 223 CVE IDs assigned to it.

There are also WordPress vulnerability statistics for every WordPress vulnerability that has been assigned a CVE ID.

The National Vulnerabilities Database, maintained by the National Institute of Standards and Technology (NIST), contains 590 vulnerabilities for WordPress.

Another good source of information on WordPress vulnerabilities is http://www.exploit-db.com/ which contains information on 376 WordPress vulnerabilities.

"CVE" stands for "Common Vulnerability and Exposure".

Many vulnerabilities never get a CVE ID, because this takes some effort to get. For example, the W3 Total Cache remote code execution vulnerability we looked at was supposed to be assigned the ID CVE-2013-2010, but although this ID was reserved for the vulnerability, no one ever completed the process, so it does not contain any information.

Types of bad guy

Satirical drawing of a stereotypical script kiddie

Script Kiddie

"lulz" (a variant of "lol") denotes laughter at someone who is the victim of a prank.

Types of bad guy

Photo of four people wearing Guy Fawkes masks, symbolizing a hactivist group

Hactivist

Types of bad guy

Photo of Jon Oberheide, a security researcher

White Hats

In the picture is Jon Oberheide, a security researcher who lives in Ann Arbor and co-founded the local company Duo Security.

Types of bad guy

Photo silhouette of a mafia enforcer holding a handgun

Organized crime and other professional bad guys

For both botnets and identities, the attacker will most likely sell them to yet another bad guy for cash; there are thriving underground markets for both. Or, the attacker could use these themselves.

The two most common purposes of botnets are to send spam or wage Distributed Denial of Service (DDoS) attacks. A DDoS attack could be for ideological reasons, to serve as a diversion for another attack or theft, or as to extort payment for not disrupting business.

Identity theft is most likely to be financial. While most WordPress blogs don't handle credit card information, an attacker will go after password hashes (for WordPress or operating system accounts) and attempt to crack them, or set up keystroke loggers. Many people use the same password for multiple web sites, or use an obvious password pattern or scheme. Knowing WordPress account passwords is not very valuable, but this could lead to compromising email accounts, merchant accounts (e.g., Amazon), or work accounts and building up enough information to be worth using or selling.

Types of bad guy

Photo of a stereotypical spy

Spies

Levels of compromise

An attacker who exploits a security vulnerability can wind up at one of several levels of compromise. From least to most serious, these are:

  1. Log in using stolen credentials (guessed, phished, intercepted). Allows the attacker to do things that the person the credentials were stolen from can do.
  2. Subvert the web application. Allows the attacker to do things that are not normally allowed, such as get private information from the database or modify posts.
  3. Subvert the account that runs the web application. Allows the attacker limited control of the server to run arbitrary code as the web server user.
  4. Subvert the server that hosts the web application. Allows the attacker complete control of the server, operating system, and all sites hosted on the server.

Frequently, an attacker will compromise the site at one level and then use the information and access that that level of compromise gives them to compromise the site at more thoroughly.

For example, an attacker might subvert the WordPress to become a blog author, allowing them to take advantage of a vulnerability that is exploitable only by authors to run any code they want, and then use this level of access to exploit an operating system vulnerability that can't be exploited remotely, only by local users, in order to become root (the superuser) on the server.

If someone compromises the server ("gets root" or "roots it") it becomes much harder to regain control again, since the attacker can hide code in the operating system kernel or libraries. The best course of action in this case is to reload the machine and restore the sites and other data from a known-good backup.

In our demonstration, we were able to go directly for #3 and stopped there. Many attackers will try to continue on to #4, if it is easy enough for them to do so (e.g., if the operating system has not been kept up to date) or if they are determined.

Stealth

Skilled attackers who are not seeking publicity will try to hide their presence on your site or server for as long as possible, since if you find them you'll kick them out and address the vulnerability which which they originally got in. It may not be obvious that your site has been compromised.

An attacker may:

How to secure your WordPress site

Short version:

  1. Check for updates to WordPress, themes, and plugins at least once a week and perform the updates right away.
  2. Do all of the stuff in the WPsecure.net Basic guide. These are practices rather than configurations.
  3. Do all of the stuff in the WPsecure.net Secure WordPress guide. These are mostly configuration changes.

WPsecure.net also has an Advanced Security guide and an guide. I don't recommend most of the things in these two guides as they are of limited effectiveness.

How to secure your WordPress site

Updating:

  1. Check for updates to WordPress, themes, and plugins at least once a week and perform the updates right away.

"But I don't want to break anything!"

You can download for free the BitNami Stack for WordPress from the Mac App Store for a very easy way to run a development WordPress site on your laptop.

A bit more work is using WAMP (Windows) or MAMP (Mac).

Or, for the most control, you can set up a server running Linux as a virtual machine on your laptop and use either a WordPress appliance or roll your own server.

How to secure your WordPress site

Password concerns:

How to secure your WordPress site

Password concerns:

Ars Technica published an article in March 2013 showing how easy it is to crack passwords.

If choosing words, don't use any phrase — make sure the words are unrelated to each other. Even obscure phrases are easy to crack.

You are protecting two things: make your password hard to guess, and if one of you passwords get stolen (from this or another site) make sure that the attacker cannot use it for anything else.

Because password cracking is so easy, it is also a good idea to limit where users can log in from. Do you really need to log in to your site — without using a VPN — from a coffee shop in Vietnam?

How to secure your WordPress site

Hosting and SSL:

Don't just select a host based on cost!

How to secure your WordPress site

Web server and filesystem:

How to secure your WordPress site

Miscellaneous:

Turning on DISALLOW_FILE_EDIT may be a little paranoid.

What to do if your site gets compromised

  1. Take the site offline (put it into maintenance mode). This prevents the attacker from doing further damage or resisting your attempts to regain control while you are fixing things.
  2. Notify your hosting provider so they can help.
  3. Make a backup of the compromised site in case you need to study it later.
  4. Look at the web server log files to determine how the attacker got in. This will help you know how to fix the problem and what else you might need to look for that the attacker did.
  5. Upgrade everything that can be upgraded.
  6. Remove any files, pages, posts, comments or processes added by the attacker. If in doubt as to whether you got everything, set up a new WordPress site from scratch and then restore your last known good backup into it.
  7. Change all passwords used by the site. Also change your hosting provider and database passwords.

How to minimize the severity of a compromise

Not using WordPress accounts for commenters removes a large trove of what are very probably horribly weak passwords associated with email addresses.

Keeping good notes serves several purposes: first, you'll have a record of how things are supposed to be, so you'll be able to tell if an attacker changed something; second, you'll be able to set up a new site with the same settings if needed without worrying if you got everything correct; third, it forces you to be more aware of the choices you've made and you'll have a clearer understanding of the big picture for your site.

References

If you want to know about vulnerabilities and how attackers exploit them, the OWASP Top 10 list (above) is a good place to start.

Also of interest for advanced readers is the analysis of the PHP object serialization vulnerability that was one of the major vulnerabilities fixed in the September 2013 release of WordPress 3.6.1:

Questions?