baumi's blog

baumi's personal blog … Linux, OS X, Windows, Random things, …

Hardening WordPress, tshark decrypting SSL traffic

From a security point of view, WordPress seems to be a nightmare. The default setup exposes hundrets of .php include files in wp-includes/ and wp-content/ that may be directly called. And indeed, many robots out there are scanning the whole internet for these kind of files.

Here are some ideas to improve security.

Step 1: Add password authentication to wp-login.php, block xmlrpc.php attacks, disable direct access to wp-includes.

in your-wordpress-root-directory/.htaccess add:

# Block the include-only files.

RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]



AuthType Basic
AuthName "Protected Area"
AuthUserFile your-wordpress-root-directory/.htpasswd
Require user your-username
Satisfy All



AuthType Basic
AuthName "Protected Area"
AuthUserFile your-wordpress-root-directory/.htpasswd
Require user your-username
Satisfy All



AuthType Basic
AuthName "Protected Area"
AuthUserFile your-wordpress-root-directory/.htpasswd
Require user your-username
Satisfy All



Order Deny,Allow
deny from all


# The following is required to hide the login names, 
# otherwise a call to  http://yoursite/?author=1 will 
# show the username for user id 1, ?author=2 will expose 
# the login name for the second user, and so on ...
RewriteCond %{REQUEST_URI}  ^/$
RewriteCond %{QUERY_STRING} ^/?author=([0-9]*)
RewriteRule ^(.*)$ http://www.yoursite.com/? [R,L]

To create your-wordpress-root-directory/.htpasswd, simply call “htpasswd -C <your-username>”.

Step 2: Add additional HTTP authentication to your-wordpress-root-directory/wp-admin/ folder. This way you have a second security level provided by Apache Web Server and external tools cannot directly call your .php files in order to use known exploits in the PHP code.

AuthType Basic
AuthName "Protected Area"
AuthUserFile your-wordpress-root-directory/.htpasswd
Require user your-username
Satisfy All

for specific wordpress themes that are loading content via ajax we have found out that we need to create an exception for admin-ajax.php


 AuthType Basic
 AuthName "Protected Area"
 AuthUserFile your-wordpress-root-directory/.htpasswd
 Require user your-username
 Satisfy All

 
  Order Deny,Allow
  Allow from all
  Satisfy any
 

Step 3: Restrict PHP execution in wp-includes. This is important so the PHP files that are meant to be included by other PHP files cannot be accessed directly. Create/add your-wordpress-root-directory/wp-includes/.htaccess

# Disable access to all file types except the following
Order deny,allow
Deny from all

  Allow from all


--

Step 4: Restrict PHP execution in wp-content. This is very important to disable potential direct PHP code execution (worst case: a .php file from an uploads!). -> Create/add your-wordpress-root-directory/wp-content/.htaccess

# Disable access to all file types except the following
Order deny,allow
Deny from all

  Allow from all


--

Step 5: Turn off the version number output for XML feeds in your-wordpress-root-directory/wp-includes/general-template.php in order to block tools that are scanning for specific wordpress versions (in order to use known exploits for that version).

Screen Shot 2016-06-21 at 09.57.59

--

Step 6: If you don't use /feed and /news/feed you may create empty directories. This way PHP won't even be executed.
mkdir -p your-wordpress-root-directory/feed
mkdir -p your-wordpress-root-directory/news/feed

--

Step 7: Alternatively to blocking thins with .htaccess, you might consider additional filters for your firewall, some examples here:

iptables -I INPUT -p tcp --dport 80 -m string --to 160 --algo bm --string 'GET /wp-sql.php' -j DROP
iptables -I INPUT -p tcp --dport 80 -m string --to 160 --algo bm --string 'GET /xmlrpc.php' -j DROP
iptables -I INPUT -p tcp --dport 80 -m string --to 250 --algo bm --string 'GET /%3Fm%3D201601&sa=U&ved=0ahUKEwi7mK69_brNAhUJEZAKHYPeASY4ZBAWCCEwAw' -j DROP
iptables -I INPUT -p tcp --dport 80 -m string --to 250 --algo bm --string 'POST /%3Fm%3D201601&sa=U&ved=0ahUKEwi7mK69_brNAhUJEZAKHYPeASY4ZBAWCCEwAw' -j DROP
iptables -I INPUT -p tcp --dport 80 -m string --to 250 --algo bm --string 'ved=0ahUKEwi7mK69_brNAhUJEZAKHYPeASY4ZBAWCCEwAw' -j DROP

Of course these can also be done via .htaccess but it shows the idea. However, .htaccess might be the preferred solution, as it will also work for https:// connections.

--

Step 8: Learn and use wireshark (or tshark for terminal). Here is a simple tshark example that allows you to monitor the requests in real time. The first time i did is i had quite a few "ahas". Now i'm watching it from time to time. For the case i discover something i don't like, i can add rules to firewall and .htaccess files.

#!/bin/bash
tshark -f "tcp port 80" -Y 'http.request || http.response'

#OR (for decrypting SSL. Won't work when using Diffie-Hellman, see Google why):

tshark -o "ssl.desegment_ssl_records: TRUE" -o "ssl.desegment_ssl_application_data: TRUE" -o "ssl.keys_list:78.46.156.164,443,http,/home/frank/ssl/.b-nm.at.key" -o "ssl.debug_file:ssldebug.log" -f "tcp port 443" -Y "http" -x

 

For reference see https://www.wireshark.org/docs/dfref/h/http.html

Screen Shot 2016-06-21 at 10.03.09

--

If you have read all the way down to this line and you think i forgot something important or have got feedback, ideas, improvements, please don't hesitate to contact me: frank (at) baumi.org

Comments are currently closed.