Stock CentOS with PHP SuPHP suhosin
From PhoenixWing
This article pertains to installing PHP from source code, along with the suhosin hardening patch and extension, and the SuPHP PHP wrapper on a CentOS 5.x Linux system.
REMEMBER Always make backups!
Contents |
Necessary RPM's
The following non-PHP related RPM's were installed:
httpd httpd-devel mysql mysql-server mysql-devel mod_ssl mod_auth_mysql perl-DBD-MySQL
In my case, I replaced the stock CentOS RPM's for MySQL with the one's from dev.mysql.com:
MySQL-client-community-5.1.22-0.rhel5.i386.rpm MySQL-devel-community-5.1.22-0.rhel5.i386.rpm MySQL-server-community-5.1.22-0.rhel5.i386.rpm MySQL-shared-compat-5.1.22-0.rhel5.i386.rpm
Optional RPM's
I consider these to be mandatory on a modern web server for the mere fact, that nearly all web developers utilize third party web applications that make use of them. Graphics utilities like GD and ImageMagick are used by most forum & bulletin board applications, and even security software such as CAPTCHA's may use GD and/or ImageMagick. Other additions include mod_python & mod_perl for those web developers that want cutting edge scripting abilities. With "cutting edge" in mind, I also have a habit of including the following (and all their dependencies):
mod_perl mod_python libtidy libtidy-devel gd gd-devel gd-progs ImageMagick ImageMagick-devel ImageMagick-perl
Download PHP, suhosin & SuPHP, then patch
- I setup a directory on a large partition for my own compiles at /storage/compile/ and store my downloads in /storage/tarballs/, however, you can place the downloads wherever you see fit. At my place of employment, we store tarballs & source to be compiled in /usr/src/SCRIPTS/.
- Download the latest PHP5 from http://www.php.net/
- Download the latest suhosin hardened patch *and* extension from http://www.suhosin.org/
- Download the latest SuPHP from http://www.suphp.org/
- Untar/gunzip PHP, suhosing extensions & the patch file. Place the patch file outside of the PHP source directory:
mv suhosin-patch-5.2.5-0.9.6.2.patch /storage/compile/
- Copy the suhosin extension source code into the PHP source tree's ext/suhosin directory:
cp -pr suhosin-0.9.22 /storage/compile/php-5.2.5/ext/suhosin
- Patch PHP with the suhosing patch:
patch -p 1 -i ../suhosin-patch-5.2.5-0.9.6.2.patch
- If successful, you should see something similar to:
patching file TSRM/TSRM.h patching file TSRM/tsrm_virtual_cwd.c patching file TSRM/tsrm_virtual_cwd.h patching file Zend/Makefile.am patching file Zend/Zend.dsp ... patching file sapi/apache/mod_php5.c patching file sapi/apache2filter/sapi_apache2.c patching file sapi/apache2handler/sapi_apache2.c patching file sapi/cgi/cgi_main.c patching file sapi/cli/php_cli.c patching file win32/build/config.w32
Configure & Compile PHP
- Change to the PHP source directory:
cd /storage/compile/php-5.2.5/
- Configure:
./buildconf --force
./configure --prefix=/usr --sysconfdir=/etc --with-config-file-path=/etc \ --enable-cgi --enable-force-cgi-redirect --enable-discard-path --with-mysql=/usr \ --enable-mbstring --with-bz2 --with-curl --enable-bcmath --enable-exif --with-gd \ --enable-gd-native-ttf --with-gettext --with-png-dir=/usr --with-jpeg-dir=/usr \ --with-freetype-dir=/usr --with-zlib --enable-calendar --with-openssl --with-gmp \ --enable-ftp --enable-magic-quotes --with-mcrypt --with-mhash --enable-ctype \ --enable-tidy --enable-dom --with-libxml-dir=/usr --enable-libxml --enable-xml \ --enable-xmlreader --enable-xmlwriter --enable-zip --enable-shmop --enable-wddx \ --with-pear --enable-pdo --with-pdo-mysql=/usr --disable-embedded-mysqli \ --with-mysqli=/usr/bin/mysql_config --enable-inline-optimization --enable-suhosin
- Compile:
make make test make install
- Copy the php.ini file to /etc:
cp ./php.ini-recommended /etc/php.ini
- Edit /etc/php.ini to suit. I recommend the following changes:
Change: short_open_tag = Off To: short_open_tag = On Change (lets you see full error messages): log_errors_max_len = 1024 To: log_errors_max_len = 0 Change (security): magic_quotes_gpc = Off To: magic_quotes_gpc = On Change: upload_max_filesize = 2M To: upload_max_filesize = 16M Change (I've seen this needed on many app'z, like [http://gallery.sf.net Gallery]): allow_url_include = Off To: allow_url_include = On Change (Set to your timezone, as found in /usr/share/zoneinfo/): ;date.timezone = To: date.timezone = America/Phoenix
Install SuPHP
- Untar/gunzip SuPHP source code, and go into the directory
cd /storage/compile/suphp-0.6.2
- HACK: Edit the following with your favorite editor:
nano src/apache2/mod_suphp.c - Find line 324 & 325 Change Line 324: ... suPHP_AddHandler", suphp_handle_cmd_add_handler, NULL, ACCESS_CONF, ... To: ... suPHP_AddHandler", suphp_handle_cmd_add_handler, NULL, RSRC_CONF | ACCESS_CONF, ... Change Line 325: ... suPHP_RemoveHandler", suphp_handle_cmd_remove_handler, NULL, ACCESS_CONF, ... To: ... suPHP_RemoveHandler", suphp_handle_cmd_remove_handler, NULL, RSRC_CONF | ACCESS_CONF, ...
- Configure suphp:
./configure --prefix=/usr --sysconfdir=/etc --enable-checkpath \ --with-apr=/usr --with-apxs=/usr/sbin/apxs --with-setid-mode=paranoid --with-min-uid=100 \ --with-min-gid=500 --with-apache-user=apache --with-logfile=/var/log/httpd/suphp_log
make make install
- Copy configuration file to /etc:
cp doc/suphp.conf-example /etc/suphp.conf
- Create mod_suphp.conf file for apache:
cd /etc/httpd/conf.d/ nano -w mod_suphp.conf (or your editor of choice: vi, joe, elvis, etc)
- mod_suphp.conf contents:
# This is the Apache server configuration file providing suPHP support. # It contains the configuration directives to instruct the server how to # serve php pages while switching to the user context before rendering. LoadModule suphp_module modules/mod_suphp.so # This option tells mod_suphp if a PHP-script requested on this server (or # VirtualHost) should be run with the PHP-interpreter or returned to the # browser "as it is". suPHP_Engine on # To use suPHP to parse PHP-Files AddHandler x-httpd-php .php .php5 .php4 .php3 .phtml # This option tells mod_suphp which path to pass on to the PHP-interpreter # (by setting the PHPRC environment variable). # Do *NOT* refer to a file but to the directory the file resides in. # # E.g.: If you want to use "/path/to/server/config/php.ini", use "suPHP_Config # /path/to/server/config". # # If you don't use this option, PHP will use its compiled in default path. suPHP_ConfigPath /etc # If you compiled suphp with setid-mode "force" or "paranoid", you can # specify the user- and groupname to run PHP-scripts with. # Example: suPHP_UserGroup foouser bargroup # # -NOTE- WE SET THIS ON A PER VHOST SETTING. DON'T SET HERE # # suPHP_UserGroup apache apache # This option tells mod_suphp to handle requests with the type <mime-type>. # Please note this only works, if an action for the handler is specified # in the suPHP configuration file. suPHP_AddHandler x-httpd-php # This option tells mod_suphp to NOT handle requests with the type <mime-type>. # suPHP_RemoveHandler <mime-type>
- Edit /etc/suphp.conf:
Change: logfile=/var/log/suphp.log To: logfile=/var/log/httpd/suphp_log Change: webserver_user=wwwrun To: webserver_user=apache Change: docroot=/ To: docroot=/var/www/virtual/ Change (if you're not concerned with security): errors_to_browser=false To: errors_to_browser=true Change: umask=0077 To: umask=0133 Change: min_gid=100 To: min_gid=500 Change: x-httpd-php=php:/usr/bin/php To: x-httpd-php=php:/usr/bin/php-cgi
Editing Apache and suPHP Configs
- First, I want to stop the loading of mod_php, or the PHP Apache module, if it exists, so it does not load on startup. To do this, rename the php module config file:
mv /etc/httpd/conf.d/php.conf /etc/httpd/conf.d/php.conf.orig2007
- Next, edit /etc/httpd/conf/httpd.conf file. In this example, we'll comment out a few global defaults, and make a few minor changes:
Change (For security reasons):
ServerTokens OS
To:
ServerTokens Prod
Change to your liking:
<IfModule prefork.c>
StartServers 8
MinSpareServers 5
MaxSpareServers 20
ServerLimit 256
MaxClients 256
MaxRequestsPerChild 4000
</IfModule>
Example:
<IfModule prefork.c>
StartServers 10
MinSpareServers 10
MaxSpareServers 25
ServerLimit 1024
MaxClients 1024
MaxRequestsPerChild 4000
</IfModule>
Change (if uncommented):
ServerName www.example.com:80
To:
#ServerName www.example.com:80
Change:
DirectoryIndex index.html index.html.var
To:
DirectoryIndex index.php index.html index.htm index.html.var
Change:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
To: (comment it out)
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
Change:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
To: (comment out example, copy and change end from "combinedio" to "combined")
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combined
Change:
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
To: (comment out global scope)
#ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
Change:
<Directory "/var/www/cgi-bin">
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
To: (comment out)
#<Directory "/var/www/cgi-bin">
# AllowOverride None
# Options None
# Order allow,deny
# Allow from all
#</Directory>
Now add NameVirtualHost & VirtualHost directives. Note that I have included "suPHP_UserGroup userid groupid", required for suPHP to work properly AND I've also enabled SuEXEC for CGI scripts. Example:
NameVirtualHost ip.add.re.ss:80
<VirtualHost ip.add.re.ss:80>
ServerAdmin webmaster@int.domain
ServerName web.int.domain
ServerAlias *.web.int.domain
SuexecUserGroup userid groupid
suPHP_UserGroup userid groupid
ErrorLog logs/web.int.domain-error_log
CustomLog logs/web.int.domain-access_log combined
DocumentRoot /var/www/virtual/default_vhost/htdocs
<Directory "/var/www/virtual/default_vhost/htdocs">
Options -Indexes SymLinksifOwnerMatch
AllowOverride Options FileInfo AuthConfig Limit
</Directory>
ScriptAlias /cgi-bin/ "/var/www/virtual/default_vhost/cgi-bin/"
<Directory "/var/www/virtual/default_vhost/cgi-bin/">
AllowOverride None
Options SymLinksifOwnerMatch
Order allow,deny
Allow from all
</Directory>
# Personal addition to disable TRACE method in Apache
<Directory "/var/www/virtual/default_vhost/cgi-bin/">
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
</Directory>
</VirtualHost>
Editing /etc/php.ini
Change the following under [sessions]:
session.save_path=/tmp/sess
Create the directory if necessary, and type:
chmod 1777 /tmp/sess
Creating a new /tmp if partition
If a /tmp partition was not created on a Linux system, you can go about creating one with the following:
cd /dev # Create 500MB file for our /tmp partition. If you need # more or less space, make count size larger or smaller. dd if=/dev/zero of=tmpMnt bs=1024 count=500000 # Make an EXT3 filesystem for our tmpMnt file /sbin/mke2fs -j /dev/tmpMnt # Backup your /tmp dir- I had mysql.sock file that I # needed to recreate the symbolic link for. Other # programs may use it to store cache files or whatever. cd / cp -r /tmp /tmp_backup # Mount the new /tmp filesystem with noexec, nosuid # and read/write, and set permissions. mount -o loop,noexec,nosuid,rw /dev/tmpMnt /tmp chmod 1777 /tmp # Copy everything back to new /tmp and remove backup cp -r /tmp_backup/* /tmp/ rm -rf /tmp_backup
