Autore Topic: Sito Hackerato:RISOLTO senza reinstallare tutto  (Letto 9236 volte)

Offline aletochigno

  • Esploratore
  • **
  • Post: 96
  • Sesso: Maschio
    • Mostra profilo
Sito Hackerato:RISOLTO senza reinstallare tutto
« il: 28 Set 2011, 17:16:33 »
Scrivo questo post per raccontare come ho potuto risolvere un problema che a quanto pare è molto diffuso,ovvero quando il sito viene hackerato.
Un anno fa inizio a realizzare un sito web appoggiandomi su altervista caricando joomla 1.5.22.
Dopo un po' di tempo speso lavorandoci sopra,per problemi non dipendenti da me lo lascio stare così com'è e smetto di lavorarci.
Qualche settimana fa mi viene chiesto di ricominciare a lavorare sul sito web,e di spostarlo su un hosting a pagamento.Dopo aver acquistato l'hosting vado in ftp su altervista,copio tutti i files e le cartelle ,faccio il backup del database e lo carico su nuovo hosting,ovviamente modificando il file configuration.php con i parametri relativi al nuovo hosting.
Apparentemente con firefox funziona,soltanto che non visualizzo le immagini.
Con firebug noto che il path di ogni immagine corrisponde a quello di altervista...mah.
Va bene,riscrivo i path corretti.
Vado ad aprire il sito con chrome e mi appare la pagina con l'allerta che il sito è pericoloso,che contiene malware e che se decido di entrare è a mio rischio.
Così decido di fare una scansione ,come consigliato, utilizzando gli strumenti per webmasters di google,che ovviamente non rileva assolutamente nulla.
Entro in ftp ,apro il file index.php e vedo che in alto ,le prime due righe contengono dei links che non conosco in mezzo a caratteri alfanumerici random,del tipo a3d0f8jk65f3e22...ecc
Apro il file index.html che stranamente pesa 144kb(troppo per una sola linea di codice) e vedo che anche lì ci sono dei links ,con una parola ricorrente :indometastan.
Inizio a cercare la soluzione sul forum seguendo  la strada dell'installazione da zero di joomla e poi la successiva sovrascrittura dei files di backup del sito.
Cosa accade?Che quando vado a digitare l'indirizzo del sito mi appare il testo della pagina index.php come spiegato nel seguente post :  http://forum.joomla.it/index.php/topic,145154.msg646965.html#msg646965.
Provo ad installare all'interno di una sottocartella del sito la versione 1.7......idem,visualizza la pagina con il testo scritto nella index.php.........Manca l'interprete php!
Riprovo a cancellare tutto e ricaricare per 4 o 5 volte..estenuante.
Così inizio a cercare degli strumenti più attendibili rispetto a google webmasters tools.
Uno di questi è http://www.ipvoid.com/ che esegue la scansione dell'ip del sito per trovare codici malware.
Un altro è http://sitecheck.sucuri.net/scanner/(la scansione è gratuita,la pulizia automatica del sito no)<posso inserirlo nel forum?>
Questi mi rilevano il malware in varie pagine.
Così metto in sicurezza il sito,mettendolo offline e cambiando tutte le password possibili(ftp,pannello di controllo,DB,accesso admin ecc).
Finalmente riesco a trovare ciò che mi serve:uno script che analizza il sito e mi dice esattamente in quali files ci sono i codici malware.La maggior parte dei files modificati si trovano nei templates,ed inizialmente,prima di usare questo script,li avevo cancellati tutti.Lo trovate qui: http://redleg-redleg.blogspot.com/p/simple-script-to-find-base64decode-in.html
Per utilizzare lo script bisogna incollarlo in un file che chiameremo ad esempio revealer.php e lo copiamo nella root del sito joomla.
Dopodichè aprendo il browser bisogna digitare l'indirizzo del sito ad esempio http://www.miosito.com/revealer.php.
A questo punto lo script inizia a funzionare ed il tempo che può impiegare varia a seconda della grandezza del vostro sito.
Il risultato ottenuto lo potete vedere nella pagina esempio in allegato:

Così non rimane altro che entrare nei files indicati e cancellare le linee scritte dal malware.

Riprovando a scansionare con i tools online descritti sopra finalmente il sito è risultato pulito.
Inoltre navigando con chrome non è più apparso il messaggio di pericolo malware per il sito.

Una nota del creatore dello script di analisi:"Lo script funziona con la maggior parte dei siti web,l'importante è che la versione di php sia dalla 5 in poi."
Spero di esser stato chiaro e soprattutto utile.




