1 of 22

Security of WordPress

A guide by Nedko Hristov

2 of 22

About me

  • Quality Assurance Engineer @ Astound Commerce
  • Wannabe sysdmin
  • Road cyclist
  • Lecturer
  • Writer

3 of 22

We’re hiring

  • Quality Assurance Engineer
  • Front-End developer
  • Web developer
  • UX Designer

Secret requirements:

Be awesome

Be great table tennis player

Be the best Mortal kombat player alive

4 of 22

Appendix

Overall security

Backups

Updates

etc

Platform security

Core

Plugins

Themes

System security

OS

Apache/nginx

PHP, etc

5 of 22

Platform security

Install plugins only if needed;

  • Always use sandbox/local install of plugins;
  • Verify the plugin before install (no matter how desperate you are):
    • Last update;
    • Avg rating;
    • Author;
    • Installs;

Note - Inactive plugins/themes are vulnerable too (using direct file access method).

6 of 22

Platform security

Don't install nulled plugins/themes

  • Possibly infected (base64, shell_exec, load external script, etc);
  • Send spam in honor of your domain name;
  • Spam links what can ruin the SEO;
  • Deface the entire website;
  • Gain access to the DB/server files.

7 of 22

Platform security

Install with different that default (wp_) prefix (to avoid some SQL injections);

Rename WordPress default prefix can be vital in case of SQL injection. Attacker can create valid admin user/post or anything he wants to (depends of the vulnerability).

8 of 22

Platform security

  • Least Privilege Principle

File privileges;

Database privileges (select/ delete/ insert/ update);

WordPress users;

Files and directories permissions (755 for directories, 644 for files, 600 for wp-config.php);

FTP access (plugins, third party contractors).

9 of 22

Platform security

  • Information leakage

User enumeration is one of the most user attack vectors.

This method use author functionality (?author=x) to find all users. Try with https://nedko.info/?author=1 and you’ll find my username and user ID.

10 of 22

Platform security

  • Use strong passwords

Even not using passwords like 1234 will not assure you from bruteforce attacks.

Why?

11 of 22

12 of 22

Platform security

�Tool - wpscan, dictionary - darc0de

Target - https://nedko.info/old_wp/

Attack vectors - information disclosure, scan for outdated core/plugins/themes, user enumeration, bruteforce dictionary attack.

Result:

+----+-------+---------------------+----------------------+

| Id | Login | Name | Password |

+----+-------+---------------------+----------------------+

| 1 | nedko | nedko – Testing old | password123!@# |

+----+-------+---------------------+----------------------+

13 of 22

System security

  • Use trusted hosting/VPS provider;
  • Use consistent nginx/apache user/group (default is www-data)
  • Files permissions (600/644/700/755);
  • No tmp directories/files/old wp-config.php file;
    • You can restrict access to any web directory using htpasswd protection (using apache-utils);
  • Separate environments and mySQL user for each project;

14 of 22

System security

Manual system scan

Tools - Nikto, wpscan, etc;

Scan for suspicious strings like base64_decode and shell_exec;

Search php files in the Uploads Directory (find ./wp-content/uploads -name "*.php" -print)

Search for files with 777

find / -type f -perm 0777

Change files permissions from 777 to 755 automatically

find /path/to/search -perm 777 -print -exec chmod 755 {} \;

15 of 22

System security

  • Enable/disable core and auto updates (todo);
  • Note that with every deinstallation of plugin there may be some DB records left. Be particularly aware of analytics plugins (use google analytics instead) due on the huge amount of data saved on the DB;
  • API with WP core/theme/plugin vulnerabilities;
  • List of exploits for WP (use only for good!)

16 of 22

System security

  • Using Google Dorks (GHDB) for good

Find wp-config.php_old

inurl:wp-config.php_old

Find database

inurl:"/wp-content/wpclone-temp/wpclone_backup/"

Find files with SQL extention and containing wp_users

filetype:sql intext:wp_users phpmyadmin

17 of 22

nginx/apache bruteforce protection

/etc/nginx/sites-available/nedko.info

limit_req_zone $binary_remote_addr zone=one:1m rate=5r/s;

location = /old_wp/wp-login.php {

limit_req zone=one burst=1 nodelay;

fastcgi_pass unix:/var/run/php5-fpm.sock;

include fastcgi_params;

}

18 of 22

Proof of Concept

19 of 22

Overall security

  • Backups - files, DB and configs;
  • Keep updated the core/plugins/themes and system if self-hosted;
  • Always use separate sandbox for each project. Don't do changes on production no matter how small is the project;
  • Always use separated environments on the production site

20 of 22

Contact me

  • Web - https://nedko.info
  • LinkedIn - @nedelchohristov
  • Facebook - @nedko2
  • Twitter - @nedkohristov
  • GitHub - @NedkoHristov

21 of 22

22 of 22