
CVE-2026-52813 (Gogs Path Traversal → Git Hooks RCE) 방어적 분석서: 근본 원인 및 패치 분석, Sigma/SIEM 탐지 규칙, IOCs, 비침습적 버전 스캐너. 무기화된 PoC 없음.
보안 연구 / 블루팀용 writeup. 이 저장소는 무기화된 PoC를 포함하지 않습니다. 재현이 필요한 연구자는 공식 advisory에서 참조하는 공개 PoC를 사용하십시오.
| 항목 | 내용 |
|---|---|
| CVE | CVE-2026-52813 |
| 별칭 | GHSA-c39w-43gm-34h5 / GO-2026-5305 |
| 영향받는 버전 | Gogs < 0.14.3 |
| 수정 버전 | 0.14.3 — PR #8334 |
| CVSS 3.1 | 10.0 Critical AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| CWE | CWE-23 Relative Path Traversal → RCE |
| 전제 조건 | 일반 등록 계정 하나 (기본적으로 회원가입이 열려 있을 경우 = 인증되지 않은 RCE) |
Gogs가 조직을 생성할 때 웹 폼은 AlphaDashDot 문자 검증을 통해 /를 차단하지만, REST API POST /api/v1/user/orgs는 그렇지 않습니다. 공격자는 API를 통해 ../가 포함된 조직 이름을 제출하여 검증을 우회하고 os.MkdirAll(repoutil.UserPath(org.Name), 0777) (internal/database/org.go:165)에 도달하여 저장소 디렉터리를 임의의 파일 시스템 경로에 씁니다. Gogs의 웹 편집기 임시 작업 트리(local-r/<repo_id>/)와 결합하면 다른 저장소의 로컬 checkout 내에 악성 hooks/update를 배치하여 git에 의해 자동으로 실행되며, git 사용자 권한으로 RCE를 달성합니다.
| Gogs 버전 | 상태 |
|---|---|
< 0.14.3 | 영향 받음, 즉시 업그레이드 |
>= 0.14.3 | 수정됨 |
업그레이드는 유일한 완전한 수정 방법입니다:
# Docker
docker pull gogs/gogs:0.14.3
# 또는 소스
git checkout v0.14.3 && go build
임시 완화 조치 (업그레이드할 수 없는 경우):
app.ini → [service] DISABLE_REGISTRATION = true), 전제 조건을 '인증되지 않음'에서 '이미 존재하는 계정 필요'로 낮춥니다;POST /api/v1/user/orgs, POST /api/v1/org/*/repos 요청 본문에서 username/name 필드에 .. 또는 /가 포함된 것을 차단합니다 (detection/ 참조);/data/gogs/data/tmp/ 외부에 쓰기 권한을 가지지 않도록 제한합니다 (selinux/apparmor).웹 폼 (internal/form/org.go, v0.14.2):
type CreateOrg struct {
OrgName string `binding:"Required;AlphaDashDot;MaxSize(35)"` // 정규식 ^[a-zA-Z0-9._-]+$
}
API (internal/route/api/v1/org/org.go, v0.14.2):
// api.CreateOrgOption (go-gogs-client)의 바인딩 태그:
type CreateOrgOption struct {
UserName string `json:"username" binding:"Required"` // ← AlphaDashDot 없음!
}
→ POST /api/v1/user/orgs의 username 필드는 임의의 문자를 DB 계층까지 직접 전달할 수 있습니다.
internal/database/users.go:1532의 isNameAllowed는 예약된 이름/접두사/접미사(예: admin, -bot)만 차단하고, 문자 집합을 검증하지 않으므로 ../가 통과할 수 있습니다.
internal/repoutil/repoutil.go (v0.14.2):
func UserPath(user string) string {
return filepath.Join(conf.Repository.Root, strings.ToLower(user)) // ← 바로 연결
}
internal/database/org.go:165:
os.MkdirAll(repoutil.UserPath(org.Name), os.ModePerm) // org.Name에 ../ 포함 → 임의 경로에 쓰기
Gogs가 웹/API 파일 편집을 처리할 때 저장소를 /data/gogs/data/tmp/local-r/<repo_id>/로 체크아웃합니다. <repo_id>는 저장소의 데이터베이스 id와 정확히 일치합니다. 공격자는:
writer를 만들고 id == n을 얻습니다;username = "../../../../data/gogs/data/tmp/local-r/n/nested" → 실제 디렉터리는 writer의 작업 트리 안에 위치합니다;rce-x 생성 → local-r/n/nested/rce-x.git에 위치;writer를 클론하고, nested/rce-x.git/hooks/update를 일반 파일로 커밋한 후 push합니다 (writer 작업 트리 안에 위치합니다);writer의 파일 조작을 트리거 → Gogs가 local-r/n/에서 git 실행 → git이 hooks/update 실행 → RCE.핵심 포인트: 악성 hook은 일반 저장소 콘텐츠로 정상 push를 통해 유입되며,
ENABLE_GIT_HOOKS설정이 필요하지 않습니다 — 이것이 "전통적인 git hooks 남용" 경로와의 차이점입니다.
자세한 패치 diff 분석은 patch/ANALYSIS.md를 참조하십시오.
전체 규칙은 detection/에서 확인하십시오:
../ 포함) 및 성공적인 악용(파일 시스템 배치)을 포함가장 중요한 두 가지:
POST /api/v1/user/orgs와 POST /api/v1/org/*/repos의 JSON 본문에서 username/name 필드에 .. 또는 /가 포함된 경우./data/gogs/data/tmp/local-r/*/ 아래에 예상치 못한 하위 디렉터리(nested/, rce-*.git, hooks/update)가 나타납니다.GET /api/v1/version을 통해 Gogs 인스턴스가 < 0.14.3인지 확인하며, 일괄 스캔 및 CSV 출력을 지원하여 자산 인벤토리에 적합합니다.이 저장소는 무기화된 익스플로잇 도구를 제공하지 않습니다. 재현은 공식 advisory에서 참조하는 공개 PoC를 사용하고, 자체 구축한 격리 환경에서만 수행하십시오.
detection/ 규칙은 영향을 받는 Gogs에서 검증해야 하며, lab/docker-compose.yml은 블루팀이 탐지 규칙이 적중하는지 테스트할 수 있도록 격리된 Gogs 0.14.2 환경을 제공합니다. 공개 네트워크에 노출하지 말고 로컬에서만 사용하십시오.
| 날짜 | 이벤트 |
|---|---|
| 2026-06-08 | CVE 보류 |
| 2026-06-24 | 공개 공개, Gogs 0.14.3 출시 |
| 2026-06-24 | 공식 advisory GHSA-c39w-43gm-34h5 발표 |
인터넷에서 이 CVE를 *'Gogs gitrebase 매개변수 주입 원격 코드 실행'*으로 설명하는 경우가 있습니다 — 그것은 잘못된 것입니다. 이 취약점은 git rebase / gitrebase와 관련이 없으며, 근본 원인은 API 경로 탐색입니다. 본 문서는 실제 취약점에 따라 분석합니다.
MIT — LICENSE 참조.