
CVE-2026-22874 분석: Gitea 웹훅/마이그레이션에서 불완전한 SSRF 허용 목록 (IPv6 전환 및 클라우드 메타데이터). Gitea 1.26.3에서 수정됨.
CVE-2026-22874 (GHSA-2r5c-gw76-rh3w)에 대한 기술적 분석 및 참고 자료: Gitea의 웹훅 전달 및 저장소 마이그레이션에서 불완전한 SSRF 허용 목록, Gitea 1.26.3에서 수정됨.
저는 이 SSRF 클래스를 Gitea 유지관리자에게 독립적으로 보고했으며, 공개된 권고에서 기여자(other)로 인정받았습니다. 권고의 주요 보고자는 J. Leitschuh입니다. 이 저장소는 공개 권고에 대한 방어적이고 교육적인 분석입니다 — 문제는 수정되었습니다.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N)<= 1.26.2 — 수정: 1.26.3Gitea의 기본 SSRF 허용 목록(MatchBuiltinExternal, 웹훅 전달 및 저장소 마이그레이션 모두에서 사용됨)은 Go 표준 라이브러리 net.IP.IsPrivate()에 의존했습니다. 이 함수는 RFC 1918(, , ) 및 RFC 4193()만 인식합니다. 클라우드 메타데이터 서비스, 내부 네트워크 및 IPv6 전환 메커니즘에서 일반적으로 사용되는 여러 주소 범위가 해당 정의에서 "private"이 아니므로 "external" 필터를 통과하여 인증된 사용자가 서버가 해당 대상에 HTTP 요청을 보내도록 할 수 있습니다.
10/8172.16/12192.168/16fc00::/7웹훅 전달은 응답 상태, 헤더 및 최대 약 1 MiB의 본문을 기록하고 웹훅 기록 UI에 렌더링하므로, 이 SSRF는 블라인드가 아닙니다: 공격자는 대상 내부 서비스가 반환하는 내용을 읽을 수 있습니다.
net.IP.IsPrivate()가 놓친 범위| 범위 | 의미 |
|---|---|
100.64.0.0/10 | RFC 6598 캐리어급 NAT |
168.63.129.16/32 | Azure WireServer / 인스턴스 메타데이터 엔드포인트 |
64:ff9b::/96 | RFC 6052 NAT64 (169.254.169.254 포함 가능, 예: AWS IMDS) |
2001::/32 | RFC 4380 Teredo |
2002::/16 | RFC 3056 6to4 |
위의 IPv4 매핑 IPv6 형태도 동일한 방식으로 영향을 받습니다.
따라서 웹훅을 생성하거나 수정할 수 있는(또는 마이그레이션을 시작할 수 있는) 인증된 사용자는 클라우드 메타데이터 엔드포인트(예: NAT64 매핑을 통한 AWS IMDS, 또는 168.63.129.16의 Azure WireServer)와 내부 전용 서비스에 도달한 다음 웹훅 기록 보기를 통해 응답을 읽을 수 있습니다.
기본 정책은 Gitea의 HostMatchList 검사에서 MatchBuiltinExternal로, 이는 모든 글로벌 유니캐스트, IsPrivate()이 아닌 주소를 허용된 것으로 처리했습니다:
case MatchBuiltinExternal:
if ip.IsGlobalUnicast() && !ip.IsPrivate() {
return true
}
net.IP.IsPrivate()는 "외부"에 대한 보안 경계가 아닙니다: 이는 캐리어급 NAT, 클라우드 메타데이터 엔드포인트 또는 내부 또는 메타데이터 대상으로 라우팅될 수 있는 IPv6 전환 범위를 고려하지 않습니다.
Gitea 1.26.3에서 내장 필터를 확장하여 위의 추가 범위를 차단함으로써 수정되었습니다. 운영자는 1.26.3 이상으로 업그레이드해야 합니다. 심층 방어로서: