WordPress setup on CentOS 6

Setting up WordPress is a pretty common task. However all too often I see people installing WordPress, and setting the ownership to ‘apache:apache’ recursively. While this makes life easier for the administrator, it opens up a host of security issues.

Taken directly from WordPress’s best practice guide on permissions:

Typically, all files should be owned by your user (ftp) account on your web server, and should be writable by that account. On shared hosts, files should never be owned by the web server process itself (sometimes this is www, or apache, or nobody user).

Most people know that using FTP is bad. However if you plan on using the wp-admin portal for media uploads, plugin updates, and core updates, you MUST have an FTP server installed and running. Using the Pecl SSH2 library looks like it would work in theory, but in reality, it doesn’t. Or at least, I haven’t found a way to make it work for the wp-admin portal without giving permission errors for this, that and everything in between since it needs weaker permissions. So while your users can use SSH/SCP to upload content via the command line, if they choose to do most of the WordPress tasks through wp-admin like most people would, use the FTP option from within /wp-admin.

This guide is going to show how you can setup WordPress properly accordingly to the note above from WordPress’s best practices guide on permissions. This guide will assume that you already have a working LAMP stack installed.

FTP Server Setup

First, install an FTP server called vsftpd:

[root@web01 ~]# yum install vsftpd
[root@web01 ~]# chkconfig vsftpd on

Now disable anonymous logins since vsftpd enables this by default for some reason:

[root@web01 ~]# vim /etc/vsftpd/vsftpd.conf
...
anonymous_enable=NO
...
[root@web01 ~]# service vsftpd restart

Then confirm you have a firewall in place that has a default to deny policy. So in the example below, I am only allowing in ports 80 and 443 from the world. Then I have SSH restricted to my IP address. Everything else is blocked, including that FTP server.

[root@web01 ~]# vim /etc/sysconfig/iptables
# Generated by iptables-save v1.4.7 on Fri Nov 13 19:24:15 2015
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2:328]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT 
-A INPUT -i eth0 -s xx.xx.xx.xx/32 -p tcp -m tcp --dport 22 -m comment --comment "Allow inbound SSH from remote ip" -j ACCEPT
-A INPUT -p icmp -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A INPUT -j REJECT --reject-with icmp-host-prohibited 
-A FORWARD -j REJECT --reject-with icmp-host-prohibited 
COMMIT
# Completed on Fri Nov 13 19:24:15 2015

Database Setup

Create a database for your new WordPress site by:

[root@web01 ~]# mysql
mysql> create database your_database;

Now grant access for that database to a user:

[root@web01 ~]# mysql
mysql> grant all on your_database.* to 'your_db_user'@'localhost' identified by 'your_secure_db_password';
mysql> flush privileges;
mysql> quit

Apache Setup

First, create a FTP/SCP user:

[root@web01 ~]# mkdir -p /var/www/vhosts/example.com
[root@web01 ~]# chmod 755 /var/www/vhosts/example.com
[root@web01 ~]# useradd -d /var/www/vhosts/example.com example_site_user
[root@web01 ~]# passwd example_site_user

Now setup the Apache vhost:

[root@web01 ~]# vim /etc/httpd/vhost.d/example.com.conf
<VirtualHost *:80>
        ServerName example.com
        ServerAlias www.example.com
        #### This is where you put your files for that domain
        DocumentRoot /var/www/vhosts/example.com

        ### Enable this if you are using a SSL terminated Load Balancer
        SetEnvIf X-Forwarded-Proto https HTTPS=on

	#RewriteEngine On
	#RewriteCond %{HTTP_HOST} ^example.com
	#RewriteRule ^(.*)$ http://www.example.com [R=301,L]

        <Directory /var/www/vhosts/example.com>
                Options -Indexes +FollowSymLinks -MultiViews
                AllowOverride All
		Order deny,allow
		Allow from all
        </Directory>
        CustomLog /var/log/httpd/example.com-access.log combined
        ErrorLog /var/log/httpd/example.com-error.log
        # New Relic PHP override
        <IfModule php5_module>
               php_value newrelic.appname example.com
        </IfModule>
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
</VirtualHost>


