Tips for securing LAMP Stack (Apache, MySQL and PHP) on Linux

If you are a system administrator and you have recently set up a LAMP stack on Linux server but you are not sure about its security, Than you are at a rite place. In this post i am trying to explain all those security tips which need to be considered while setting up new LAMP system for production.

If you are a new and do not know how to install LAMP on Linux systems, please follow the links given below as per your requirements.

How to Install LAMP Stack on CentOS 6
How To Install a LAMP stack On Ubuntu 16.04

All the configuration changes applied in this article will be updated in following mention configuration files as per your operating systems. In some cases configuration files path can be change. So make changes in appropriate files. After making changes restart related services to take changes effect.

For CentOS, RedHat & Fedora:

Apache: /etc/httpd/conf/httpd.conf
PHP: /etc/php.ini
MySQL: /etc/my.cnf

For Ubuntu, Debian & LinuxMint:

Apache2: /etc/apache2/apache2.conf
PHP5: /etc/php5/apache2/php.ini
MySQL: /etc/mysql/my.cnf

1. Hide Apache Version and OS

The ServerTokens directive controls whether Server response header field which is sent back to clients. The ServerSignature configures the footer on server-generated documents. Edit Apache configuration file and update following directives as following

By default, the server HTTP response header contains apache and php version. This is harmful, as we don’t want an hacker to know about the specific version number. To avoid this, Edit Apache configuration file and update following directives.

httpd.conf
ServerTokens Prod
ServerSignature Off

This will display “Server: Apache” without any version information.

2. Disable Directory Listing in Apache

If you do not disabled directory listing in Apache. Then all the files and directories list will be shown on web page if no default document exists. Add following configuration in Apache to disable directory listing server wide.

<Directory />
Options -Indexes
</Directory>

After that you can enable listing on per directory basis if required.

3. Restricting File and Directory Access (Apache)

We also need to Restrict access on basis of Directory, File and Location in Apache for security purposes.

Restrict Directory

To restrict directory and files access from users, It will only allowed the ips are defined as:

<Directory "/home/user/public_html">
Order Deny,Allow
Deny from all
Allow from 192.168.1.0/24
Allow from .example.com
</Directory>

Restrict File

We can also restrict specific file using File directive like below.

<File data.xml>
Order deny,allow
Deny from all
</File>

Restrict Location

The Location directive limits the scope of the enclosed directives by URL.

<Location /admin>
Order Deny,Allow
Deny from all
Allow from 192.168.1.0/24
Allow from .example.com
</Location>

4. Disable Server Side Includes and CGI Execution in Apache

We can simply disable server-side includes and CGI execution by defining directory tag. Add below in Apache virtual host configuration file.

<Directory "/home/user/public_html">
Options -Includes -ExecCGI
</Directory>

5. Set appropriate permissions for conf and bin directory

bin and conf directory should be viewed only by authorized users. It is good practice to create a group, and add all users who are allowed to view/modify the apache configuration files within this group.

Let say group name is: apacheadmin

Create the group.

groupadd apacheadmin

Allow access to bin directory for this group.

chown -R root:apacheadmin /usr/local/apache/bin
chmod -R 770 /usr/local/apache/bin

Allow access to conf directory for this group.

chown -R root:apacheadmin /usr/local/apache/conf
chmod -R 770 /usr/local/apache/conf

Add valid members to this group.

# nano /etc/group
apacheadmin:x:1121:sara,norman

6. Restrict access to root directory

Secure the root directory by setting the following in the httpd.conf

<Directory />
Options None
Order deny,allow
Deny from all
</Directory>

7. Restrict PHP Information Leakage

By Default PHP installation exposes to the world that PHP is installed on the server, which includes the PHP version within the HTTP header

To hide this values from header edit php.ini and update below directive to Off

expose_php = Off

8. Disable Remote Code Execution in PHP

If allow_url_fopen is enabled on your server setup, It allows ile functions like file_get_contents() and the include and require statements which can fetch the data from http or ftp remote locations and execute their code.

allow_url_fopen=Off
allow_url_include=Off

9. Disabling Dangerous PHP Functions

We can disable any php functions using disable_functions directive in php configuration file. Disable all the functions which can be harmful and not used in applications.

disable_functions =exec,shell_exec,passthru,system,popen,curl_exec,
curl_multi_exec,parse_ini_file,show_source,proc_open,pcntl_exec

10. Limit PHP Access To File System

We can use the open_basedir directive which allowed the PHP to access files
open_basedir=”/home/user/public_html”

11. Disable Unused PHP Modules

We can disable any unused module to load in system by changing configuration file name.

# cd /etc/php.d/
# mv oci8.ini oci8.ini.disable

12. Enable Limits in PHP (PHP)

To allow users to upload files of maximum size, update following configuration value.

upload_max_filesize = 2M # Maximum 2M of file user can upload

Maximum execution time of each script
max_execution_time = 30 # seconds

Maximum amount of time each script may spend parsing request data

max_input_time = 60 # seconds

13. Restrict MySQL Remote Access

To disable all remote connections for database server. The easiest way to do it to force MySQL server to listen only on 127.0.0.1 (localhost).

Edit MySQL configuration file and update following value.

bind-address=127.0.0.1

14. Disable use of LOCAL INFILE in MySQL

Enabling LOCAL INFILE can be dangerous for you system security. If LOCAL INFILE is enabled on server, a user can load any file ( like /etc/passwd, /etc/shadow ) easily.

To disable this edit MySQL configuration file and add following value under [mysqld] section.

[mysqld]
local-infile=0

15. Create Application Specific User in MySQL

Do not use mysql ‘root’ user for accessing database through application. It can be dangerous for your system. So make sure to create and use application specific user with limited access on application database only. Do following:

root@tecadmin:~# mysql -u root -p

mysql> CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE ON mydb.* TO 'user'@'
localhost' IDENTIFIED BY 'password';
mysql> FLUSH PRIVILEGES;

16. Improve Security with mysql_secure_installation

After installing MySQL mysql_secure_installation command is very useful for securing MySQL server. This will also setup password protection on root user.

mysql_secure_installation
"Only required output is showing below. In actual you will see more 
output on-screen"

Change the root password? [Y/n] y
New password: **********
Re-enter new password: **********

Remove anonymous users? [Y/n] y
Disallow root login remotely? [Y/n] y
Remove test database and access to it? [Y/n] y
Reload privilege tables now? [Y/n] y

17. Protect Configuration Files (Apache/MySQL/PHP)

In this section we will protect all our server configuration files used in LAMP Stack:

# chattr +i /etc/php.ini
# chattr +i /etc/php.d/*
# chattr +i /etc/my.cnf
# chattr +i /etc/httpd/conf/httpd.conf

please note that after enabling write protection no user including root would be able to update these file. In case if you need to update any of files, disable write protection first using below command.

# chattr -i filename

That’s all, We hope this article helped you to secure LAMP Stack . Please check and give your opinion below if you experience any issues or to discuss your ideas and experiences. 

One Response

  1. Steve
    Steve at | | Reply

    Great article man! Helped out a newbie a lot!

Leave a Reply

Register to Get FREE Offers

Why Pay for Software when you can GET it for FREE

JOIN US TONIGHT!