LAMP Stack Security: Essential Hardening Techniques for Apache, MySQL, and PHP


3 views

Start by disabling unnecessary modules and restricting directory permissions:

# Disable risky modules
a2dismod autoindex status cgi
# Secure directory permissions
chmod 750 /var/www/html
chown -R www-data:www-data /var/www/html

After installation, run the security script and implement these changes:

mysql_secure_installation
# In MySQL console:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'ComplexP@ssw0rd';
DELETE FROM mysql.user WHERE User='';
FLUSH PRIVILEGES;

Edit php.ini with these critical settings:

expose_php = Off
allow_url_fopen = Off
display_errors = Off
log_errors = On
disable_functions = exec,passthru,shell_exec,system

Set up basic firewall rules:

ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow http
ufw allow https
ufw enable

Install and configure the web application firewall:

apt install libapache2-mod-security2
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
# Enable Core Rule Set
git clone https://github.com/coreruleset/coreruleset /etc/modsecurity/crs/
  • Set up automatic security updates: apt install unattended-upgrades
  • Implement log monitoring with fail2ban
  • Schedule regular backups with verification
  • Monitor for suspicious processes: ps auxf

Securing a LAMP server requires a multi-layered approach addressing each component:

  • Linux: OS-level hardening and user permissions
  • Apache: Web server configuration and module management
  • MySQL/MariaDB: Database access controls
  • PHP: Runtime security and sandboxing
# Disable unnecessary services
sudo systemctl list-unit-files --type=service | grep enabled
sudo systemctl disable [unnecessary-service]

# Configure firewall (UFW example)
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

# Automatic security updates
sudo apt-get install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

Essential directives for /etc/apache2/apache2.conf:

ServerTokens Prod
ServerSignature Off
TraceEnable Off
Header always append X-Frame-Options SAMEORIGIN
Header set X-Content-Type-Options nosniff
Header set X-XSS-Protection "1; mode=block"

# Disable directory listing
Options -Indexes

# Restrict HTTP methods
<LimitExcept GET POST>
    Deny from all
</LimitExcept>
# Run mysql_secure_installation
sudo mysql_secure_installation

# Create application-specific users
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT SELECT, INSERT, UPDATE ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;

# Enable binary logging for audit
[mysqld]
log-bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10

Key settings for php.ini:

expose_php = Off
display_errors = Off
log_errors = On
allow_url_fopen = Off
allow_url_include = Off
disable_functions = exec,passthru,shell_exec,system
upload_max_filesize = 2M
post_max_size = 4M

For WordPress installations (example):

# .htaccess protection
<Files wp-config.php>
    Order Allow,Deny
    Deny from all
</Files>

# Disable XML-RPC
<Files xmlrpc.php>
    Order Deny,Allow
    Deny from all
</Files>
# Install and configure fail2ban
sudo apt-get install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Configure for Apache
[apache]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/*error.log
maxretry = 3

# Regular vulnerability scanning
sudo apt-get install lynis
sudo lynis audit system
# Simple backup script
#!/bin/bash
DATE=$(date +%Y-%m-%d)
mysqldump -u root -p[password] --all-databases > /backups/mysql-$DATE.sql
tar -czvf /backups/web-$DATE.tar.gz /var/www/html/
find /backups/ -type f -mtime +30 -exec rm {} \;