Home ·  Knowledge Base ·  News ·  Contact  

 Knowledge Base


Web Servers

Mail Servers

FTP Servers

Firewall / Security

Intrusion Detection

FreeBSD General

Solaris General

Linux General







 Web Servers

Go Back  ·   Related Links

Apache/PHP4/Mysql hardening techniques (including chroot)  

To chroot Apache using mod_security, harden PHP via basic security configurations, harden MySQL and allow our chroot'd Apache to connect to MySQL socket.

ModSecurity is an open source intrusion detection and prevention engine for web applications. Operating as an Apache Web server module, the purpose of ModSecurity is to increase web application security, protecting web applications from known and unknown attacks.

The version of mod_security that we need is 1.8.6. Currently portage only as 1.7.6 and this version does not support chroot and is lacking in some features. To get the the stable 1.8.6 version we need to create an ebuild and 'overlay' existing portage tree.

The mod_security ebuild can be found here:

To create the 'overlay' we need to first edit /etc/make.conf and add the following value:

Then we need to create our overlay portage tree and get the ebuild
mkdir -p /usr/local/portage/net-www/mod_security
cd /usr/local/portage/net-www/mod_security
wget http://www.seekline.net/gentoo/ebuilds/net-www/mod_security/mod_security-1.8.6.ebuild

After receiving the ebuild, a digest will need to be made:
ebuild mod_security-1.8.6.ebuild digest

Since this version is greater than the current version we need to add this to /etc/portage/package.keywords
net-www/mod_security ~x86

To maintain this package during later emerge syncs|emerge world (to prevent 'downgrade' flag) we need to add this to package.unmask

Now we can emerge mod_security
emerge -v mod_security

Setting mod_security to chroot, edit /etc/apache2/conf/modules.d/99_mod_security.conf
SecChrootDir /var/chroot/apache

Since we're chroot'ing Apache the init script will not know where to grap the pid to stop the server, so we'll need to edit /etc/conf.d/apache2 and add the following:
While we are in here, change the following flags so that apache starts with PHP4 and MOD_SECURITY:

After chroot environment is set up (documented next) test to see if pid is dropped in the correct directory.

/etc/init.d/apache2 start

Initial 'jail' setup. Chroot jail will exist in /var/chroot/apache. We'll need to create some required directories for Apache and MySQL to work together.

mkdir -p /var/chroot/apache/var/run/mysqld
mkdir -p /var/chroot/apache/var/www
chown mysql:mysql /var/chroot/apache/var/run/mysqld

During the chroot process, Apache will drop it's pid file in /var/chroot/apache/var/run and the MySQL socket will need to be in /var/chroot/apache/var/run/mysqld/ for php to connect to MySQL. To do the later, just edit /etc/mysql/my.cnf and add the following:
socket = /var/chroot/apache/var/run/mysqld/mysqld.sock

Also, you will want to create the following bash alias:
alias mysql="mysql -S /var/chroot/apache/var/run/mysqld/mysqld.sock"
This way, when you run mysql from the command line, it will connect to the correct socket.

For chroot to work with mod_security, we still need a 'fake' directory in /var/www/localhost/htdocs. This is due to configuration check on Apache on start. It will complain that the directory is not there.. but once Apache is loaded it will fall into jail.

Here are some config options that will aide in harding Apache.

