PI Debug/ WordPress, plug-in a rischio

Il successo di questo CMS è in parte dovuto alla marea di plug-in che ne estendono le funzionalità. Tuttavia, bisogna stare attenti a cosa si installa nel proprio sito Web: un bug può permette ai pirata l'esecuzione di una SQL Injection

Negli ultimi anni, l'e-commerce ha aumentato la propria diffusione in modo esponenziale. Soprattutto perché ormai non si vende più soltanto su Amazon, eBay o altre grosse piattaforme: chiunque può aprire un proprio sito Web e vendere ciò che desidera. Una buona parte del merito va ai CMS destinati alla costruzione di siti di e-commerce. I Content Management System sono applicazioni Web, solitamente scritte in PHP o ASP, che permettono anche a chi non è esperto di programmazione la costruzione di un sito utilizzando una serie di schemi pronti all'uso. I CMS per l'e-commerce esistono da molto tempo, ma solo recentemente sono diventati più semplici da usare e gestire. Non soltanto: anche i normali CMS, quelli utilizzati per realizzare blog, hanno prodotto dei plug-in che permettono la vendita di prodotti o servizi. È il caso di WordPress, il CMS più diffuso al mondo: si calcola che WordPress sia utilizzato nel 20 per cento di tutti i siti Web esistenti. Tuttavia, dobbiamo ricordare che quasi il 70 per cento dei siti non è costruito con un CMS (molti siti governativi, ad esempio, hanno piattaforme statiche). Ciò significa che WordPress è il motore di due terzi dei siti Web basati su CMS.

Esistono diversi plug-in di WordPress che permettono di realizzare in pochi clic un sito di e-commerce. Uno dei più diffusi fino a qualche tempo fa era Product Catalog 8. Al momento, questo plug-in è stato sospeso perché lo sviluppatore non ha più il tempo di aggiornarlo e questo lo rende un facile bersaglio per i pirati. Secondo le statistiche di WordPress, infatti, la maggior parte degli utenti non è particolarmente solerte nell'aggiornare il proprio CMS e i relativi plug-in. Il risultato è che diversi siti rischiano di essere vulnerabili ai vari bug che affliggono questo ormai datato plug-in.


La pagina del plugin Product Catalog 8 è stata rimossa dal sito di Wordpress, ma la si trova ancora su Web Archive

Un'iniezione SQL
C'è un bug che risalta fra tutti per la sua pericolosità, perché offre la possibilità di una SQL Injection. Ma forse dobbiamo fare qualche passo indietro. WordPress è un'applicazione PHP basata su database SQL. Di solito si utilizza un server MySQL oppure PostgreSQL, ma si può anche ricorrere ad un file SQLite. Ad ogni modo, è poco rilevante, perché in ciascun caso il risultato è che tutte le informazioni del sito Web vengono memorizzate nel database. Questo include i testi, la struttura delle pagine, l'interfaccia, e persino le immagini e i file allegati (il loro URL). Ma, soprattutto, i dati sugli utenti, i commenti e le password di accesso, inclusa quelle di amministrazione. Ciò significa che è estremamente importante proteggere questo database e impedire che un malintenzionato possa accedervi in lettura e, soprattutto, in scrittura. Perché potendo scrivere nel database un pirata potrebbe, ad esempio, cancellare delle tabelle o modificare la password di amministratore per accedere al sito e modificarlo a proprio piacimento.
I database SQL sono molto comodi per i programmatori perché si basano su delle query, ovvero dei comandi. Per fare qualche esempio: esiste un comando per leggere le tabelle, uno per crearle e uno per distruggerle. Basta inviare tali comandi tramite PHP e si può manipolare il database. Siccome i comandi sono di fatto delle stringhe di testo, sono molto comode da realizzare e da adattare alle varie esigenze. Il problema nasce quando un comando deve essere realizzato utilizzando delle informazioni fornite dall'utente. Ad esempio, il comando DROP TABLE gianni provvede a cancellare la tabella chiamata gianni. Si può decidere di inserire in una pagina HTML una casella di testo tramite la quale l'utente possa indicare il nome della tabella da eliminare. Poi PHP non deve far altro che concatenare DROP TABLE con il valore della casella di testo e il gioco è fatto. Il problema è che in questo modo se l'utente commette un errore, il comando può essere snaturato. Addirittura, se l'utente è un malintenzionato, può scrivere nella casella di testo un codice che sostituisce il comando con un altro, in modo da "iniettare" nel server SQL un comando malevolo al posto di quello previsto originariamente. Per evitare che ciò accada, si deve controllare ogni contributo dell'utente, per assicurarsi che non contenga caratteri speciali che possano modificare la query.