##
# To install the SSL certificate, please place the certificates in the following files:
# >> SSLCertificateFile    /etc/pki/tls/certs/example.com.crt
# >> SSLCertificateKeyFile    /etc/pki/tls/private/example.com.key
# >> SSLCACertificateFile    /etc/pki/tls/certs/example.com.ca.crt
#
# After these files have been created, and ONLY AFTER, then run this and restart Apache:
#
# To remove these comments and use the virtual host, use the following:
# VI   -  :39,$ s/^#//g
# RedHat Bash -  sed -i '39,$ s/^#//g' /etc/httpd/vhost.d/example.com.conf && service httpd reload
# Debian Bash -  sed -i '39,$ s/^#//g' /etc/apache2/sites-available/example.com && service apache2 reload
##

# <VirtualHost _default_:443>
#        ServerName example.com
#        ServerAlias www.example.com
#        DocumentRoot /var/www/vhosts/example.com
#        <Directory /var/www/vhosts/example.com>
#                Options -Indexes +FollowSymLinks -MultiViews
#                AllowOverride All
#        </Directory>
#
#        CustomLog /var/log/httpd/example.com-ssl-access.log combined
#        ErrorLog /var/log/httpd/example.com-ssl-error.log
#
#        # Possible values include: debug, info, notice, warn, error, crit,
#        # alert, emerg.
#        LogLevel warn
#
#        SSLEngine on
#        SSLCertificateFile    /etc/pki/tls/certs/2016-example.com.crt
#        SSLCertificateKeyFile /etc/pki/tls/private/2016-example.com.key
#        SSLCACertificateFile /etc/pki/tls/certs/2016-example.com.ca.crt
#
#        <IfModule php5_module>
#                php_value newrelic.appname example.com
#        </IfModule>
#        <FilesMatch \"\.(cgi|shtml|phtml|php)$\">
#                SSLOptions +StdEnvVars
#        </FilesMatch>
#
#        BrowserMatch \"MSIE [2-6]\" \
#                nokeepalive ssl-unclean-shutdown \
#                downgrade-1.0 force-response-1.0
#        BrowserMatch \"MSIE [17-9]\" ssl-unclean-shutdown
#</VirtualHost>

Then restart Apache to apply the changes:

[root@web01 ~]# service httpd restart

WordPress Setup

Download a copy of WordPress, uncompress, and move the files into place by:

[root@web01 ~]# cd /var/www/vhosts/example.com
[root@web01 ~]# wget http://wordpress.org/latest.tar.gz && tar -xzf latest.tar.gz
[root@web01 ~]# mv wordpress/* ./ && rmdir ./wordpress && rm -f latest.tar.gz

Update the files and directories ownership to lock it down accordingly:

[root@web01 ~]# chown -R example_site_user:example_site_user /var/www/vhosts/example.com

Then open up a few files so wp-admin can manage the .htaccess, and so it can install plugins, upload media, and use the cache if you choose to configure it:

[root@web01 ~]# mkdir /var/www/vhosts/example.com/wp-content/uploads
[root@web01 ~]# mkdir /var/www/vhosts/example.com/wp-content/cache
[root@web01 ~]# touch /var/www/vhosts/example.com/.htaccess
[root@web01 ~]# chown apache:apache /var/www/vhosts/example.com/wp-content/uploads
[root@web01 ~]# chown apache:apache /var/www/vhosts/example.com/wp-content/cache
[root@web01 ~]# chown apache:apache /var/www/vhosts/example.com/.htaccess

And thats it! Once you have the domain setup in DNS, you should be able to navigate to the domain, and follow the WordPress installation wizard to complete the setup. Afterwards, log into wp-admin, and try to update a plugin, or install a new one. When it prompts you for the FTP information, be sure to use:

Hostname:  localhost
FTP Username:  example_site_user
FTP Username:  example_site_user_pw
Connection Type:  FTP

