- Date: July 15, 2008
- Author: Joe Stewart, Director of Malware Research, SecureWorks
Although little-known at this time, the Coreflood botnet has had a major impact in the past year, both in terms of who it's infecting and how it's infecting them. Some organizations have seen outbreaks of hundreds or even thousands of computers.
So how does the security team at an impacted enterprise tackle cleaning up such a massive infection? Well, if they are a large-enough customer of an antivirus firm, they might be able to get detection added to their desktop AV (assuming that they can locate the right piece of malware and send it to their customer rep, and assuming the malware has not disabled AV updates on all the infected computers). Or they might script a manual removal process and execute it on all computers on the Windows domain (after all, that capabilitity is what Coreflood used to infect them all at once). It would still take quite a few hours of work, but that doesn't compare at all to how much work it would be to visit each workstation individually and remove the bot.
However, the fastest way to remove Coreflood en masse from a network might be to use the botnet's own command-and-control syntax. That's right, among the many commands that Coreflood can use to spy on your browsing activity or steal certificates, cookies and email logins, it also includes an "uninstall" command.
So, how can we put this to use? Well, all we need to do is redirect any traffic destined for the Coreflood controller from infected machines on our network to a webserver we control, and send the proper response when the bots try and check-in with the server, which they already do at regular intervals. Normally, the traffic flow on the network might resemble the diagram below:
We can set up our own simulated control server on any webserver and send the uninstall command. Rather than have to deal with reconfiguring an existing webserver to run our script, we can run our own simplified HTTP daemon using the Perl script below. Two things to note - port 80 must not already be in use by some other daemon, and the script must run as root in order to bind to port 80. Running a daemon as root may be a security risk, but hopefully the script is small enough to be easily audited (author assumes no responsibility for security flaws that may exist in Perl itself). For administrators nervous about running the disinfection daemon as root, it is always possible to bind the service to a port greater than 1024, and run as a less-privileged user, then use netfilter rules to redirect traffic on port 80 to the higher port.
#!/usr/bin/perl# removeaf.pl - Coreflood removal daemonuse
HTTP::Daemon;use HTTP::Status;my $bindaddr = "0.0.0.0";
my $port = 80;my $d = HTTP::Daemon->
new( LocalAddr => $bindaddr, LocalPort => $port );
while ( my $c = $d->accept )
{ while ( my $r = $c->get_request )
{ printf "%s: %s %s\n", $c->peerhost, $r->method, $r->url->path;
if ( $r->method eq 'POST' and $r-> url->path eq "/c/a" )
{$c->send_response( 200, "OK", HTTP::Headers->
new( "Content-Type" =>"text/plain"), "uninstall\n"); }
elsif ( $r->url->path =~ "/cgi-bin/.*\.php" )
{$c-> send_response( 200, "OK",
HTTP::Headers-> new( "Content-Type" => "text/plain" ),
"dropself \n\n" ); }
else {$c->send_error(RC_FORBIDDEN); } }
$c->close; undef($c); }
Once we have a server on our internal network running our removal daemon, we just need to redirect any infected internal hosts to it instead of the real Coreflood controller. This can be accomplished in a number of ways. The simplest one is probably to use interface aliasing on the removal server along with a static route statement on the gateway.
Creating an interface alias:
On the disinfection server (which is on a network directly attached to our router or gateway), we create an interface alias using the IP address of the real Coreflood controller. For instance, if the real controller IP were 1.2.3.4, we issue one of the following commands on the disinfection server (be sure to replace the interface name with the correct device for your platform):
Linux:
ifconfig eth0:0 1.2.3.4 netmask 255.255.255.255
*BSD:
ifconfig ep0 inet 1.2.3.4 netmask 255.255.255.255 alias
Creating a static route:
Now our disinfection server has the same IP address as the real controller, except it is physically located on our internal network. In order for the internal infected machines to be able to find our disinfection server, we need to add a static route on the network to tell machines looking for 1.2.3.4 that they should contact our disinfection server instead. If our disinfection server's IP address on eth0 were 10.1.1.10, the route statement to run on the gateway or router (not the disinfection server) might look something like:
Cisco IOS:
ip route 1.2.3.4 255.255.255.255 10.1.1.10
Linux:
route add -host 1.2.3.4 gw 10.1.1.10
*BSD:
route add -host 1.2.3.4 10.1.1.10
Of course, this will only work if the disinfection server is physically located on the same network as one of the gateway/router interfaces.
After this, our traffic flow from the infected hosts should look like the following diagram:
The removal daemon will print out each IP address that requests a file from the disinfection server, so the network administrator can follow up with the infected user, letting them know their data may have been compromised and changing passwords on all the user's accounts is in order.
To identify infected hosts ahead of disinfection, the following Snort signature can be deployed:
alert tcp any any ->
any 80 (msg:"Coreflood/AFcore trojan infection";
flags:A+; content:"POST|20|/c/a";
byte_test:1,<,64,0,relative; content:"HTTP/1.0|0d0a|Host|3a20|";
within:21; classtype:trojan-activity;
reference:url,www.secureworks.com/research/threats/coreflood;
sid:99999999; rev:1;)
Of course, all the usual disclaimers apply to the removal method - use at your own risk, etc. Does this method currently work? Yes, we've tested it and it works. Will it always work? This isn't guaranteed, the Coreflood code could change at any time. We know it works on Coreflood versions up to build 3118 (AF-3.1/test18). The version number can be seen in the POST data sent by infected clients back to the controller (variable "v"). However it would be always be advisable to test disinfection on a single host before attempting to clean the entire network.