Per rassicurarne alcuni, non ho trovato il bug osservando gli exploit, non ho motivo di credere che sia stato sfruttato prima di essere divulgato (anche se ovviamente non posso escluderlo). Non l'ho trovato nemmeno guardando bash
il codice.
Non posso dire di ricordare esattamente il mio treno di pensieri in quel momento.
Che più o meno è venuto da una riflessione su alcuni comportamenti di alcuni software che trovo pericolosi (i comportamenti, non il software). Il tipo di comportamento che ti fa pensare: non sembra una buona idea .
In questo caso, stavo riflettendo sulla configurazione comune di ssh che consente il passaggio di variabili di ambiente non autenticate dal client a condizione che il loro nome inizi LC_
. L'idea è che le persone possano continuare a usare la propria lingua quando si ssh
immettono in altre macchine. Una buona idea fino a quando non si inizia a considerare quanto sia complessa la gestione della localizzazione, specialmente quando UTF-8 viene portato nell'equazione (e vedendo come è gestita male da molte applicazioni).
Nel luglio 2014, avevo già segnalato una vulnerabilità nella gestione della localizzazione di glibc che si combinava con quella sshd
configurazione, e altri due comportamenti pericolosi della bash
shell
consentivano agli attaccanti (autenticati) di hackerare i server git a condizione che fossero in grado di caricare file lì e che bash
fosse usato come shell di login dell'utente git unix (CVE-2014-0475).
Stavo pensando che probabilmente era una cattiva idea usare bash
come shell di login degli utenti che offrono servizi su ssh, dato che è una shell piuttosto complessa (quando tutto ciò che serve è solo analizzare una riga di comando molto semplice) e ha ereditato la maggior parte dei disegni errati di ksh. Dato che avevo già identificato alcuni problemi con bash
l'uso in quel contesto (per interpretare gli ssh ForceCommand
), mi chiedevo se ci fosse potenzialmente altro.
AcceptEnv LC_*
permette a qualsiasi variabile il cui nome inizia con LC_
e ho avuto il vago ricordo che le bash
funzioni esportate (una funzione pericolosa seppur utile al momento) stavano usando variabili d'ambiente il cui nome era qualcosa di simile
myfunction()
e mi chiedevo se non ci fosse qualcosa di interessante da guardare lì.
Stavo per respingere sul fatto che la cosa peggiore che si potesse fare sarebbe stata ridefinire un comando chiamato LC_something
che non poteva davvero essere un problema in quanto quelli non erano nomi di comandi esistenti, ma poi ho iniziato a chiedermi come bash
importasse quelle variabili d'ambiente.
E se le variabili fossero chiamate LC_foo;echo test; f()
ad esempio? Quindi ho deciso di dare un'occhiata più da vicino.
UN:
$ env -i bash -c 'zzz() { :;}; export -f zzz; env'
[...]
zzz=() { :
}
ha rivelato che il mio ricordo era sbagliato in quanto le variabili non erano chiamate myfunction()
ma myfunction
(ed è il
valore che inizia con ()
).
E un breve test:
$ env 'true;echo test; f=() { :;}' bash -c :
test
bash: error importing function definition for `true;echo test; f'
ha confermato il mio sospetto che il nome della variabile non sia stato disinfettato e che il codice sia stato valutato all'avvio .
Peggio ancora, molto peggio, il valore non è stato neppure sanificato:
$ env 'foo=() { :;}; echo test' bash -c :
test
Ciò significava che qualsiasi variabile d'ambiente poteva essere un vettore.
Fu allora che mi resi conto dell'entità del problema, confermai che era sfruttabile anche su HTTP ( HTTP_xxx
/ QUERYSTRING
... env vars), altri come i servizi di elaborazione della posta, in seguito DHCP (e probabilmente un lungo elenco) e lo riportai (attentamente) .