Disable non-needed modules:
LoadModule access_module modules/mod_access.so
LoadModule auth_module modules/mod_auth.so
#LoadModule auth_anon_module modules/mod_auth_anon.so
#LoadModule auth_dbm_module modules/mod_auth_dbm.so
#LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule include_module modules/mod_include.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
#LoadModule mime_magic_module modules/mod_mime_magic.so
#LoadModule cern_meta_module modules/mod_cern_meta.so
#LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
#LoadModule usertrack_module modules/mod_usertrack.so
#LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
#LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_connect_module modules/mod_proxy_connect.so
#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
#LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule mime_module modules/mod_mime.so
LoadModule status_module modules/mod_status.so
#LoadModule autoindex_module modules/mod_autoindex.so
#LoadModule asis_module modules/mod_asis.so
#LoadModule info_module modules/mod_info.so
#LoadModule cgi_module modules/mod_cgi.so
#LoadModule cgid_module modules/mod_cgid.so
LoadModule vhost_alias_module modules/mod_vhost_alias.so
#LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
#LoadModule imap_module modules/mod_imap.so
#LoadModule actions_module modules/mod_actions.so
#LoadModule speling_module modules/mod_speling.so
#LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
### New Modules for 2.0 (some are experimental)
#LoadModule file_cache_module modules/mod_file_cache.so
#LoadModule echo_module modules/mod_echo.so
#LoadModule charset_lite_module modules/mod_charset_lite.so
#LoadModule cache_module modules/mod_cache.so
#LoadModule disk_cache_module modules/mod_disk_cache.so
#LoadModule mem_cache_module modules/mod_mem_cache.so
#LoadModule ext_filter_module modules/mod_ext_filter.so
#LoadModule case_filter_module modules/mod_case_filter.so
#LoadModule case_filter_in_module modules/mod_case_filter_in.so
#LoadModule deflate_module modules/mod_deflate.so
#LoadModule optional_hook_export_module modules/mod_optional_hook_export.so
#LoadModule optional_hook_import_module modules/mod_optional_hook_import.so
#LoadModule optional_fn_import_module modules/mod_optional_fn_import.so
#LoadModule optional_fn_export_module modules/mod_optional_fn_export.so
#LoadModule bucketeer_module modules/mod_bucketeer.so
#LoadModule logio_module modules/mod_logio.so

Prevent information disclosure.
ServerAdmin admin@domain.com
ServerTokens Prod
ServerSignature Off

ServerTokens Prod will not display module information (mod_php, etc)
ServerSignature Off will on display Apache in the headers, no version numbers, etc.

We recommend compiling PHP without POSIX support. This USE flag is not available, so the custom configuration option will need to be added. To preserve this change we'll need to add it to our portage tree overlay. This value is stored in an eclass file so a directory to store eclasses will need to be made.
mkdir /usr/local/portage/eclass

First we'll copy the eclass to our overlay and edit that file with custom configuration flag.
cp /usr/portage/eclass/php-sapi.eclass /usr/local/portage/eclass/php-sapi.eclass
vi /usr/local/portage/eclass/php-sapi.eclass

Add this value
myconf="${myconf} ?disable-posix"

Make sure you have minimal use flags configured to you mod_php. Currently, only use flags used for mod_php were:

emerge -v mod_php

Here are some configuration options that were adjusted in /etc/php/apache2-php4/php.ini
safe_mode = on
Limits what php can do. Prevents system calls and heavily enforces file ownership

disable_functions = phpinfo, curl_exec, curl_init, passthru, show_source, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, shell_exec, system
Prevents php scripts to use these functions. These functions are 'high-end' system function and are not normally used in standard web applications.

expose_php = Off
Hides php info in headers

display_errors = Off
Will not display errors to the browser. A white screen will be presented if error occurs and is not handled via code.

log_errors = On
Make sure we log those php errors


Here are some basic configurations to MySQL to improve security. Edit /etc/mysql/my.cnf

socket = /var/chroot/apache/var/run/mysqld/mysqld.sock
This is where the socket will be dropped. This is required for PHP to communicate properly with MySQL while in chroot.

set-variable = local-infile=0
Prevent mysql to read and write files on the system

With this value set MySQL will not listen on tcp port 3306 and just listen with internal sockets

After everything is compiled and configured, restart the services.
/etc/init.d/apache2 restart
/etc/init.d/mysqld restart

1.check /var/chroot/apache/var/run for apache2.pid file.
2.check /var/chroot/apache/var/run/mysqld for mysqld.sock file
3.netstat -lnp and verify that mysqld is not listening on tcp 3306
4.netstat -lnp and verify that apache is listening on 80 and 443
5.ps aux | grep apache to make sure that Apache is started and the -D SECURITY flag is on
6.browse to localhost of the server to verify that Apache is serving pages.

Possible Issues:
1) Upon starting apache, you get the following:
No such file or directory: Cannot create SSLMutex with file `/var/cache/apache2/ssl_mutex.8136'
To fix this, do the following:
a) create a directory in /var/cache
-> mkdir /var/cache/apache2
That should do it.

2) If you have problems using php's mail() function inside of your chroot, check out this article


How's your network?, Inc. © 2001-2014