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: AllowOverride None Order Deny,Allow Deny from all 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.