Cheap VPS & Xen Server

Residential Proxy Network - Hourly & Monthly Packages

How To Harden PHP5 With Suhosin On CentOS 5.4


This tutorial shows how to harden PHP5 with Suhosin on a CentOS 5.4 server. From the Suhosin project page: “Suhosin is an advanced protection system for PHP installations that was designed to protect servers and users from known and unknown flaws in PHP applications and the PHP core. Suhosin comes in two independent parts, that can be used separately or in combination. The first part is a small patch against the PHP core, that implements a few low-level protections against bufferoverflows or format string vulnerabilities and the second part is a powerful PHP extension that implements all the other protections.”

This document comes without warranty of any kind! I want to say that this is not the only way of setting up such a system. There are many ways of achieving this goal but this is the way I take. I do not issue any guarantee that this will work for you!

 

1 Preliminary Note

I have tested this on a CentOS 5.4 server with the IP address 192.168.0.100.

I will install both Suhosin parts in this tutorial, the Suhosin patch (for which we need to recompile PHP5) and the Suhosin PHP extension. To see what Suhosin can do, please refer to http://www.hardened-php.net/suhosin/a_feature_list.html. The features of the Suhosin patch are listed under Engine Protection (only with patch); all the other features come with the Suhosin extension.

 

2 Installing Apache2 And PHP5 (Optional)

(This chapter is optional if you already have Apache2 and PHP5 installed – please skip to the next chapter.)

If you don’t have Apache2 and PHP5 installed on your server, install it now:

yum install httpd php php-devel

Then create the system startup links for Apache2 and start Apache2:

chkconfig –levels 235 httpd on
/etc/init.d/httpd start

You now have a PHP5 with basic functionality on your server; if you need special PHP5 modules, you can search for them like this:

yum search php

From the output, pick the modules you need, install them like this and restart Apache2:

yum install php-gd php-imap php-ldap php-mysql php-odbc php-pear php-xml php-xmlrpc

/etc/init.d/httpd restart

 

3 Getting Details About Your PHP5 Installation

Unless you have already created virtual hosts in your Apache installation, the document root of the default web site is /var/www/html. We will now create a small PHP file (info.php) in that directory (if you have created virtual hosts, place it in any of the virtual hosts that has PHP enabled) and call it in a browser. The file will display lots of useful details about our PHP installation, such as the installed PHP version.

vi /var/www/html/info.php

<?php
phpinfo();
?>

Now we call that file in a browser (e.g. http://192.168.0.100/info.php):

1

2

As you see, our PHP version is 5.1.6, and Suhosin is not mentioned anywhere on that page which means it is not installed.

4 Installing Suhosin

Suhosin can be downloaded from here: http://www.hardened-php.net/suhosin/download.html

To install the Suhosin patch, we need to recompile PHP5 from the sources, but we will use the CentOS 5.4 PHP5 .src.rpm package for this (using the rpmbuild command), so that we get new PHP5 .rpm packages (with Suhosin) that we can install. That way, we don’t have to worry about the right PHP5 configuration options because rpmbuild will take care of this.

But first we grab a copy of the Hardened-PHP Project’s release signaturekey and import it into our GNU Privacy Guard keychain:

wget http://www.hardened-php.net/hardened-php-signature-key.asc
gpg –import < hardened-php-signature-key.asc

Then we download a PHP5 .src.rpm package (that suits our currently installed PHP version, 5.1.6 in this example) from a CentOS 5.4 mirror to /usr/src and install it:

cd /usr/src
wget http://ftp-stud.fht-esslingen.de/pub/Mirrors/centos/5.4/updates/SRPMS/php-5.1.6-24.el5_4.5.src.rpm

(As you see above, I download the newest PHP5 .src.rpm from the updates/ directory of my CentOS mirror; of course, you can also download the original .src.rpm from the os/ directory, e.g. http://ftp-stud.fht-esslingen.de/pub/Mirrors/centos/5.4/os/SRPMS/php-5.1.6-23.2.el5_3.src.rpm. If you do so, you’ll have to adjust the filenames in the rest of this tutorial.)

rpm -ivh php-5.1.6-24.el5_4.5.src.rpm

If you get warnings like these ones:

warning: user mockbuild does not exist – using root
warning: group mockbuild does not exist – using root

you can ignore them.

Next we download the Suhosin patch that suits our PHP version to /usr/src/redhat/SOURCES (you can find all available patches on the Suhosin downloads page):

cd /usr/src/redhat/SOURCES
wget http://www.hardened-php.net/suhosin/_media/suhosin-patch-5.1.6-0.9.6.patch.gz

We should check now that the MD5 sum of the downloaded patch is identical to the one published on the Suhosin downloads page:

md5sum suhosin-patch-5.1.6-0.9.6.patch.gz

If the MD5 sum is ok, we can check the digital signature like this:

wget http://www.hardened-php.net/suhosin/_media/suhosin-patch-5.1.6-0.9.6.patch.gz.sig
gpg suhosin-patch-5.1.6-0.9.6.patch.gz.sig

If you see this line in the output:

gpg: Good signature from “Hardened-PHP Signature Key”

everything is ok with the downloaded patch, and we can proceed.

Now we unpack the Suhosin patch, rename it so that it fits into the CentOS naming scheme, and modify the file /usr/src/redhat/SPECS/php.spec so that the rpmbuild command knows it has to include the Suhosin patch when it rebuilds PHP5:

gunzip suhosin-patch-5.1.6-0.9.6.patch.gz
mv suhosin-patch-5.1.6-0.9.6.patch php-5.1.6-suhosin.patch
cd /usr/src/redhat/SPECS/
vi php.spec

Add Patch112: php-5.1.6-suhosin.patch to the stanza where all patches are listed and comment out the line Patch14: php-5.1.6-ecalloc.patch in the same stanza (the ecalloc patch conflicts with Suhosin), and then add %patch112 -p1 -b .suhosin to the %setup -q stanza and comment out the line %patch14 -p1 -b .ecalloc in the same stanza:

[...]
Source51: php.ini

Patch1: php-5.1.4-gnusrc.patch
Patch2: php-5.1.4-warnings.patch
Patch5: php-4.3.3-install.patch
Patch6: php-5.0.4-norpath.patch
Patch7: php-4.3.2-libtool15.patch
Patch13: php-5.0.2-phpize64.patch
#Patch14: php-5.1.6-ecalloc.patch
Patch15: php-5.2.0-includedir.patch
Patch16: php-5.1.6-bug38534.patch
Patch17: php-5.1.6-umask.patch
Patch18: php-4.3.9-metaphone.patch
Patch19: php-5.1.6-zendecase.patch
Patch20: php-5.1.6-zendhash.patch
[...]
Patch104: php-5.1.6-mbstring-overload-func.patch
Patch105: php-5.1.6-gdoverflow.patch
Patch106: php-5.1.6-CVE-2009-3546.patch
Patch107: php-5.1.6-CVE-2009-3291.patch
Patch108: php-5.1.6-CVE-2009-3292.patch
Patch109: php-5.1.6-CVE-2009-4017.patch
Patch110: php-5.1.6-CVE-2009-2687.patch
Patch111: php-5.1.6-CVE-2009-4142.patch
Patch112: php-5.1.6-suhosin.patch
[...]
%setup -q
%patch1 -p1 -b .gnusrc
%patch2 -p1 -b .warnings
%patch5 -p1 -b .install
%patch6 -p1 -b .norpath
%patch7 -p1 -b .libtool15
%patch13 -p1 -b .phpize64
#%patch14 -p1 -b .ecalloc
%patch15 -p1 -b .includedir
%patch16 -p1 -b .bug38534
%patch17 -p1 -b .umask
%patch18 -p1 -b .metaphone
%patch19 -p1 -b .zendecase
%patch20 -p1 -b .zendhash
[...]
%patch104 -p1 -b .mbstring-overload-func
%patch106 -p1 -b .cve3546
%patch107 -p1 -b .cve3291
%patch108 -p1 -b .cve3292
%patch109 -p1 -b .cve4017
%patch110 -p1 -b .cve2687
%patch111 -p1 -b .cve4142
%patch112 -p1 -b .suhosin
[...]

If you are on an x86_64 system, you need to install apr-devel.x86_64 (don’t do it if you are on an i386 system!)…

yum install apr-devel.x86_64

… because otherwise you will see the following error message when you try to rebuild PHP5:

cannot open /httpd/build/config_vars.mk: No such file or directory at /usr/sbin/apxs line 201.

Now we rebuild PHP5:

rpmbuild -ba php.spec

Depending on what PHP5 modules you have installed, rpmbuild will most likely complain about missing packages that it needs to build new packages for the various PHP5 modules:

[root@server1 SPECS]# rpmbuild -ba php.spec
cat: /usr/include/httpd/.mmn: No such file or directory
error: Failed build dependencies:
aspell-devel >= 0.50.0 is needed by php-5.1.6-24.5.x86_64
httpd-devel >= 2.0.46-1 is needed by php-5.1.6-24.5.x86_64
libjpeg-devel is needed by php-5.1.6-24.5.x86_64
libpng-devel is needed by php-5.1.6-24.5.x86_64
pcre-devel >= 4.5 is needed by php-5.1.6-24.5.x86_64
libc-client-devel is needed by php-5.1.6-24.5.x86_64
mysql-devel >= 4.1.0 is needed by php-5.1.6-24.5.x86_64
postgresql-devel is needed by php-5.1.6-24.5.x86_64
unixODBC-devel is needed by php-5.1.6-24.5.x86_64
net-snmp-devel is needed by php-5.1.6-24.5.x86_64
gd-devel is needed by php-5.1.6-24.5.x86_64
freetype-devel is needed by php-5.1.6-24.5.x86_64
[root@server1 SPECS]#

If you see an error like this, install the missing packages, e.g. like this:

yum install aspell-devel httpd-devel libjpeg-devel libpng-devel pcre-devel libc-client-devel mysql-devel postgresql-devel unixODBC-devel net-snmp-devel gd-devel freetype-devel

Afterwards, run rpmbuild again:

rpmbuild -ba php.spec

This should now compile PHP5 and all installed PHP5 modules again and create new .rpm packages in the /usr/src/redhat/RPMS/i386 directory (if you are on an i386 system) or in the /usr/src/redhat/RPMS/x86_64 directory (if you are on an x86_64 system). This can take some time, so please be patient.

Afterwards, we can install the new PHP5 packages like this:

i386:

cd /usr/src/redhat/RPMS/i386
rpm -Uvh –force php-*

x86_64:

cd /usr/src/redhat/RPMS/x86_64
rpm -Uvh –force php-*

That’s it for the Suhosin patch.

Now we are going to build the Suhosin PHP extension. First we download its sources to the /usr/src directory (the sources of the Suhosin extension are available on the Suhosin downloads page):

cd /usr/src
wget http://download.suhosin.org/suhosin-0.9.29.tgz

Next we check the MD5 sum and the signature again:

md5sum suhosin-0.9.29.tgz

wget http://download.suhosin.org/suhosin-0.9.29.tgz.sig
gpg suhosin-0.9.29.tgz.sig

Then we unpack the sources and build the extension like this:

tar xvfz suhosin-0.9.29.tgz
cd suhosin-0.9.29
phpize
./configure
make
make install

To enable the Suhosin extension, we create the file /etc/php.d/suhosin.ini and put the line extension=suhosin.so into it:

vi /etc/php.d/suhosin.ini

extension=suhosin.so

All that is left to do now is restart Apache2:

/etc/init.d/httpd restart

Now let’s call our info.php page again in a browser (e.g. http://192.168.0.100/info.php). If everything went ok, you should now see Suhosin mentioned in two places on the page:

3

4

That’s it. If you like you can configure Suhosin (see http://www.hardened-php.net/suhosin/configuration.html), although Suhosin will work out of the box with its default configuration, so be sure that you know what you’re doing.

 

  • Suhosin: http://www.hardened-php.net/suhosin/index.html
  • PHP: http://www.php.net/
  • CentOS: http://www.centos.org/

 

 

 

Comments

comments