RHCSA Study Guide – Objective 9 : Network Security

############################
Everything below are my raw notes that I took while attending an unofficial RHCSA training session.  I am posting them here in hopes they will assist others who may be preparing to take this exam.  

My notes are my own interpretation of the lectures, and are certainly not a replacement to classroom training either through your company, or by taking the official RHCSA classes offered through Red Hat.  If you are new to the Red Hat world, I strongly suggest looking into their training courses over at Red Hat.
############################

TCP Wrappers

TCP wrappers were originally written to provide host based access controls, pretty much back 30 years ago. It can be thought of as the first firewall of sorts. So assuming the service your looking to protect supports tcpwrappers, and tcpwrappers are turned on, then you can enable wrappers.

To see if the application has tcpwrappers built in, you can do the following:

[root@web01 ~]# which sshd
[root@web01 ~]# /usr/sbin/sshd
[root@web01 ~]# ldd /usr/sbin/sshd |grep wrap # If you see libwrap.so.0, it has support.

The 2 configuration files are below:

/etc/hosts.allow
/etc/hosts.deny

They are parsed in the following order:

1.  /etc/hosts.allow is consulted first.  If the configuration permits the requested connections, its allowed.
2.  /etc/hosts.deny is consulted.  If the configuration doesn't permit the connection, its denied.

If the connection is not specifically accepted or rejected in either file, its denied.

The syntax in both of these files are as follows: (Using sshd as the example)

[root@web01 ~]# vi /etc/hosts.deny
# Deny ssh connections from 192.168.2.223
sshd: 192.168.2.223

iptables

Iptables operates at the kernel level, which allows for:

- Flexible layer 2 filtering engine
- NAT support
- Port forwarding
- And a ton more

The configuration is parsed top to bottom. First match wins. If there is no specific match, the chain policy will apply.

Tools:

[root@web01 ~]# iptables # view/modify current firewall rules
[root@web01 ~]# iptables-save # Script to save current firewall rules for use with iptables-restore
[root@web01 ~]# iptables-restore # Restores iptables-save format firewall rules - useful to setup firewalls at boot.

Personally, I like doing this stuff myself by directly editing:

[root@web01 ~]# /etc/sysconfig/iptables.

When creating rules, considerations include:

1.  What chain should the rule apply to?  Note:  A chain is just a collection of rules
  a.  INPUT - Any traffic coming inbound 
  b.  OUTPUT - Egress filtering (outbound filtering)
  c.  FORARD - Responsible for filtering traffic between different interfaces

2.  What traffic pattern to look for
The most common flags for the exam are posted below:
  a.  -i incoming interface
  b.  -p protocol (udp/tcp)
  c.  -s source ip address
  d.  -d destination ip address
  e.  --dport destination port

3.  What should happen with the traffic.
  a.  DROP : Do not deliver, do not respond
  b.  REJECT : Do not deliver, send reject notice
  c.  ACCEPT : Deliver
  d.  Log : Just log the packet.

EXAM NOTE: Will probably only see INPUT chain rules only.

Summary of iptables:
- iptables

What chain should the rule apply to?
 -A INPUT

What is the traffic pattern to look for?
 -s 192.168.222.2

What should happen with the traffic?
 -j REJECT

Lab

1.  Use iptables, configure your web server to NOT accept connections from the 192.168.1.0/24 network, EXCEPT for the ip address of whomever is sitting next to you.  Work together to test firewall settings, and remember, WEB server.

[root@web01 ~]# vi /etc/sysconfig/iptables
...
-A INPUT -s 192.168.1.4 -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -s 192.168.1.0/24 -m tcp -p tcp --dport 80 -j REJECT
...

2.  Browse through the man page for iptables.
[root@web01 ~]# man iptables

3.  Use iptables to allow ssh from the classroom network only.
[root@web01 ~]# vi /etc/sysconfig/iptables
...
-A INPUT ! -s 192.168.1.0/24 -m tcp -p tcp --dport 22 -j REJECT
...