amon.so: Hijacking System Calls For Hardening PHP - Debian Lenny And Squeeze

Want to support HowtoForge? Become a subscriber!
 
Submitted by radish2003 (Contact Author) (Forums) on Fri, 2011-04-08 13:00. :: Debian | Apache | PHP

amon.so: Hijacking System Calls For Hardening PHP - Debian Lenny And Squeeze

amon.so 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 http://www.lucaercoli.it/

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:

wget http://www.lucaercoli.it/amon/amon.c

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.so amon.c

Finally move "amon.so" in the directory /lib:

mv ./amon.so /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 LD_PRELOAD=amon.so" inside it. For instance:

#!/bin/sh
export PHPRC=/etc/php5/cgi
export LD_PRELOAD = amon.so
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:

#!/bin/sh
export LD_PRELOAD=amon.so
exec /path/of/the/real/php5 "$@"

Reload apache2:

/etc/init.d/apache2 restart

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

export LD_PRELOAD=amon.so

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:

<?php
phpinfo();
?>

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:

"/usr/sbin/sendmail"
"/usr/lib/sendmail"
"/etc/alternatives/lib.sendmail"
"/usr/lib/sm.bin/sendmail"
"/usr/bin/mail"
"/bin/mv"
"/bin/rm"
"/usr/bin/unlink"
"/bin/rmdir"
"/bin/cp"
"/bin/date"
"/bin/bzip2"
"/bin/gunzip"
"/bin/gzip"
"/usr/bin/unzip"
"/bin/tar"
"/usr/bin/host"
"/usr/bin/file"
"/usr/bin/uptime"
"/bin/grep"
"/usr/bin/diff3"
"/bin/pwd"

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


Please do not use the comment function to ask for help! If you need help, please use our forum.
Comments will be published after administrator approval.
Submitted by Phil (not registered) on Sat, 2011-06-25 05:33.

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

http://www.idontplaydarts.com/2011/02/hardening-and-securing-php-on-linux/

Submitted by yogg (not registered) on Thu, 2011-05-12 14:11.

Hi

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)

yogg

Submitted by yogg (not registered) on Thu, 2011-05-12 16:25.

Found the problem.

amon.so works "recursive"

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

The "LD_PRELOAD=amon.so" 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.

yogg

Submitted by bobdavis (registered user) on Fri, 2011-05-20 04:25.

Hi Yogg,

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

 Thanks !

 Best Regards,

Submitted by Bob (not registered) on Fri, 2011-05-20 04:09.

@yogg

 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,

 

 

Submitted by yogg (not registered) on Mon, 2011-05-23 16:01.

Hi

Here is my amon.c File:
http://paste.pocoo.org/show/393679/
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:
const
char *acceptlog = "/var/log/amon/accept.log";
const
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 amon.so 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!

yogg

Submitted by bob (not registered) on Sat, 2011-05-28 21:38.

Hi Yogg,

 Thanks alot your solutions works just fine for me ! 

 Regards,

 Bob Davis

Submitted by Deckard (not registered) on Tue, 2011-04-19 22:56.

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

Maybe because I'm testing it on OpenVZ ??

Submitted by Anonymous (not registered) on Thu, 2011-04-21 11:00.

What mean crash your vps?

Have you an error message?

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

Submitted by Anonymous (not registered) on Sat, 2011-04-16 01:18.

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

Submitted by Anonymous (not registered) on Mon, 2011-04-18 18:18.
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 amon.so into /lib?