
Gitea 1.27.1 이전 버전은 Git 훅 설치를 통해 diffpatch API를 경유한 원격 코드 실행을 허용합니다.
[!WARNING] 이 저장소는 오직 승인된 보안 연구 및 통제된 실험실 테스트만을 위해 제공됩니다. 소유하지 않았거나 명시적인 평가 허가를 받지 않은 시스템에 대해 개념 증명을 실행하지 마십시오.
CVE-2026-60004는 Gitea의 diffpatch API에 존재하는 치명적인 원격 코드 실행 취약점입니다. 저장소를 생성하거나 쓰기 권한이 있는 인증된 사용자는 임시 bare 저장소 내부에 실행 가능한 Git 훅이 생성되도록 조작된 패치를 제출할 수 있습니다. 훅이 트리거되면 공격자가 제어하는 명령이 Gitea 서비스 계정의 권한으로 실행됩니다.
공개 등록이 활성화된 경우, 인증되지 않은 공격자가 계정을 생성하여 취약한 인증 엔드포인트에 접근할 수 있습니다.
| 속성 | 세부 정보 |
|---|
| 식별자 | CVE-2026-60004 |
| 권고 | GHSA-rcr6-4jqh-j84m |
| 심각도 | 치명적 — CVSS 3.1: 9.8 |
| 취약점 유형 | CWE-94: 코드 생성의 부적절한 제어 |
| 영향받는 버전 | Gitea 1.17.0 ~ 1.27.0 |
| 수정된 버전 | Gitea 1.27.1 |
| 필요한 접근 권한 | 저장소 쓰기 권한 |
| 실행 컨텍스트 | Gitea 운영체제 계정 |
| CISA KEV 날짜 | 2026-08-25 |
| 파일 | 설명 |
|---|---|
gitea_diffpatch_rce.py | 인증하고, 비공개 저장소를 생성하고, 조작된 패치를 제출하고, 명령 출력을 가져오는 표준 라이브러리만 사용하는 개념 증명. |
payload.patch | 실행 가능한 hooks/post-index-change 훅을 생성하는 예제 패치. |
poc.png | 실험실 검증 중 캡처한 스크린샷. |
README.md | 원본 연구 노트. |
개념 증명은 다음 격리된 환경에서 검증되었습니다:
| 구성 요소 | 구성 |
|---|---|
| Gitea | 1.27.0 |
| Git | 2.47.2 |
| 배포 | gitea-lab이라는 이름의 Docker 컨테이너 |
| 서비스 주소 | 192.168.184.128:3000 |
| 관찰된 신원 | uid=1000(git) gid=1000(git) |
성공적인 익스플로잇은 다음과 유사한 명령 출력을 생성했습니다:
uid=1000(git) gid=1000(git) groups=1000(git)
Linux 6.12.20-amd64 x86_64
/data/gitea/tmp/local-repo/upload.git630501597
[exit-status=0]

이 스크립트는 Python 표준 라이브러리만 사용하며 추가 패키지가 필요하지 않습니다.
python3 gitea_diffpatch_rce.py <base_url> <username> <password> "<command>"
로컬 실험실 인스턴스의 예:
python3 gitea_diffpatch_rce.py \
http://127.0.0.1:3000 \
pocuser \
'P@ssw0rd!' \
'id; uname -a'
이 스크립트는 먼저 웹 등록을 시도한 다음, 제공된 자격 증명으로 인증합니다. 이를 통해 동일한 명령이 공개 등록이 활성화된 인스턴스의 새 계정이나 기존 계정 모두에서 작동할 수 있습니다.
익스플로잇 체인은 네 단계로 구성됩니다:
공격자 제어 패치 제출
POST /api/v1/repos/{owner}/{repo}/diffpatch는 임시 클론 내에서
git apply --index --recount --cached --binary --ignore-whitespace --whitespace=fix -3를 사용하여 제공된 패치 내용을 적용합니다.
훅 경로 배치
임시 저장소는 bare, 공유 클론으로 생성됩니다. bare 저장소에서는 저장소
루트가 $GIT_DIR이기도 합니다. 결과적으로 패치 경로
hooks/post-index-change는 Git의 활성 훅 디렉터리 내부에서
해석됩니다.
실행 가능한 훅 생성
동일한 패치가 두 번 제출됩니다. 두 번째 적용은 add/add 충돌을
발생시키며, 이로 인해 3-way 폴백이 --cached 사용에도 불구하고 경로를
모드 100755로 디스크에 생성합니다. 이후 인덱스 업데이트가
post-index-change를 호출하여 주입된 셸 코드를 Gitea 서비스 계정으로
실행합니다.
Git 네이티브 출력 검색
훅은 objects/info/alternates를 통해 원본 저장소를 식별하고, 명령
출력을 Git blob으로 저장하고, 트리와 커밋을 생성하고,
refs/heads/output-leak을 업데이트합니다. 그런 다음 개념 증명은 Gitea의
raw-file API를 통해 결과를 검색합니다. 이 기법은 대상에서 직접적인
아웃바운드 연결을 필요로 하지 않습니다.
성공적인 익스플로잇은 Gitea 서비스 계정의 권한으로 명령 실행을 허용합니다. 배포 구성에 따라 공격자는 다음에 접근할 수 있습니다:
app.ini 및 데이터베이스 자격 증명SECRET_KEY, INTERNAL_TOKEN 및 LFS 관련 비밀실험실 계정은 app.ini에 대한 읽기 접근 권한이 확인되었습니다.
방어자는 다음 아티팩트와 요청 패턴을 조사해야 합니다:
/api/v1/repos/*/*/diffpatch에 대한 두 개의 동일하거나 거의 동일한
요청이 빠르게 연속으로 발생output-leak이라는 이름의 브랜치poc <[email protected]>가 작성한 커밋hooks/post-index-change라는
이름의 예상치 못한 실행 가능 파일/data/gitea/tmp/local-repo/upload.git*와 같은 경로 아래의 의심스러운
활동이러한 지표는 포함된 개념 증명을 설명하며 완전하지 않습니다. 수정된 익스플로잇은 다른 경로, ref, 신원 또는 출력 채널을 사용할 수 있습니다.
/api/v1/.../diffpatch 라우트에 대한
접근을 거부하는 방식입니다. 배포 전에 정당한 통합에 대해 규칙을
검증하십시오.DISABLE_REGISTRATION=true를 설정하여
공개 등록을 비활성화하십시오. 이는 인증되지 않은 접근 가능성을
줄이지만 저장소 쓰기 권한이 있는 기존 사용자로부터는 보호하지
않습니다.이 연구에 사용된 실험실 컨테이너의 경우, 다음과 같이 정리할 수 있습니다:
docker rm -f gitea-lab
이 자료는 방어자가 취약점을 재현하고, 이해하고, 탐지하고, 수정할 수 있도록 돕기 위해 제공됩니다. 운영자는 격리된 환경에서만 테스트하고 조직의 승인 및 공개 요구 사항을 따라야 합니다.