Broken LAMPS; Basic OS (Part 1)

Spring has sprung, and all about us, the frantic rush to clean up from all the things ignored over the long winter of March 2020 is in progress. Many LAMPS and WordPress sites are awaking to find the latest set of requirements, guidelines, and best practices from the OWASP and W3C groups, leaves them in a questionable state. In this set of missives, we will address many of these, but let’s begin with a firm foundation

We will assume one has a basic Ubuntu 20.04 server. For this, I’ll spin up an AWS instance and perform the basics. I note the CIS standards call for several modifications to a standard AWS AMI; a perusal of said is suggested, application of those recommendations should follow your standards. Thence commence the installation of a LAMPS stack. For the MySQL server, I’ll utilize an RDS instance to focus on the various OWASP, W3C, NIST, and other guidelines.

As we are assuming our server is a fresh Ubuntu AMI from the AWS repository (do check this, there are many shared builds that may not conform to GASSP), we will start with the basics; Confirm all packages are up to date:

#Systems Updates
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get autoremove
sudo apt-get autoclean

For the truly brave, or those who have complete confidence in their backups and monitoring, the option exists to apply security patches automatically:

# Auto Apply Security Patches
sudo apt-get install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

To paraphrase an old air freshener commercial; “This is a good place for a reboot”.

Our next step is to harden the TCP stack; whilst the basic AWS network ingress has some monitoring for internet trash traffic, the shared responsibility model tells us we are responsible for the OS and applications. My crib sheet(s) are as below; (DO NOTE THE COMMENTS.)

#sudo nano /etc/sysctl.conf
# Append to bottom

#----  Begin to Append
# IP Spoofing protection
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1

# Block SYN attacks
net.ipv4.tcp_syncookies = 1

# Controls IP packet forwarding.  Nope, we are NOT a router.
# Just be careful IF this is a VPN host, or a web proxy
net.ipv4.ip_forward = 0

# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# Ignore send redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Disable source packet routing. Nope, we are NOT a router.
# Just be careful IF this is a VPN host, or a web proxy
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# Log Martians
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Block SYN attacks
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Ignore Directed pings
net.ipv4.icmp_echo_ignore_all = 1

# kernel.exec-shield = 1
kernel.randomize_va_space = 1

# Accept Redirects? Nope, we are NOT a router.
# Just be careful IF this is a VPN host, or a web proxy
net.ipv4.conf.all.secure_redirects = 0

# Log packets with impossible addresses to kernel log? yes
net.ipv4.conf.default.secure_redirects = 0

The next stanza may cause screams of “Heresy!, Blasphemy!, Heretic!“, etc. Do check your Minimum Base Standards, and apply as you deem necessary. (Please leave the torches and pitchforks at home)

# disable IPv6 if required (IPv6 might cause issues with the Internet connection being slow)
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
# [IPv6] Number of Router Solicitations to send until assuming no routers are present.
# This is host and not router.
net.ipv6.conf.default.router_solicitations = 0
# Accept Router Preference in RA?
net.ipv6.conf.default.accept_ra_rtr_pref = 0
# Learn prefix information in router advertisement.
net.ipv6.conf.default.accept_ra_pinfo = 0
# Setting controls whether the system will accept Hop Limit settings from a router advertisement.
net.ipv6.conf.default.accept_ra_defrtr = 0
# Router advertisements can cause the system to assign a global unicast address to an interface.
net.ipv6.conf.default.autoconf = 0
# How many neighbor solicitations to send out per address?
net.ipv6.conf.default.dad_transmits = 0
# How many global unicast IPv6 addresses can be assigned to each interface?
net.ipv6.conf.default.max_addresses = 1

And for the brave beyond all reason or those inflicted with memory leaks (“Java” he whispers, in an ominous voice); We can set up automated reboots for out-of-memory conditions.

# In rare occasions, it may be beneficial to reboot your server reboot if it runs out of memory.
# This simple solution can avoid you hours of down time. The vm.panic_on_oom=1 line enables panic
# on OOM; the kernel.panic=10 line tells the kernel to reboot ten seconds after panicking.
vm.panic_on_oom = 1
kernel.panic = 10

As spoken prior; “This is a good place for a reboot”. Or one can apply the above with a simple:

# Apply new settings
sudo sysctl -p

One should also set our locale and tz to ensure centralized logging and date times are coordinated. Many organizations leave these as UTC; some want them set to ZULU, and others want Local Time Zone. Review your Minim Base Standards and set them as appropriate. Here I have used EST:

#Set Locale and TZ
sudo locale-gen en_US.UTF-8
sudo update-locale LANG=en_US.UTF-8
sudo timedatectl set-timezone America/New_York

As with all the posts on this blog, I will caution you that the above may / may not apply to your environment and strongly suggest reviewing your backups and back up any files to be edited BEFORE EDITING.