Server Hardening

While the defaults should be secure, there are some simple administrative actions that will increase your overall security. None of these steps are required, but we encourage you to read this document to see if the enhancements are relevant for your environment.

Tighten PHP configuration

Tighten the security of the PHP installation by creating a file /etc/php5/conf.d/harden.ini with the following content:

user@host:~$ sudo sh -c 'cat > /etc/php5/conf.d/harden.ini'
display_errors = Off
log_errors = On
user@host:~$

Tighten Apache configuration

Tighten the security of the Apache installation by making sure directory listings are disabled globally. Edit /etc/apache2/conf.d/security and make sure the following is uncommented:

<Directory />
  AllowOverride None
  Order Deny,Allow
  Deny from all
</Directory>

Time Synchronization

For logging and (on the validation server) time-stamping it is important to have synchronized clocks. Install ntp.

user@host:~$ sudo apt-get install ntp
...

Firewall

There is no reason why the KSM needs to listen to incoming requests from the entire Internet, and restricting access to the intended YK-VAL servers are recommended.

user@ksm:~$ sudo sh -c 'cat > /etc/network/if-pre-up.d/iptables'
#!/bin/sh

# IPv4 firewall:
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -i eth0 -s 1.2.3.4 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 -s 2.3.4.5 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 -s 2.3.4.5 --dport 443 -j ACCEPT

# IPv6 firewall:
ip6tables -F
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -i lo -p all -j ACCEPT
ip6tables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 -s 2000:1:2::3 --dport 22 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 -s 2000:2:3::4 --dport 80 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 -s 2000:2:3::4 --dport 443 -j ACCEPT

user@ksm:~$ chmod +x /etc/network/if-pre-up.d/iptables
user@ksm:~$

Replace 1.2.3.4 (for IPv4) and 2000:1:2::3 (for IPv6) with the address of the host you want to be able to login from via SSH, and replace 2.3.4.5 (for IPv4) and 2000:2:3::4 (for IPv6) with the address of the YK-VAL that will be accessing this YK-KSM. Add more lines for each validation server and SSH host.

For a validation server, you may want to allow HTTP(S) requests from anyone, but not anything else.

user@val:~$ sudo sh -c 'cat > /etc/network/if-pre-up.d/iptables'
#!/bin/sh

# IPv4 firewall
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -i eth0 -s 1.2.3.4 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 443 -j ACCEPT

# IPv6 firewall:
ip6tables -F
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -i lo -p all -j ACCEPT
ip6tables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 -s 2000:1:2::3 --dport 22 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 443 -j ACCEPT

user@ksm:~$ chmod +x /etc/network/if-pre-up.d/iptables
user@ksm:~$

Again, replace 1.2.3.4 (for IPv4) and 2000:1:2::3 (for IPv6) with the address of the host you want to be able to login from via SSH.

If you want to allow SSH and HTTP(S) from everywhere, but nothing else, try this:

user@val:~$ sudo sh -c 'cat > /etc/network/if-pre-up.d/iptables'
#!/bin/sh

# IPv4 firewall
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 443 -j ACCEPT

# IPv6 firewall:
ip6tables -F
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -i lo -p all -j ACCEPT
ip6tables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 22 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 443 -j ACCEPT

user@ksm:~$ chmod +x /etc/network/if-pre-up.d/iptables
user@val:~$

Database Encryption

The database contains sensitive information. If someone is able to access your machine physically, they may shut it off and steal it with the goal of reading out the sensitive information. By encrypting the disk, you can prevent this. Note that this does not protect against an attacker who has physical access to your server and sufficient time to read out the data from the already running system.

Full disk encryption will give you the highest protection, but requires that you can enter the disk encryption password on each power-up. This can be unpractical when your hosting environment is remote.

Partial disk encryption allows the operating system to start up, and enable you to login to the machine remotely to enter the disk encryption password. This is less secure than full disk encryption, because an attacker could physically disconnect your machine, modify the operating system to send a copy of the password to the attacker, but may be sufficient if you keep good track of when your machine is not working properly.

To use partial disk encryption for the database content, we suggest you install the operating system as normal but create another file system on an encrypted volume.

If you need swap space, be sure to only put the swap on the encrypted volume too. Make sure that the database does not start up automatically on boot, and also make sure that the system does not attempt to mount your encrypted partition automatically.

Setup:

user@ksm:~$ sudo apt-get install loop-aes-utils loop-aes-modules-2.6-amd64
...
user@ksm:~$ sudo rmmod loop && sudo modprobe loop
user@ksm:~$ sudo dd if=/dev/zero of=/root/ksm.img bs=1k count=1M
...
user@ksm:~$ sudo losetup -e AES128 /dev/loop0 /root/ksm.img
Password:
user@ksm:~$ sudo mkfs.ext2 -q /dev/loop0
user@ksm:~$ sudo mkdir /ksm
user@ksm:~$ sudo mount /dev/loop0 /ksm
user@ksm:~$ sudo /etc/init.d/postgresql-8.3 stop
...
user@ksm:~$ sudo update-rc.d -f postgresql-8.3 remove
user@ksm:~$ sudo mv /var/lib/postgresql /ksm
user@ksm:~$ sudo ln -s /ksm/postgresql /var/lib/postgresql
user@ksm:~$ sudo sh -c 'cat > /usr/local/sbin/ykksm-start'
#!/bin/sh
set -e
set -x
losetup -e AES128 /dev/loop0 /root/ksm.img
fsck /dev/loop0
mount /dev/loop0  /ksm/
/etc/init.d/postgresql-8.3 start
user@ksm:~$ sudo sh -c 'cat > /usr/local/sbin/ykksm-stop'
#!/bin/sh
set -e
set -x
/etc/init.d/postgresql-8.3 stop
umount /ksm
losetup -d /dev/loop0
user@ksm:~$ sudo chmod +x /usr/local/sbin/ykksm-{start,stop}

Slightly adapted for MySQL:

user@ksm:~$ sudo apt-get install loop-aes-utils loop-aes-modules-2.6-686
...
user@ksm:~$ sudo rmmod loop && sudo modprobe loop
user@ksm:~$ sudo dd if=/dev/zero of=/root/ksm.img bs=1k count=1M
...
user@ksm:~$ sudo losetup -e AES128 /dev/loop0 /root/ksm.img
Password:
user@ksm:~$ sudo mkfs.ext2 -q /dev/loop0
user@ksm:~$ sudo mkdir /ksm
user@ksm:~$ sudo mount /dev/loop0 /ksm
user@ksm:~$ sudo /etc/init.d/mysql stop
user@ksm:~$ sudo update-rc.d -f mysql remove
user@ksm:~$ sudo mv /var/lib/mysql /ksm
user@ksm:~$ sudo ln -s /ksm/mysql /var/lib/mysql
user@ksm:~$ sudo sh -c 'cat > /usr/local/sbin/ykksm-start'
#!/bin/sh
set -e
set -x
losetup -e AES128 /dev/loop0 /root/ksm.img
fsck /dev/loop0
mount /dev/loop0  /ksm/
/etc/init.d/mysql start
user@ksm:~$ sudo sh -c 'cat > /usr/local/sbin/ykksm-stop'
#!/bin/sh
set -e
set -x
/etc/init.d/mysql stop
umount /ksm
losetup -d /dev/loop0
user@ksm:~$ sudo chmod +x /usr/local/sbin/ykksm-{start,stop}

Then in the future, to start the YK-KSM, you will need to login to the machine and issue the command sudo ykksm-start and enter the disk encryption password.

Again, make sure that you don’t use any unencrypted swap.

Intrusion Detection

To make some attacks discussed in the previous section harder, make sure that your system has a hardware intrusion detection system and that your software is notified when it is triggered. When the intrusion detection is triggered, you should stop the database and unmount the encrypted volume and send out a signal to your administrators.