La distribuzione del sistema operativo open source OpenBSD è ben nota tra gli amministratori di sistema, in particolare quelli che gestiscono i server, per la sua attenzione alla sicurezza piuttosto che alla velocità, alle funzionalità e ai fantasiosi front-end.
Opportunamente, forse, il suo logo è un pesce palla - gonfiato, con le sue punte pronte a respingere eventuali hacker astuti che potrebbero presentarsi.
Ma il team di OpenBSD è probabilmente meglio conosciuto non per la sua intera distribuzione, ma per il toolkit di accesso remoto OpenSSH che è stato scritto alla fine degli anni '1990 per essere incluso nel sistema operativo stesso.
SSH, abbreviazione di shell sicura, è stato originariamente creato da un informatico finlandese Tatu Ylonen a metà degli anni '1990 nella speranza di svezzare gli amministratori di sistema dalla rischiosa abitudine di utilizzare il protocollo Telnet.
Il problema con Telnet
Telnet era straordinariamente semplice ed efficace: invece di collegare cavi fisici (o utilizzare un modem su una linea telefonica) per effettuare una connessione telescrivente a server remoti, si utilizzava invece una connessione TELetype NETwork.
Fondamentalmente, i dati che di solito fluivano avanti e indietro su una connessione seriale dedicata o su una linea telefonica dial-up venivano inviati e ricevuti su Internet, utilizzando una connessione di rete TCP a commutazione di pacchetto invece di un collegamento point-to-point a commutazione di circuito. .
Stesso sistema di accesso familiare, connessioni più economiche, nessuna necessità di linee dati dedicate!
Il gigantesco difetto di Telnet, ovviamente, era la sua totale mancanza di crittografia, così che fiutare la tua esatta sessione di terminale era banale, permettendo ai cracker di vedere ogni comando che digitavi (anche gli errori che facevi, e tutte le volte che premevi [Backspace]
), e ogni byte di output prodotto...
…e, naturalmente, il nome utente e la password all'inizio della sessione.
Chiunque sul tuo percorso di rete potrebbe non solo ricostruire facilmente le tue sessioni di amministratore di sistema in tempo reale sul proprio schermo, ma probabilmente anche manomettere la tua sessione modificando i comandi che hai inviato al server remoto e simulando il ritorno delle risposte in modo che tu non te ne accorga il sotterfugio.
Potrebbero persino creare un server impostore, attirarti e renderti sorprendentemente difficile individuare l'inganno.
Crittografia forte FTW
L'SSH di Ylönen mirava ad aggiungere uno strato di forte crittografia e autenticazione a ciascuna estremità di una sessione simile a Telnet, creando un shell sicura (questo è ciò che rappresenta il nome, se te lo sei mai chiesto, anche se quasi tutti lo chiamano semplicemente ess-ess-aitch questi giorni).
È stato un successo immediato e il protocollo è stato rapidamente adottato dagli amministratori di sistema di tutto il mondo.
Presto seguì OpenSSH, come accennato in precedenza, apparso per la prima volta alla fine del 1999 come parte del OpenBSD2.6 rilasciare.
Il team di OpenBSD voleva creare un'implementazione gratuita, affidabile e open source del protocollo che loro e chiunque altro potrebbe usare, senza alcuna delle complicazioni di licenza o commerciali che avevano ostacolato l'implementazione originale di Ylönen negli anni immediatamente successivi al suo rilascio.
In effetti, se esegui il server Windows SSH e ti connetti ad esso da un computer Linux in questo momento, quasi sicuramente farai affidamento sull'implementazione OpenSSH su entrambe le estremità.
Il protocollo SSH è utilizzato anche in altri popolari servizi client-server tra cui SCP e SFTP, abbreviazione di copia protetta ed FTP sicuro rispettivamente. SSH significa vagamente "connettiti in modo sicuro ed esegui una SHell di comandi dall'altra parte", tipicamente per accessi interattivi, perché il programma Unix per una shell di comandi è solitamente /bin/sh
. SCP è simile, ma per CoPying files, perché generalmente viene chiamato il comando Unix file-copy /bin/cp
e SFTP è denominato più o meno allo stesso modo.
OpenSSH non è l'unico toolkit SSH in città.
Altre implementazioni ben note includono: libsh2, per gli sviluppatori che desiderano integrare il supporto SSH direttamente nelle proprie applicazioni; Dropbear Drop, un server SSH ridotto dal programmatore australiano Matt Johnston che si trova ampiamente sui cosiddetti dispositivi IoT (Internet of Things) come router domestici e stampanti; E PuTTY, una popolare raccolta gratuita di strumenti relativi a SSH per Windows da uno sviluppatore open source indipendente Simon Tatham in Inghilterra.
Ma se sei un normale utente SSH, oggi ti sei quasi sicuramente connesso ad almeno un server OpenSSH, anche perché la maggior parte delle distribuzioni Linux contemporanee lo include come strumento di accesso remoto standard e Microsoft offre sia un client OpenSSH che un OpenSSH server come componenti ufficiali di Windows in questi giorni.
Correzione di bug doppiamente gratuita
OpenSSH versione 9.2 appena uscito, e il note di rilascio segnalare come segue:
Questa versione contiene correzioni per […] un problema di sicurezza della memoria. [Questo bug] non è ritenuto sfruttabile, ma riportiamo la maggior parte degli errori di memoria raggiungibili dalla rete come bug di sicurezza.
Il bug colpisce sshd
, il server OpenSSH (il -d
suffisso sta per demone, il nome Unix per il tipo di processo in background che Windows chiama a servizio):
shd(8): correggere un errore di memoria doppia libera di pre-autenticazione introdotto in OpenSSH 9.1. Non si ritiene che ciò sia sfruttabile e si verifica nel processo di pre-autenticazione senza privilegi che è soggetto a chroot(2) ed è ulteriormente in modalità sandbox sulla maggior parte delle piattaforme principali.
Un bug double-free significa che un blocco di memoria è già stato restituito al sistema operativo per essere riutilizzato in altre parti del programma...
…verrà poi riconsegnato da una parte del programma che in realtà non “possiede” più quel ricordo, ma non sa di non averlo.
(O restituiti deliberatamente su suggerimento di codice che sta tentando di provocare il bug apposta per trasformare un vulnerabilità in un sfruttare.)
Questo può portare a bug sottili e difficili da svelare, soprattutto se il sistema contrassegna il blocco liberato come disponibile quando il primo free()
accade, successivamente lo alloca a un'altra parte del tuo codice quando richiede memoria tramite malloc(
), quindi contrassegna nuovamente il blocco come libero quando la chiamata superflua a free()
appare.
Questo ti lascia nel tipo di situazione che provi quando fai il check-in in un hotel che dice: “Oh, buone notizie! Pensavamo di essere pieni, ma un altro ospite ha appena deciso di fare il check-out in anticipo, così puoi avere la sua stanza.
Anche se la stanza è ben pulita e preparata per i nuovi occupanti quando entri, e quindi sembra che sia stata assegnata correttamente per il tuo uso esclusivo, devi comunque fidarti che la chiave magnetica dell'ospite precedente sia stata effettivamente cancellata correttamente e che il loro " checkout anticipato” non era uno stratagemma astuto per tornare di soppiatto più tardi lo stesso giorno e rubare il tuo laptop.
Correzione di bug per correzione di bug
Ironia della sorte, se guardi alla recente cronologia del codice OpenSSH, vedrai che OpenSSH aveva un bug modesto in una funzione chiamata compat_kex_proposal()
, utilizzato per verificare il tipo di algoritmo di scambio di chiavi da utilizzare durante l'impostazione di una connessione.
Ma la correzione di quel modesto bug ha introdotto invece una vulnerabilità più grave.
A proposito, la presenza del bug in una parte del software utilizzato durante l'impostazione di una connessione è ciò che rende questo un cosiddetto pre-autenticazione raggiungibile dalla rete vulnerabilità (o bug di pre-autorizzazione in breve).
Il bug double-free si verifica nel codice che deve essere eseguito dopo un client ha avviato una sessione remota, ma prima qualsiasi accordo chiave o autenticazione ha avuto luogo, quindi la vulnerabilità può, in teoria, essere attivata prima che qualsiasi password o chiave crittografica sia stata presentata per la convalida.
In OpenSSH 9.0, compat_kex_proposal
sembrava qualcosa del genere (molto semplificato qui):
char* compat_kex_proposal(char* suggestion) { if (condition1) { return suggestion; } if (condition2) { suggestion = allocatenewstring1(); } if (condition3) { suggestion = allocatenewstring2(); } if (isblank(suggestion)) { error(); } return suggestion; }
L'idea è che il chiamante passi nel proprio blocco di memoria contenente una stringa di testo che suggerisce un'impostazione di scambio di chiavi e riceva un'approvazione per utilizzare lo stesso suggerimento che ha inviato o una stringa di testo appena allocata con un suggerimento aggiornato .
Il bug è che se la condizione 1 è falsa ma le condizioni 2 e 3 sono entrambe vere, il codice esegue l'allocazione seconda nuove stringhe di testo, ma restituisce solo prima.
Il blocco di memoria allocato da allocatenewstring1()
non viene mai liberato e quando la funzione ritorna, il suo indirizzo di memoria viene perso per sempre, quindi non c'è modo per alcun codice di free()
in futuro.
Quel blocco è essenzialmente abbandonato, causando ciò che è noto come a perdita di memoria.
Nel tempo, ciò potrebbe causare problemi, forse anche costringere il server a spegnersi per riprendersi dal sovraccarico della memoria.
In OpenSSH 9.1, il codice è stato aggiornato nel tentativo di evitare di allocare due stringhe ma di abbandonarne una:
/* Always returns pointer to allocated memory, caller must free. */ char* compat_kex_proposal(char* suggestion){ char* previousone = NULL; if (condition1) { return newcopyof(suggestion); } if (condition2) { suggestion = allocatenewstring1(); } if (condition3) { previousone = suggestion; suggestion = allocatenewstring2(); } free(previousone); } if (isblank(suggestion()) { error(); } return suggestion; }
Questo ha il bug double-free, perché se la condizione 1 e la condizione 2 sono entrambe false, ma la condizione 3 è vera, allora il codice alloca una nuova stringa da restituire come risposta...
... ma libera in modo errato la stringa che il chiamante ha originariamente passato, perché la funzione allocatenewstring1()
non viene mai chiamato per aggiornare la variabile suggestion
.
La stringa di suggerimento passata è la memoria che appartiene al chiamante, e che il chiamante si libererà quindi in seguito, portando al pericolo del doppio libero.
In OpenSSH 9.2, il codice è diventato più cauto, tenendo traccia di tutti e tre i possibili blocchi di memoria utilizzati: l'originale suggestion
(memoria di proprietà di qualcun altro) e due possibili nuove stringhe che potrebbero essere allocate lungo il percorso:
/* Always returns pointer to allocated memory, caller must free. */ char* compat_kex_proposal(char* suggestion) { char* newone = NULL; char* newtwo = NULL; if (condition1) { return newcopyof(suggestion); } if (condition2) { newone = allocatenewstring1(); } if (condition3) { newtwo = allocatenewstring2(); } free(newone); newone = newtwo; } if (isblank(newone)) { error(); } return newone; }
Se la condizione 1 è vera, viene utilizzata una nuova copia della stringa passata, quindi il chiamante può farlo in seguito free()
la memoria della loro stringa passata ogni volta che lo desiderano.
Se superiamo la condizione 1 e la condizione 2 è vera ma la condizione 3 è falsa, allora il suggerimento alternativo creato da allocatenewstring1()
viene restituito e il passato suggestion
la stringa viene lasciata sola.
Se la condizione 2 è falsa e la condizione 3 è vera, allora una nuova stringa viene generata e restituita, e il passato suggestion
la stringa viene lasciata sola.
Se entrambe le condizioni 2 e 3 sono vere, vengono allocate due nuove stringhe lungo il percorso; il primo viene liberato perché non serve; il secondo viene restituito; e il passato suggestion
la stringa viene lasciata sola.
Puoi RTxM per confermare che se si chiama free(newone)
quando newone
is NULL
, quindi "nessuna operazione viene eseguita", perché è sempre sicuro farlo free(NULL)
. Tuttavia, molti programmatori si difendono ancora in modo robusto con codici come if (ptr != NULL) { free(ptr); }
.
Cosa fare?
Come suggerisce il team di OpenSSH, sfruttare questo bug sarà difficile, anche a causa dei privilegi limitati che il file sshd
programma ha mentre sta configurando la connessione per l'uso.
Tuttavia, l'hanno segnalato come una falla di sicurezza perché è quello che è, quindi assicurati di aver aggiornato a OpenSSH 9.2.
E se stai scrivendo codice in C, ricorda che non importa quanto sei esperto, la gestione della memoria è facile da sbagliare...
... quindi fai attenzione là fuori.
(Sì, Rust e i suoi amici moderni lo faranno aiutarti a scrivere il codice corretto, ma a volte avrai ancora bisogno di usare C, e nemmeno Rust può garantirlo impedirti di scrivere codice errato se programmi in modo sconsiderato!)
- Distribuzione di contenuti basati su SEO e PR. Ricevi amplificazione oggi.
- Platoblockchain. Web3 Metaverse Intelligence. Conoscenza amplificata. Accedi qui.
- Fonte: https://nakedsecurity.sophos.com/2023/02/03/openssh-fixes-double-free-memory-bug-thats-pokable-over-the-network/