[allegato vecchio più di un anno eliminato da un amministratore]

Offline jabber

  • Esploratore
  • **
  • Post: 114
    • Mostra profilo
Re:Sito Hackerato:RISOLTO senza reinstallare tutto
« Risposta #1 il: 28 Set 2011, 18:23:18 »
Grazie 1000, le info che dai in questo post sono veramente interessanti.

Ciao
   J

Offline Faurinz

  • Nuovo arrivato
  • *
  • Post: 14
    • Mostra profilo
Re:Sito Hackerato:RISOLTO senza reinstallare tutto
« Risposta #2 il: 16 Gen 2012, 14:46:09 »
Anche io ho avuto lo stesso problema e ho fatto col file revealer come hai detto tu!
Scusa l'ignoranza ma come faccio a riconoscere quali sono le righe di codice scritte dal malware?
è per caso: $code ='    PtxWPFNtVPNtWUS1MKW5VQ0tVyA....????

Offline aletochigno

  • Esploratore
  • **
  • Post: 96
  • Sesso: Maschio
    • Mostra profilo
Re:Sito Hackerato:RISOLTO senza reinstallare tutto
« Risposta #3 il: 16 Gen 2012, 14:56:09 »
Si,i codici maligni sono all'inizio del file.Alcuni vengono duplicati più in basso.Poi li vedi sono stringhe lunghissime di caratteri alfanumerici..

Offline Faurinz

  • Nuovo arrivato
  • *
  • Post: 14
    • Mostra profilo
Re:Sito Hackerato:RISOLTO senza reinstallare tutto
« Risposta #4 il: 16 Gen 2012, 15:14:25 »
scusa ma tipo in questo file qui non c'è niente giusto???
perchè il revealer.php continua a dirmi che è infetto...

Codice: [Seleziona]
<?php
/**
 * Joom!Fish - Multi Lingual extention and translation 
manager for Joomla!
 * Copyright (C) 2003-2009 Think Network GmbH, 
Munich
 *
 * All rights reserved.  The Joom!Fish project is 
a set of extentions for
 * the content management system Joomla!. It 
enables Joomla!
 * to manage multi lingual sites especially in all 
dynamic information
 * which are stored in the 
database.
 *
 * This program is free software; you can 
redistribute it and/or
 * modify it under the terms of the GNU General 
Public License
 * as published by the Free Software Foundation; either 
version 2
 * of the License, or (at your option) any later 
version.
 *
 * This program is distributed in the hope that it 
will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied 
warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 See the
 * GNU General Public License for more 
details.
 *
 * You should have received a copy of the GNU 
General Public License
 * along with this program; if not, write to the 
Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, 
MA  02111-1307,USA.
 *
 * The "GNU General Public License" 
(GPL) is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
-----------------------------------------------------------------------------
 * 
$Id: JCacheStorageJFDB.php 1344 2009-06-18 11:50:09Z akede $
 * @package 
joomfish
 * @subpackage cache
 *
*/


// Check to 
ensure this file is within the rest of the framework
defined
('JPATH_BASE') or 
die();

//Register class that don't follow one file per class naming 
conventions
JLoader
::register('JCacheStorage' JPATH_LIBRARIES .DS
'joomla'.DS.'cache' .DS.'storage.php');

/**
 * Joomfish Cache 
Class
 *
 * @author        Geraint Edwards 
(http://www.gwesystems.com)
 * @package     
   Joomfish
 * @subpackage    Cache
 * 
@since        2.0
 */
