Scopri cos’è un Format String Attack, come funziona e quali sono le best practices per evitarlo nello sviluppo sicuro del software.

In un periodo storico in cui le minacce informatiche sono in costante aumento, sta diventando sempre più importante sviluppare programmi sicuri. Infatti, le vulnerabilità legate alla scrittura del codice sono tra le più insidiose. Basta un errore nella gestione dell’input per trasformare un programma perfettamente funzionante in una porta d’ingresso per attacchi informatici. È il caso del Format String Attack, una tecnica di exploit presente fin dalla fine degli anni novanta, ma ancora oggi utilizzata con successo da attori malevoli.

  1. Introduzione alle funzioni di formattazione
  2. Cos’è il Format String Attack?
  3. Conseguenze di un Format String Attack
  4. Come prevenire la vulnerabilità delle funzioni di formattazione
format-string-attack-image

Questo tipo di attacco sfrutta le funzioni di formattazione delle stringhe integrate in numerosi linguaggi di programmazione, tra cui C, C++, Perl, Java, PHP e Ruby. Se queste funzioni sono utilizzate senza una corretta validazione dell’input, l’attaccante può manipolare l’esecuzione del programma, accedere alla memoria, alterare variabili interne, o eseguire codice arbitrario.

In questo articolo analizzeremo nel dettaglio il funzionamento di un Format String Attack, le conseguenze pratiche che può generare e, soprattutto, le migliori contromisure da adottare per prevenirlo.

Introduzione alle funzioni di formattazione

Prima di discutere del funzionamento alla base del Format String Attack, è fondamentale spiegare cosa sono le funzioni di formattazione. Si tratta di istruzioni utilizzate in numerosi linguaggi di programmazione per rappresentare i dati in una forma leggibile o specifica, ad esempio durante l’output su schermo o su file. Il meccanismo alla base è quello delle stringhe di formattazione, che contengono identificatori di formato: caratteri speciali che indicano il tipo di dato da stampare o elaborare. Questi identificatori vengono interpretati dal programma al momento dell’esecuzione, e associati ai valori passati come argomenti.

Un esempio classico è la funzione printf del linguaggio C:

printf("%s", "Onorato");

In questo caso, %s è è l’identificatore che segnala la presenza di una stringa, mentre “Onorato” è il valore che verrà effettivamente stampato. Semplice, utile, ma anche molto pericoloso se gestito in maniera inadeguata.

Cos’è il Format String Attack?

Il Format String Attack si verifica quando un programma utilizza una funzione di formattazione, come printf, senza validare correttamente l’input fornito dall’utente. Rientra nella famiglia delle vulnerabilità da input non validato, la stessa categoria di iniezione che la OWASP Top 10 annovera tra i principali rischi per le applicazioni. In questi casi, l’attaccante può inserire stringhe contenenti identificatori di formato (%x, %p, %n) per manipolare direttamente il comportamento della funzione, accedendo alla memoria o eseguendo codice arbitrario.
In questi casi, l’attaccante può inserire stringhe contenenti identificatori di formato (%x, %p, %n) per manipolare direttamente il comportamento della funzione, accedendo alla memoria o eseguendo codice arbitrario.

Un esempio classico è il seguente:

printf(username);

Se il valore di username è controllato dall’utente, la funzione può interpretare la stringa come istruzioni da eseguire, anziché semplici dati da stampare. Da qui si aprono diverse possibilità d’attacco. Una delle tecniche più comuni consiste nell’accedere alla memoria interna del programma. Usando identificatori come %x e %p, l’attaccante può visualizzare contenuti sensibili in formato esadecimale o leggere indirizzi di memoria, ottenendo informazioni cruciali per pianificare attacchi più complessi.

Un altro scenario consiste nel manipolare il flusso di esecuzione. Con l’identificatore %n, progettato per scrivere in memoria, un cybercriminale può sovrascrivere variabili puntatore con indirizzi arbitrari, facendo puntare il programma a script malevoli. Basta un accesso successivo a quella variabile per avviare l’esecuzione del codice malevolo.

Ma il Format String Attack può essere usato anche per provocare un crash del programma. L’invio di una lunga sequenza di identificatori %x, ad esempio, può forzare la funzione a leggere indirizzi non validi, generando un segmentation fault. E questo, in un ambiente produttivo, ha conseguenze gravi.

