Autore Topic: Sito Hackerato:RISOLTO senza reinstallare tutto  (Letto 8567 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: 30134
  • 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.
NEWS DataGrill Xataface Installer (Ver. 1.0.1) per Joomla 3.8.x - DEMO Gestione Magazzino

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