class JCacheStorageJfdb 
extends JCacheStorage
{

    var 
$db;
    var 
$profile_db;

    
    
/* Constructor
  
  *
    * @access protected
    * @param array 
$options optional parameters
    */
    
function 
__construct$options = array() )
    {
      
  static 
$expiredCacheCleaned;

        
$this->profile_db = & JFactory::getDBO();
        
$this->db = clone ($this->profile_db);       
 

        
$this->_language    
(isset(
$options['language'])) ? $options['language'] : 'en-GB';
    
    
$this->_lifetime    = (isset($options['lifetime'])) ? 
$options['lifetime'] : 60;
        
$this->_now   
     
= (isset($options['now'])) ? $options['now'] : 
time();

        
$config         
   
=& JFactory::getConfig();
        
$this->_hash    
$config->getValue('config.secret');

        
// if 
its not the first instance of the joomfish db cache then check if it should be 
cleaned 
and otherwise garbage collect
        
if 
(!isset(
$expiredCacheCleaned)) {
            
// 
check a file in the 'file' cache to check if we should remove all our db cache 
entries since cache manage doesn
't handle anything other than file 
caches
            $conf =& 
JFactory::getConfig();
            $cachebase = 
$conf->getValue('
config.cache_path',JPATH_ROOT.DS.'cache');
    
        $cachepath = 
$cachebase.DS."joomfish-cache";
            if 
(!JFolder::exists($cachepath)){
            
    JFolder::create($cachepath);
          
  }
            $cachefile = 
$cachepath.DS."cachetest.txt";
            
jimport("joomla.filesystem.file");
            
if (!JFile::exists($cachefile) || JFile::read($cachefile)!="valid"){
  
              // clean out the whole 
cache
                
$this->cleanCache();
              
  JFile::write($cachefile,"valid");
          
  }
            $this->gc();
  
      }
        $expiredCacheCleaned = 
true;
    }

    /**
     * One 
time only DB setup function
     *
    
 */
    function setupDB() {
        
$db = & JFactory::getDBO();
        $charset = 
($db->hasUTF()) ? '
CHARACTER SET utf8 COLLATE utf8_general_ci' : 
'';
        $sql = "CREATE TABLE IF NOT EXISTS 
`#__dbcache` ("
        . "\n `id` varchar ( 32 ) 
 NOT NULL default '',"
        . "\n `groupname` 
varchar ( 32 ) NOT NULL default '',"
        . "\n 
`expire` datetime NOT NULL default '
0000-00-00 00:00:00',"
    
    //. "\n `value` MEDIUMTEXT NOT NULL default '',"
    
    . "\n `value` MEDIUMBLOB NOT NULL default '',"
    
    . "\n PRIMARY KEY ( `id`,`groupname` ),"
      
  . "\n KEY ( `expire`,`groupname` )"
        . "\n 
) $charset";
        $db->setQuery( $sql );
  
      if (!$db->query()){
        
    echo $db->getErrorMsg()."[br /]";
      
      echo $db->_sql;
        
}
    }

    /**
     * Get 
cached data from a db by id and group
     *
    
 * @access    public
     * @param   
 string    $id            The cache 
data id
     * @param    string    $group 
       The cache data group
     * @param 
   boolean    $checkTime    True to verify cache 
time expiration threshold
     * @return    mixed 
   Boolean false on failure or a cached data string
    
 * @since    1.5
     */
    
function get($id, $group, $checkTime)
    {
      
  
        if 
(method_exists($this->profile_db,"_profile")) $pfunc = 
$this->profile_db->_profile();

        
$hashedid = md5($id.'
-'.$this->_hash.'-'.$this->_language);

  
      $data = false;

        $sql = 
"SELECT  UNCOMPRESS(value) FROM `#__dbcache` WHERE 
id=".$this->db->quote($hashedid)." AND 
groupname=".$this->db->quote($group)." AND 
expire>FROM_UNIXTIME(".$this->db->quote($this->_now).")";
  
      
        $keepSQL = 
$this->db->_sql;
        
$this->db->setQuery($sql);

        // Must set 
false to ensure that Joomfish doesn'
t get involved
      
  $data 
$this->db->loadResult(false);
      
  
        
$this->db->_sql $keepSQL 
;
        if (
is_null($data)){
      
      
$data false;
        }
  
      else {
            
//$data 
base64_decode($data);
        }
      
  if (
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile($pfunc);

        
return 
$data;
    }

    
/**
    
 * Store the data to a file by id and group
    
 *
     * @access    public
    
 * @param    string    $id       
 The cache data id
     * @param    string 
   $group    The cache data group
     * 
@param    string    $data    The data to store in 
cache
     * @return    boolean    True on 
success, false otherwise
     * @since   
 1.5
     */
    
function store($id$group
$data)
    {
        
//$this->db =& 
JFactory::getDBO();
        if 
(
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile();

        
$hashedid md5($id.'-'.$this->_hash.'-'.$this->_language);

  
      
//$data = base64_encode($data);
      
  
$sql "REPLACE INTO `#__dbcache` (id, groupname,expire,value) VALUES 
("
.$this->db->quote($hashedid).",".$this->db->quote($group).",FROM_UNIXTIME(".$this->db->quote($this->_now 

$this->_lifetime)."),COMPRESS(".$this->db->quote($data)."))";
  
      
$this->db->setQuery($sql);

    
    
$res =  $this->db->query();
      
  if (
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile($pfunc);
        return 
$res;
    }

    
/**
     * 
Remove a cached data file by id and group
     *
  
   * @access    public
     * @param 
   string    $id        The cache data 
id
     * @param    string    $group 
   The cache data group
     * @return   
 boolean    True on success, false otherwise
    
 * @since    1.5
     */
    
function remove($id$group)
    {
        
//$this->db =& JFactory::getDBO();
        
if 
(
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile();
        
$sql 
"DELETE FROM `#__dbcache` WHERE id=".$this->db->quote($id)." AND 
groupname="
.$this->db->quote($group);
        
$this->db->_skipSetRefTables=true;
        
$this->db->setQuery($sql);
        
$this->db->_skipSetRefTables=false;
        if 
(
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile($pfunc);
        return 
$this->db->query();
    }

    
/**
  
   * Clean cache for a group given a mode.
    
 *
     * group mode        : cleans 
all cache in the group
     * notgroup mode    : 
cleans all cache not in the group
     *
    
 * @access    public
     * @param   
 string    $group    The cache data group
  
   * @param    string    $mode    The 
mode for cleaning cache [group|notgroup]
     * @return   
 boolean    True on success, false otherwise
    
 * @since    1.5
     */
    
function clean($group$mode)
    {
        
//$this->db =& JFactory::getDBO();
        
if 
(
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile();
        
$result 
false;
        switch (
trim($mode))
    
    {
            case 
'group':
                
$sql 
"DELETE FROM `#__dbcache` ";
              
  
$this->db->setQuery($sql);
          
      break;
            
default:
                
$sql 
"DELETE FROM `#__dbcache` WHERE 
groupname="
.$this->db->quote($group);
        
        
$this->db->setQuery($sql);
    
            break;
        
}
        
$this->db->_skipSetRefTables=true;
        
$result 
$this->db->query();
        
$this->db->_skipSetRefTables=false;
        

        if 
(
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile($pfunc);
        return 
$result;
    }

    
/**
     * 
Clean the whole cache
     *
     * @return 
   boolean    True on success, false otherwise
  
   */
    
function cleanCache()
    
{
        
//$this->db =& 
JFactory::getDBO();
        if 
(
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile();
        
$result 
false;
        
$sql "DELETE FROM `#__dbcache` 
"
;
        
$this->db->setQuery($sql);
  
      
$this->db->_skipSetRefTables=true;
    
    
$result $this->db->query();
        
$this->db->_skipSetRefTables=false;
        if 
(
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile($pfunc);
        return 
$result;
    }

    
/**
     * 
Garbage collect expired cache data
     *
    
 * @access public
     * @return boolean  True on 
success, false otherwise.
     */
    
function 
gc()
    {
        
//$this->db =& 
JFactory::getDBO();
        if 
(
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile();
        
$sql 
"DELETE FROM `#__dbcache` WHERE expire< 
FROM_UNIXTIME("
.$this->db->quote($this->_now).")";
    
    
$this->db->setQuery($sql);
        
$this->db->_skipSetRefTables=true;
        
$result 
$this->db->query();
        
$this->db->_skipSetRefTables=false;
        
// if 
we can't delete then the database table probably doesn't exist so create 
it
        
if (!$result && 
$this->db->getErrorNum()==1146){
          
  
$this->setupDB();
        }
    
    if (
method_exists($this->profile_db,"_profile")) $pfunc 
$this->profile_db->_profile($pfunc);
    }

  
  
/**
     * Test to see if the cache storage is 
available.
     *
     * @static
  
   * @access public
     * @return boolean 
 True on success, false otherwise.
     */
  
  
function test()
    {
        return 
true;
    }

}
« Ultima modifica: 13 Lug 2012, 16:41:55 da tomtomeight »

Offline tomtomeight

  • Global Moderator
  • Fuori controllo
  • ********
  • Post: 31614
  • Sesso: Maschio
  • Gli automatismi aiutano ma non insegnano nulla.
    • Mostra profilo
Re:Sito Hackerato:RISOLTO senza reinstallare tutto
« Risposta #5 il: 31 Gen 2012, 19:31:38 »
@Faurinz
Cortesemente non credo sia il caso di inserire codice così in abbondanza, almeno inseriscilo nel tag # o ancora meglio visto che è così lungo ti chiedo cortesemente di editare il post ed inserire quel codice in allegato in un file txt in modo da avere il post meglio leggibile, grazie.

Offline aletochigno

  • Esploratore
  • **
  • Post: 96
  • Sesso: Maschio
    • Mostra profilo
Re:Sito Hackerato:RISOLTO senza reinstallare tutto
« Risposta #6 il: 31 Gen 2012, 22:37:04 »
Che tipo di errore da?(ehm.. se è lungo in allegato va bene)

 

Host

Torna su