
Un escáner inteligente para Log4Shell/Log4j/CVE-2021-44228
Aunque se han publicado algunas herramientas excelentes para ayudar a las organizaciones a escanear sus entornos en busca de aplicaciones vulnerables a la crítica vulnerabilidad Log4J / CVE-2021-44228, consideré que:
Así nació Log4Shell Sentinel. Log4Shell Sentinel es un escáner basado en archivos con algunas características únicas. No pretende sustituir a todas las demás herramientas disponibles, sino complementarlas.
Log4Shell Sentinel es un escáner basado en archivos. Busca aplicaciones basadas en Java escaneando un sistema objetivo en busca de artefactos con los siguientes formatos de archivo:
| Tipo de archivo | Detalles |
|---|
| Jar simple | Este es el caso en el que el archivo log4j-core no está embebido. |
| Jar gordo / Uber jar | Un uber jar es un jar que contiene tanto tus clases / paquetes como todas las dependencias de tu aplicación (bibliotecas, recursos y archivos de metadatos) dentro de un único archivo jar. Esta es la opción de despliegue más utilizada. |
| WAR | Un archivo war (Web Application Archive) es un archivo que contiene tu código JSP, HTML y JavaScript, además de tus bibliotecas y otros recursos. Este formato se utiliza con menos frecuencia. |
| EAR | Un ear (Enterprise Application Archive) es otro formato que se utilizaba más habitualmente con Jakarta EE para despliegues. |
y busca instancias de archivos log4j-core vulnerables. A continuación:
calcula un hash MD5 del artefacto. Esto permite a un analista identificar la misma aplicación ejecutándose en diferentes máquinas / contenedores y tratarlos como un único hallazgo
para los archivos que se determina que pertenecen a un contenedor, como: /var/lib/docker/overlay2/192768f471818601094bf4edd96d14bfc0e2b178a04a2efd00b2231ad4e46b33/merged/app/spring-boot-application.jar, realiza el trabajo pesado de mapear el archivo a la imagen correspondiente. Por ejemplo, traduciría lo anterior a la siguiente imagen: ghcr.io/christophetd/log4shell-vulnerable-app:latest. Como los distintos runtimes de contenedores almacenan este mapeo de diferentes maneras, esto puede ahorrarle horas de frustración a un analista. Esto también permite a un analista tratar varios contenedores que ejecutan una única aplicación como un solo hallazgo.
elimina coincidencias inútiles, como las correspondientes a contenedores que no se están ejecutando actualmente, incluidas las imágenes en caché. Esto permite al analista centrarse en lo importante y, de nuevo, le ahorra horas de trabajo innecesario
permite a un analista ignorar coincidencias basándose en:
Esto permite al analista eliminar aplicaciones que sabe que no son vulnerables o que corresponden a aplicaciones basadas en CLI que no representan una amenaza. Por ejemplo, si se detecta una instancia de Logstash, un analista puede optar por ignorarla si no ejecuta la herramienta o simplemente la ejecuta desde la CLI de vez en cuando.
está optimizado para funcionar con tus herramientas de gestión de configuración, como Ansible, lo que te permite escanear rápidamente tu entorno en minutos
Para más detalles sobre el enriquecimiento de metadatos añadido por Log4Shell Sentinel, consulta mi artículo en el blog.
La forma más sencilla es simplemente descargar el binario precompilado.
También esto es sencillo. Sin embargo, probablemente querrás compilar una versión estáticamente enlazada para evitar cualquier variación relacionada con GLIBC en tu entorno. La herramienta utiliza los siguientes módulos, que usan CGO por defecto:
os/usernetPara compilar una versión estáticamente enlazada que utilice las versiones Go de estas bibliotecas, simplemente clona el repositorio y luego ejecuta:
$ CGO_ENABLED=0 go build -ldflags="-s -w"
$ ldd log4shell_sentinel
not a dynamic executable
$ ./log4shell_sentinel -h
NAME:
Log4Shell Sentinel - by Osama Elnaggar
USAGE:
log4shell_sentinel [global options] command [command options] [arguments...]
VERSION:
v1.0.0
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--path value, -p value Path to search (default: ".")
--no-banner, --nb Suppress banner (default: false)
--no-messages, --nm Suppress messages except for CSV output (default: false)
--no-header, --nh Suppress header in CSV output (default: false)
--imd5 value, --im value Ignore MD5 hashes. Refer to the GitHub page for expected format
--ipath value, --ip value Ignore file path matches. Refer to the GitHub page for expected format
--icimage value, --ic value Ignore container image matches. Refer to the GitHub page for expected format
--print-headers, --ph Print CSV Headers only (default: false)
--help, -h show help (default: false)
--version, -v print the version (default: false)
De serie, un escaneo simplemente escaneará el directorio actual. Por ejemplo:
$ ./log4shell_sentinel
░█░░░█▀█░█▀▀░█░█░█▀▀░█░█░█▀▀░█░░░█░░░░░█▀▀░█▀▀░█▀█░▀█▀░▀█▀░█▀█░█▀▀░█░░
░█░░░█░█░█░█░░▀█░▀▀█░█▀█░█▀▀░█░░░█░░░░░▀▀█░█▀▀░█░█░░█░░░█░░█░█░█▀▀░█░░
░▀▀▀░▀▀▀░▀▀▀░░░▀░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░▀▀▀░▀▀▀░▀░▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀
- A CVE-2021-44228/CVE-2021-45046/CVE-2021-45105 Scanner
- v1.0.0
- by Osama Elnaggar
[*] WARNING: Running as non-root user.
Non-readable files / dirs will be skipped
Container mapping will fail
[*] Starting shallow scan ............ [DONE]
[*] Starting deep scan ............... [DONE]
[*] Calculating MD5 hashes ........... [DONE]
[*] Performing container image lookups [DONE]
[*] Processing ignore list(s) ........ [DONE]
[*] Generating output ................ [DONE]
IP,Hostname,AppName,Team,Ignore (Y/N),Comments,MD5Hash,Timestamp,Container,ContainerImage,FullPath,Version
192.168.121.121,server3,,,,,4e615cd580758b70c49ade1f79103328,2021-12-21T07:38:09Z,true,ghcr.io/christophetd/log4shell-vulnerable-app:latest,/run/containerd/io.containerd.runtime.v2.task/k8s.io/dc2c9c214809f506283c917244cd126a9b056ac7274322d12b59c9196d95dd9b/rootfs/app/spring-boot-application.jar,log4j-core-2.14.1.jar
Inmediatamente verás una ADVERTENCIA si lo ejecutas como un usuario no root, ya que requiere permisos de root:
Seguirá funcionando sin privilegios de root, pero puede que no te dé los mejores resultados.
Un hallazgo de ejemplo tiene este aspecto:
IP,Hostname,AppName,Team,Ignore (Y/N),Comments,MD5Hash,Timestamp,Container,ContainerImage,FullPath,Version
192.168.121.121,server3,,,,,4e615cd580758b70c49ade1f79103328,2021-12-21T07:38:09Z,true,ghcr.io/christophetd/log4shell-vulnerable-app:latest,/run/containerd/io.containerd.runtime.v2.task/k8s.io/dc2c9c214809f506283c917244cd126a9b056ac7274322d12b59c9196d95dd9b/rootfs/app/spring-boot-application.jar,log4j-core-2.14.1.jar
Algunos campos se dejan vacíos intencionadamente para que el analista los rellene en Excel, etc. A continuación se muestra una breve descripción de cada campo:
| Campo | Ejemplo | Descripción |
|---|---|---|
| IP | 192.168.121.121 | Si la instancia tiene varias IP, se añade la IP principal |
| Hostname | server3 | Nombre de host |
| AppName | Esto queda para que el usuario lo complete después de finalizar el escaneo | |
| Team | Esto queda para que el usuario lo complete después de finalizar el escaneo | |
| Ignore (Y/N) | Esto queda para que el usuario lo complete después de finalizar el escaneo | |
| Comment | Esto queda para que el usuario lo complete después de finalizar el escaneo | |
| MD5Hash | 4e615cd580758b70c49ade1f79103328 | Una huella digital única de nuestra aplicación |
| Timestamp | 2021-12-21T07:38:09Z | Una marca de tiempo de cuándo se realizó el escaneo. Es útil si quieres agregar múltiples escaneos del mismo host |
| Container | true | True = esto es un contenedor |
| ContainerImage | ghcr.io/christophetd/log4shell-vulnerable-app:latest | Si se detectó un contenedor, esta es la imagen correspondiente |
| FullPath | /run/containerd/io.containerd. runtime.v2.task/k8s.io/.../spring-boot-application.jar | La ruta completa del hallazgo. En este ejemplo, el archivo JAR vulnerable forma parte de un fat / uber jar |
| Version | log4j-core-2.14.1.jar | La versión de lo4j-core detectada |
La herramienta incluye las siguientes opciones:
| Opción | Detalles |
|---|---|
--path value, -p value | Especifica qué rutas buscar. Por defecto, busca en el directorio actual. IMPORTANTE Se recomienda establecerla en / para cubrir todo tu sistema de archivos |
--no-banner, --nb | Suprime el banner |
--no-messages, --nm | Suprime mensajes, como los relacionados con el progreso |
--no-header, --nh | Suprime el encabezado de la salida CSV. Se recomienda cuando se ejecuta en múltiples servidores |
--imd5 value, --im value | Ignora los hashes MD5. Más información en la sección Listas de ignorados |
--ipath value, --ip value | Ignora las coincidencias de rutas de archivo. Más información en la sección Listas de ignorados |
--icimage value, --ic value | Ignora las coincidencias de imágenes de contenedor. Más información en la sección Listas de ignorados |
--print-headers, --ph | Imprime solo los encabezados CSV. Cuando ejecutas Log4Shell Sentinel en múltiples servidores y agregas los resultados, normalmente deshabilitas la salida de encabezados. Este comando genera solo el encabezado para que puedas añadirlo a tu hoja de Excel |
Una de las características únicas de Log4Shell Sentinel, que no se encuentra en ninguna otra herramienta, es la capacidad de traducir los jars encontrados en escaneos del sistema de archivos, como:
/var/lib/docker/overlay2/192768f471818601094bf4edd96d14bfc0e2b178a04a2efd00b2231ad4e46b33/merged/app/spring-boot-application.jar
a la imagen de contenedor correspondiente (lo anterior se traduce a ghcr.io/christophetd/log4shell-vulnerable-app:latest, por ejemplo). Como los distintos runtimes de contenedores almacenan este mapeo de diferentes maneras, esto puede ahorrarle horas de frustración a un analista. Esto también permite a un analista tratar varios contenedores que ejecutan una única aplicación como un solo hallazgo. La solución actualmente admite las siguientes búsquedas:
El número de aplicaciones identificadas puede resultar abrumador al principio, o puede que quieras centrarte primero en un subconjunto concreto de aplicaciones identificadas, como las expuestas a usuarios externos. O puede que quieras centrarte en un determinado alcance de cumplimiento. Para respaldar esto, la aplicación permite especificar una lista. Log4Shell actualmente admite 3 listas de ignorados:
En lugar de listas simples, espera un archivo CSV como entrada. Esto anima al analista a documentar por qué ignora un hallazgo determinado. A medida que el analista procesa los hallazgos e identifica aplicaciones no vulnerables mediante análisis de código fuente manual o automatizado, herramientas DAST, etc.
La lista es un archivo CSV simple con el siguiente formato:
MD5Sum,AppName,Reason
Las columnas AppName y Reason pueden estar vacías, pero están ahí para que lleves un registro de por qué incluyes o excluyes aplicaciones específicas.
NOTA Como esta función utiliza el hash MD5 calculado para la aplicación, solo funcionará con aplicaciones que sean fat / uber jars, EARs o WARs.
Por ejemplo, si tuviéramos el siguiente hallazgo:
IP,Hostname,AppName,Team,Ignore (Y/N),Comments,MD5Hash,Timestamp,Container,ContainerImage,FullPath,Version
192.168.121.121,server3,,,,,4e615cd580758b70c49ade1f79103328,2021-12-21T07:38:09Z,true,ghcr.io/christophetd/log4shell-vulnerable-app:latest,/run/containerd/io.containerd.runtime.v2.task/k8s.io/dc2c9c214809f506283c917244cd126a9b056ac7274322d12b59c9196d95dd9b/rootfs/app/spring-boot-application.jar,log4j-core-2.14.1.jar
y determináramos que la aplicación no es vulnerable, podemos simplemente guardar lo siguiente en hashes.csv:
4e615cd580758b70c49ade1f79103328,Demo App,Not vulnerable
y luego volver a ejecutarla:
# ./log4shell_sentinel --im hashes.csv --path /
el hallazgo anterior se suprimiría.
La lista es un archivo CSV simple con el siguiente formato:
Container Image,AppName,Reason
Continuando con el ejemplo anterior, podemos indicarle que ignore cualquier hallazgo donde la imagen del contenedor sea: ghcr.io/christophetd/log4shell-vulnerable-app:latest creando un archivo images.csv como este:
ghcr.io/christophetd/log4shell-vulnerable-app:latest,,
y luego ejecutándola con:
# ./log4shell_sentinel --ic images.csv -p /
Una vez más, nuestro hallazgo anterior se suprimiría.
De nuevo, este es un archivo CSV simple con el siguiente formato:
Path,AppName,Reason
Usando el ejemplo anterior, si creamos el siguiente archivo paths.csv:
/run/containerd/io.containerd.runtime.v2.task/k8s.io/dc2c9c214809f506283c917244cd126a9b056ac7274322d12b59c9196d95dd9b/rootfs/app/spring-boot-application.jar,Demo App,Not vulnerable
el hallazgo anterior se suprimiría.
ADVERTENCIA Cuando sea posible, es mejor usar un hash MD5 o el nombre de la imagen del contenedor para la supresión, ya que la ruta puede no ser única.
Si bien es perfectamente aceptable ejecutar Log4Shell Sentinel en un solo servidor, realmente brilla cuando se combina con tu herramienta de gestión de configuración favorita (Ansible, Chef, Puppet, Salt, AWS SSM, etc.) o incluso con herramientas SSH paralelas simples como parellel-ssh.
Esto te ofrece numerosos beneficios, entre ellos:
Para ver un ejemplo completo de esto en acción, consulta mi artículo en el blog.
Consulta la sección Escaneo masivo de tu entorno.
root (requiere acceso a donde tus aplicaciones puedan estar instaladas) o con no haber especificado la ruta correcta. Se recomienda ejecutarlo como usuario root y establecer --path /A partir de v1.0.0, la herramienta actualmente admite la asignación para lo siguiente:
Si estás usando cualquier otra cosa, la asignación no funcionará. Si estás usando uno de los anteriores, puede que no estés ejecutando la herramienta como usuario root o que el socket / los archivos utilizados se encuentren en una ubicación no predeterminada.
Desarrollado por: Osama Elnaggar