Hijacking System Calls For Hardening PHP - Debian Lenny And Squeeze is a library that integrates with the PHP interpreter and intercepts and manipulates the system calls provided by libc6. It replace the execve() syscall with a custom function which does extra sanity checking in order to prevent that an attacker could execute arbitrary code on the system exploiting a vulnerability in a web-based application (such as a bugged cms). It's open-source software released under the terms of the GPL license and compatible with PHP running as a CGI process or Apache's DSO module. The official website is

For this brand new project at the moment there aren't prebuilt packages, therefore to use it you must download the source code and compile it.

In order to install the compiler (gcc) with development libraries and header files, open a terminal and execute the following command:

apt-get install build-essential

The next step is to download source code so we can get the file using wget:


Now that you have everything you needed for installing the software, execute this command to generate the shared library file:

gcc -fPIC -shared -ldl -o amon.c

Finally move "" in the directory /lib:

mv ./ /lib/

Installation is complete and all that remains is to load modules into Apache.

Depending on your configuration you must follow one of the following methods:

1)If your PHP is executed via mod_fcgid, open the wrapper that calls the PHP and insert the string "export" inside it. For instance:

export PHPRC=/etc/php5/cgi
export LD_PRELOAD =
exec /usr/lib/cgi-bin/php

After that reload apache2:

/etc/init.d/apache2 restart

2) If the PHP interpreter works with Apache's suEXEC support, create a simple wrapper modifying your vhost configuration.

Add these directives:

ScriptAlias /php_amon/ "/usr/local/bin/"
AddHandler php-script .php
Action php-script /php_amon/php5-cgi

Create the file /usr/local/bin/php5-cgi and write in it:

exec /path/of/the/real/php5 "[email protected]"

Reload apache2:

/etc/init.d/apache2 restart

3) If you run PHP with libapache2-mod-php5, write in /etc/apache2/envvars the instruction


and reload the web service:

/etc/init.d/apache2 restart

To check if the library is loaded, write in a file the following PHP code and call it with a web browser:


That's all, your PHP installation has been hardened and you're protected from any web-based backdoor (such as r57shell) and script kiddies! If an attacker tries to execute a command not allowed (such as /bin/bash), an alert will be generated and saved in the site's error log.This is the log format:

sh: command_name: command not found

These are the only commands that the webuser can execute:


If you want to add or delete some commands edit the variable "char * cmds []" in the source code and recompile it.

Share this page:

Suggested articles

13 Comment(s)

Add comment


By: Anonymous

It's work with CentOS?
added to the file /etc/sysconfig/httpd
but nothing happens, and the phpinfo() can not see anything

By: Anonymous

This library isn't bound to one specific linux version, so it works also on centos.

Your php runs as module or cgi? Do you have copied the file into /lib?

By: Anonymous

What mean crash your vps?

Have you an error message?

I've been tested on various system and work properly.

By: Deckard

This tutorial is great however the amon keeps crashing my VPS :(

Maybe because I'm testing it on OpenVZ ??

By: yogg


Here is my amon.c File:
I have no idea how long this will be online. If someone have the possibility please provide it on a permanent way.

The logging is very simple and ugly ;)

With the two variables the location and the name of the Logfile can be changed:
char *acceptlog = "/var/log/amon/accept.log";
char *rejectlog = "/var/log/amon/reject.log";

This will definitely slow down the code execution. I can not say how much, but every time the lib is used there is an extra disc write.

Don't forget to set the rights for the logging path. On an fastcgi environment every site logs with its own user so I use 777. If the Logfile is not writeable the complete amon lib does not work anymore!

Also do not forget do add lograotate for the logfiles!


By: bob

Hi Yogg,

 Thanks alot your solutions works just fine for me ! 


 Bob Davis

By: yogg

Found the problem. works "recursive"

"/usr/bin/gm identify" uses "/usr/bin/gs".

The "" option is passed to all child processes. So always when an process uses the "execve" command to start a child process, it would be checked if this process is in the allowed list.

In my case I have allowed  "/usr/bin/gs" and everything works :)

I also have now implemented a very simple logging mechanism that logs all commands and if they are accepted or rejected.
So its very easy for me to see if there should be more commands in the accept list.



Hi Yogg,

 Is there any possibility for you to share this logging mechanism  ? Would be very much appreciated !

 Thanks !

 Best Regards,

By: Bob


 How exactly did you implement the logging mechanism is there any chance for you to make this public ? If so would you mind pasting the difference and a little ex-plainer would appreciate it very much.

 Kind Regards,



By: yogg


I use this lib on my new apache server.
It works really fine, but something is strange.

It seems that is not possible to execute "/usr/bin/gm identify /path/file" in the right way. If this command is executed there is no return value.
Without the extra lib the command works fine.

I have added a logging mechanism to see all commands. Also I have written an extra c file that uses the same command.

With the c file the " /usr/bin/gm identify /path/file" works without problems.

On php I get only 1 (for error) back :(

The command is used by Typo3 (4.5.2)


By: Phil

Good tips, I've written a PHP script to check all the additional security settings:

By: vasya

How to compile this in Debian 8 64 bit

command:gcc -fPIC -shared -ldl -o amon.c

send this or more errors:

/usr/include/x86_64-linux-gnu/bits/fcntl.h:40:5: error: unknown type name ‘__off_t’

By: Mikhail

-#define _FCNTL_H-#include <bits/fcntl.h>+#include <fcntl.h>