Retrospettiva su Log4j - Parte 1: retroscena delle vulnerabilità
Cronologia
Il 24 novembre 2021, la Apache Foundation ha ricevuto, in privato da parte del team per la sicurezza nel cloud di Alibaba, la notizia che Log4j, una libreria di registrazione basata su Java ampiamente utilizzata, conteneva un'importante vulnerabilità che avrebbe potuto causare la diffusione di informazioni private, nonché una vulnerabilità RCE (Remote Code Execution). Questa vulnerabilità esisteva sin dal 2013.
Il giorno seguente, la Apache Foundation ha riservato il codice CVE-2021-44228 e ha iniziato a cercare una correzione. Nei 12 giorni successivi, sono state introdotte diverse modifiche al codice sorgente per risolvere il problema e, il 9 dicembre 2021, la vulnerabilità è stata divulgata pubblicamente.
Questo problema ha comportato un afflusso di tentativi di sfruttamento, incrementatisi a una velocità allarmante, mai vista prima.
Che cos'è l'autenticazione Log4j?
Per capire davvero la vulnerabilità, dobbiamo comprendere cosa sia Log4j. Log4j è una libreria che viene utilizzata ampiamente tra gli sviluppatori della community Java. Fornisce un sistema abbastanza robusto per registrare messaggi di errore, informazioni di diagnostica e altro.
Tra alcune delle funzioni più importanti, figura la capacità di registrare più destinazioni, inclusi, a titolo di esempio, la console, un file, un server remoto che utilizza TCP, Syslog, registri eventi NT e messaggi e-mail. Inoltre, consente il filtraggio gerarchico dei messaggi e dei livelli del registro, dei layout personalizzati e molto altro.
In breve, la libreria presenta una serie completa di funzionalità che ne rendono molto attraente l'utilizzo per gli sviluppatori, il che ne ha comportato l'ubiquità in tutto, dalle applicazioni web ai dispositivi incorporati.
Ricerche e annidamento
Una delle funzionalità davvero potenti supportate da Log4j è quella delle ricerche. Le ricerche consentono a uno sviluppatore di inserire variabili o espressioni nel testo automaticamente valutate da Log4j prima dell'output. Ad esempio, uno sviluppatore può scrivere un codice che registra il seguente testo:
"${date:MM-dd-yyyy} All Systems Good"
Log4j riconosce lo schema ${date:MM-dd-yyyy} come ricerca di date e sostituisce appositamente l'espressione con la data corrente. Ad esempio, se la data è il 20 dicembre 2021, il testo viene modificato come segue prima del suo output su una destinazione:
"12-20-2021 All Systems Good"
Questa funzione è estremamente utile per gli sviluppatori, che, pertanto, non sono costretti a scrivere manualmente il codice per cercare la data, formattarlo in una stringa, farlo precedere nella riga di registro e poi occuparsi del suo output. Sebbene il codice di cui sopra non sia particolarmente difficile o complesso da scrivere, non riguarda la logica aziendale di base del software e viene ripetuto da un progetto all'altro.
Sfruttando la funzionalità già codificata all'interno della libreria Log4j, gli sviluppatori possono, invece, concentrarsi sulla differenza che conta per il loro progetto e lasciare che sia Log4j a gestire tutte le attività correlate alla registrazione.
Esistono molti tipi di espressioni di ricerca supportati da Log4j. Esaminiamone altre due, di cui parleremo diffusamente in questo articolo, env e lower. env, che consentono di includere le variabili di ambiente nel sistema host nelle righe di registro. Ad esempio, uno sviluppatore che registra il testo:
"The current user is ${env:USER}"
produce il seguente output, supponendo che il software venga eseguito come utente Administrator.
"The current user is Administrator"
A differenza di env e date, che iniettano nuovi dati nel testo, lower può essere utilizzato per manipolare ciò che è già presente. Log4j semplicemente scrive in minuscolo ciò che appare nell'espressione. Ad esempio:
"The lower case text is ${lower:ABCDEFG}"
produce:
"The lower case text is abcdefg"
Questo esempio, preso singolarmente, non è molto interessante. Perché non scrivere semplicemente in minuscolo la stringa da soli? La potenza di tutto questo diventa più ovvia quando si considera il fatto che Log4j consente l'annidamento delle espressioni di ricerca.
Possiamo combinare le prime due espressioni nel modo seguente:
"The lower case current user is ${lower:${env:USER}}"
Ciò porta Log4j a valutare per primo l'espressione ${env:USER} come Administrator, quindi la invia a lower che poi dà luogo ad administrator, producendo, infine, la seguente riga:
"The lower case current user is administrator"
JNDI
Mentre date, enve lower sono tutti interessanti e molto utili, questa vulnerabilità non sarebbe possibile senza la ricerca JNDI. JNDI(Java Naming and Directory Interface) è un meccanismo realizzato in modo nativo negli ambienti di sviluppo Java e di runtime, che consente un'interrogazione semplificata, a vari servizi di directory, per informazioni che utilizzano un'interfaccia comune.
Come risulta evidente, esistono molti tipi diversi di servizi di directory supportati. Ad esempio, JNDI supporta l'interrogazione ai server DNS per scoprire l'indirizzo IP di un host, nonché interrogare AD e LDAP per le voci di directory. Supporta persino l'interrogazione dell'ambiente Java corrente per Environmental Entries, che può essere vista come una serie di opzioni di configurazione specializzate per il software attualmente in esecuzione.
L'espressione di ricerca JNDI in Log4j consente agli sviluppatori di accedere a questo sottosistema molto potente direttamente tramite espressioni incorporate nel testo registrato. Ad esempio, se uno sviluppatore tentasse di registrare la seguente stringa:
"The current mail host is ${jndi:java:comp/env/mailhost}"
Log4j riconoscerebbe l'espressione ${jndi:java:comp/env/mailhost} come ricerca JNDI passando lo pseudo-URL java:comp/env/mailhost al sottosistema di JNDI. JNDI riconosce questo particolare tipo di URL come una query per la ricerca di un'opzione di configurazione denominata mailhost per il componente attualmente in esecuzione.
Immaginiamo che sia configurato come mymailserver.example.com. JNDI restituirebbe questa informazione a Log4j, il che poi sostituirebbe l'espressione di ricerca con mymailserver.example.com, producendo il seguente output:
"The current mail host is mymailserver.example.com"
Come esiste la vulnerabilità
In breve, la vulnerabilità di Log4j in Apache ha rappresentato una grande opportunità per gli autori degli attacchi, per via della vasta popolarità della libreria e, in particolare, delle sue funzionalità di ricerca, annidamento e JNDI. Questa funzionalità, sebbene sia potente per gli sviluppatori, crea anche le opportunità di passare le richieste che possono esfiltrare i dati o causare RCE. Sulla base di ciò, ora possiamo iniziare a comprendere meglio la vulnerabilità e il modo in cui gli autori degli attacchi possono sfruttare il sistema.
Il futuro
Nella parte 2 di questa serie, tratteremo le modalità con le quali gli autori degli attacchi iniziano a sfruttare questa vulnerabilità per esfiltrazione di dati e RCE.