Conseguenze di un Format String Attack

Un Format String Attack eseguito con successo può compromettere profondamente un’applicazione, aprendo la strada a una serie di conseguenze spesso difficili da rilevare. La varietà degli impatti dipende dal contesto e dai privilegi con cui viene eseguito il programma vulnerabile.

Una delle implicazioni più comuni è la violazione di dati sensibili. Accedendo alla memoria, l’attaccante può ottenere informazioni critiche come credenziali di accesso, chiavi di cifratura o indirizzi email, sfruttando identificatori di formato per leggere aree non protette del sistema.

Un rischio ancora più serio è la possibilità di eseguire Arbitrary Code Execution. Manipolando puntatori e indirizzi, l’attaccante può forzare il programma a eseguire codice arbitrario, ottenendo così il pieno controllo dell’esecuzione. Questo rappresenta uno degli scenari più critici in assoluto, soprattutto in ambienti di produzione.

Il Format String Attack può anche essere impiegato in attacchi DDoS (Distributed Denial of Service). Basta una sequenza malformata di identificatori per forzare la lettura di indirizzi invalidi, causando un segmentation fault e bloccando l’applicazione.

In altri casi, le stringhe malformate possono corrompere strutture dati e variabili di stato, generando comportamenti imprevedibili, errori logici o perdite di integrità nei dati gestiti dal software. Una corruzione silenziosa può essere ancora più dannosa di un crash immediato.

Se l’attacco avviene in un contesto con privilegi elevati, come quello di root o amministratore, può verificarsi un’escalation di privilegi. Questo consente all’attaccante di accedere a risorse normalmente protette, compromettendo l’intero sistema operativo o la rete.

Il Format String Attack viene spesso impiegato come fase iniziale di attacchi multi-stage. Dopo aver ottenuto l’accesso iniziale, l’attaccante può sfruttare altre vulnerabilità per esercitare persistenza nel sistema, o semplicemente passare inosservato. In molti casi, questi attacchi sono difficili da rilevare, perché non generano eventi evidenti nei log e permettono all’aggressore di muoversi nell’ombra.

Come prevenire la vulnerabilità delle funzioni di formattazione

I Format String Attack possono essere evitati con accorgimenti relativamente semplici, a patto che vengano applicati con costanza. Di seguito, sono riportate alcune best practices fondamentali per mitigare efficacemente questo tipo di vulnerabilità.

  • Usare correttamente le funzioni di formattazione.
    Le funzioni devono sempre includere un formato esplicito, evitando di passare input utente direttamente. Ad esempio printf(“%s”, username) è sicuro, mentre printf(username) è vulnerabile. Quando possibile, utilizzare versioni più sicure come snprintf, che consentono di definire un limite al buffer.
  • Validare rigorosamente gli input utente.
    Qualsiasi input proveniente da fonti esterne deve essere filtrato e validato. Bisogna escludere caratteri imprevisti, come identificatori di formato, e accettare solo valori conformi a pattern predefiniti.
  • Eseguire analisi statica e code review.
    L’utilizzo di tool per l’analisi statica del codice, affiancati da revisioni manuali durante lo sviluppo, consente di individuare potenziali vulnerabilità prima che raggiungano la produzione.
  • Prestare attenzione ai warning del compilatore.
    I warning non vanno mai ignorati. Molti compilatori segnalano potenziali problemi di sicurezza legati alla formattazione. Se affrontati tempestivamente, è possibile ridurre il rischio di exploit.
  • Evitare input utente diretto nel log.
    Quando si registrano dati nei log, è buona norma non inserire direttamente input utente. Meglio loggare ID o riferimenti contestuali. Se l’input è necessario, sanificarlo prima dell’inserimento.
  • Utilizzare librerie orientate alla sicurezza.
    Per applicazioni web, è utile integrare librerie come OWASP ESAPI o framework specifici per la validazione sicura degli input. Questi strumenti forniscono API progettate per ridurre gli errori di implementazione.
  • Implementare sistemi di protezione runtime.
    Tecniche come Address Space Layout Randomization (ASLR) e stack canaries aiutano a rilevare e bloccare exploit in fase di esecuzione. Sono spesso integrati nei sistemi operativi moderni e vanno sempre abilitati.



    Dichiaro di aver letto e compreso l'Informativa sul trattamento dei dati