Questione di codice
Questo controllo, però, non avviene nel codice del plug-in Product Catalog: quest'estensione è realizzata con una serie di file PHP. Tra questi, c'è il file includes/ajax-functions.php, che contiene una serie di funzioni. In particolare, si nota la funzione UpdateCategoryList, che può essere chiamata fornendo alla pagina wp-admin/admin-ajax.php il suo nome nel campo action fornito tramite HTTP POST (è quindi sufficiente creare un semplice form HTML contente questo codice:

<input type="text" name="action" value="UpdateCategoryList">
.

Il codice di questa funzione è il seguente:

function UpdateCategoryList() {
global $wpdb, $subcategories_table;

global $wpdb;
$table = $subcategories_table;
$catid = $_POST['selectedCategory'];

if($catid !== '0') {

$get_items = $wpdb->get_results( "SELECT * FROM $table WHERE subcategory_category = $catid ORDER BY subcategory_name ASC" );
echo json_encode($get_items);
}
else {
$get_items = "";
echo json_encode($get_items);
}

die();

}

Si può immediatamente notare che la funzione riceve tramite HTTP POST un testo chiamato selectedCategory, che viene subito inserito nella variabile $catid. Il problema è che poi tale variabile viene inserita direttamente nella query SQL, ovvero quel testo che inizia con il comando SELECT. Siccome non c'è alcun controllo sul contenuto della variabile $catid e non viene applicata alcuna funzione di escape per eliminare potenziali caratteri pericolosi. Ciò significa che un utente malintenzionato può facilmente sfruttare l'occasione per far eseguire a PHP una query a propria discrezione. In poche parole, ad un pirata è sufficiente scrivere questo codice:

<form method="post" action="http://www.sitoweb.com/wp-admin/admin-ajax.php">
<input type="text" name="selectedCategory" value="0 UNION SELECT 1,2,3,4,5,6 FROM wp_terms WHERE term_id=1">
<input type="text" name="action" value="UpdateCategoryList">
<input type="submit" value="Send">
</form>

per produrre un form tramite il quale inviare una query arbitraria. Il pirata può quindi modificare parti sensibili del database, inclusi gli hash delle password degli utenti amministratori.


Basta una semplice richiesta HTTP POST per eseguire l'exploit

Come correre ai ripari
Se questo plug-in è presente sulla nostra installazione di WordPress, la soluzione migliore consiste nel disabilitarlo e passare ad un altro plug-in simile ma costantemente aggiornato. Questo caso ci insegna quanto sia importante mantenere aggiornato il CMS, perché essere presi di mira dai pirati è davvero molto facile se si utilizzano applicazioni contenenti bug. Se siamo dei programmatori, invece, possiamo evitare le SQL Injection in due modi. Il primo, e più semplice, consiste nel ricorrere ad una funzione di escape, che rimuova tutti i simboli speciali che potrebbero modificare la natura della query che abbiamo scritto:

$unsafe_variable = $_POST["user-input"];
$safe_variable = mysql_real_escape_string($unsafe_variable);
mysql_query("INSERT INTO table (column) VALUES ('". $safe_variable. "')");

La funzione di escape fornita da PHP si chiama mysql_real_escape_string, ed è valida nella maggioranza dei casi. L'alternativa, è rappresentata dall'uso delle funzioni MYSQLi invece della comuni MYSQL. In particolare, le query possono essere "preparate" con una funzione chiamata, per l'appunto mysqli.prepare.
Questo è un esempio di utilizzo:

<?php
$mysqli = new mysqli("server", "username", "password", "database_name");
$unsafe_variable = $_POST["user-input"];
$stmt = $mysqli->prepare("INSERT INTO table (column) VALUES (?)");
$stmt->bind_param("s", $unsafe_variable);
$stmt->execute();
$stmt->close();
$mysqli->close();
?>

Questa opzione è solitamente la migliore, ma ha un difetto: supporta soltanto MySQL. Se si vuole utilizzare un differente database SQL, si deve provvedere a sviluppare un livello di astrazione utilizzando PDO, il che complica abbastanza le cose.

AVVERTENZE
Le informazioni contenute in questo articolo sono state pubblicate a scopo puramente didattico, per consentire ai lettori di conoscere e imparare a difendersi dai pericoli a cui sono esposti navigando in Internet o in generale utilizzando applicazioni affette da vulnerabilità.
L'editore e la redazione non si assumono responsabilità alcuna circa l'utilizzo improprio di tali informazioni, che possa avere lo scopo di violare la legge o di arrecare danni a terzi. Per cui, eventuali sanzioni economiche e penali saranno esclusivamente a carico dei trasgressori.
13 Commenti alla Notizia PI Debug/ WordPress, plug-in a rischio
Ordina
  • Inzio ad essere stufo di certi articoli usati per fare dei maledetti test su noi lettori...

    L'articolo e' di un approssimazione disarmante...
    non+autenticato
  • - Scritto da: Stone e Cojone
    > Inzio ad essere stufo di certi articoli usati per
    > fare dei maledetti test su noi
    > lettori...
    >
    > L'articolo e' di un approssimazione disarmante...
    che lagna pero'Con la lingua fuori tutta la parte sul bug di Product Catalog 8 l'hanno copiata e tradotta bene (anche se e' di novembre)...
    non+autenticato
  • Un sacco di gente programma così.
    Bisogna prendere in seria considerazione un testo che tratti anche la sicurezza.
    iRoby
    9639
  • - Scritto da: iRoby
    > Un sacco di gente programma così.

    Scuola M$ visual basic!

    > Bisogna prendere in seria considerazione un testo
    > che tratti anche la
    > sicurezza.

    Bisogna prendere in seria considerazione la zappa e un campo da predisporre alla semina.
  • - Scritto da: panda rossa

    > Scuola M$ visual basic!

    Peccato sia PHP. Hai presente la P in LAMP?
  • - Scritto da: Zucca Vuota
    > - Scritto da: panda rossa
    >
    > > Scuola M$ visual basic!
    >
    > Peccato sia PHP. Hai presente la P in LAMP?

    Non ho mica negato che sia PHP.
    Ho solo detto che l'autore di quella fetenzia ha imparato a programmare gestionali in VB.

    Perche' solo chi arriva dalla scuola VB esegue il contenuto di una stringa senza alcuna verifica o controllo preventivo.
  • Sono tanti che iniziano a programmare coi libri sul PHP un po' vecchiotti che non prendono in considerazione questioni di sicurezza.

    Chi si è aggiornato per curiosità personale o perché gli hanno trapanato il sito oggi sa come evitare questo genere di cose.

    Io mi guardo il codice dei plugin, soprattutto i form e verifico come passano i parametri per la query.

    Oltre ciò in PHP io uso framework come Zend o altri che mi danno alcune classi di sanitizing dell'input utili proprio a questi scopi...

    In JavaEE è ancora meglio perché il meccanismo è protetto già by design.
    iRoby
    9639
  • - Scritto da: iRoby
    > Sono tanti che iniziano a programmare coi libri
    > sul PHP un po' vecchiotti che non prendono in
    > considerazione questioni di
    > sicurezza.

    Libri nel 2017?
    Con tutti i manuali aggiornati che ci sono in rete?

    > Chi si è aggiornato per curiosità personale o
    > perché gli hanno trapanato il sito oggi sa come
    > evitare questo genere di
    > cose.

    Ma lo sapeva anche ieri, chi programmava seriamente.
    Certo non puoi mica pretendere che uno nato a pane e vanti, vanti, vanti, stalla, si ponga il problema delle injections.
  • - Scritto da: iRoby
    > Sono tanti che iniziano a programmare coi libri
    > sul PHP un po' vecchiotti che non prendono in
    > considerazione questioni di
    > sicurezza.

    Ma che cazzo dici? La questione della SQL injection la insegnavano anche nel 1995.

    > Chi si è aggiornato per curiosità personale o
    > perché gli hanno trapanato il sito oggi sa come
    > evitare questo genere di
    > cose.
    >
    > Io mi guardo il codice dei plugin, soprattutto i
    > form e verifico come passano i parametri per la
    > query.
    >
    > Oltre ciò in PHP io uso framework come Zend o
    > altri che mi danno alcune classi di sanitizing
    > dell'input utili proprio a questi
    > scopi...

    E introducono altri bug.

    NON SI IMPARA A PROGRAMMARE SERIAMENTE CON DEI FRAMEWORK, lo volete capire o no?
    non+autenticato
  • - Scritto da: panda rossa
    > - Scritto da: iRoby
    > > Un sacco di gente programma così.
    >
    > Scuola M$ visual basic!
    >
    > > Bisogna prendere in seria considerazione un
    > testo
    > > che tratti anche la
    > > sicurezza.
    >
    > Bisogna prendere in seria considerazione la zappa
    > e un campo da predisporre alla
    > semina.

    No! L' agricoltura è una cosa seria, bisogna per lo meno saper distinguere il cibo dal concime. Io sinceramente non voglio magnà la mer*a.
    non+autenticato
  • - Scritto da: panda rossa

    > Scuola M$ visual basic!

    che era un linguaggio client side, mananged e con controllo automatico dei bordi degli array.
    In pratica virtualmente impenetrabile da remoto.

    direi che hai capito tutto.
    non+autenticato
  • - Scritto da: tu si che capisci
    > - Scritto da: panda rossa
    >
    > > Scuola M$ visual basic!
    >
    > che era un linguaggio client side, mananged e con
    > controllo automatico dei bordi degli
    > array.
    > In pratica virtualmente impenetrabile da remoto.

    Esatto.
    Ed e' in quel frangente che lo sparagestionali VB ha imparato a comporre le query in runtime senza alcuna verifica, che tanto l'applicazione la usa solo il proprietario.

    Poi un bel giorno gli e' stato chiesto di portarla in ambiente client-server in php, e quello ha diligentemente convertito le funzioni, mantenendo la composizione in runtime delle query senza alcun controllo.

    > direi che hai capito tutto.
    E ho anche capito quanto ne sai tu, pensa che bravo che sono.
  • Forse intendeva ASP parente del VB. E la loro reincarnazione .NET.
    iRoby
    9639