
Gitea의 repo migrate 엔드포인트에서 발생하는 인증된 SSRF에 대한 개념 증명 및 실습 환경으로, git이 HTTP 리다이렉트를 따라 루프백 git HTTP로 접근하여 내부 객체를 유출하는 취약점입니다.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitea-git-redir-ssrf
분석 문서: https://abraxaslabs.tech/research/gitea-git-redir-ssrf
Gitea 1.27.3 - Gitea
IsMigrateURLAllowed는 입력한 URL에 대해 한 번만 수행하는 net.LookupIP입니다. 그런 다음 바이트는 git clone --mirror를 거칩니다. HandleGitCmdHTTPRedirection은 git이 해당 홉을 따라가지 못하게 막아야 합니다. 하지만 아무것도 하지 않습니다. 주석 자체가 취약점입니다. GitLab이 .git 없이 301을 반환하기 때문에 http.followRedirects=false를 빼놓은 것입니다. 풀 미러 페치는 동일한 no-op을 호출합니다.
로그인한 사용자는 허용 목록에 있는 미끼 호스트에서 마이그레이션할 수 있으며, git은 302를 따라 루프백 git HTTP로 진입합니다. 내부 객체가 사용자가 소유한 저장소에 저장됩니다.
| ID | 아직 CVE 없음 |
| CWE | CWE-918 |
| CVSS | High: 7.7 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N |
| 제품 | Gitea |
| 영향 범위 | v1.27.3 (146cc3e)까지 |
| 인증 | 인증됨 (기본 공개 등록) |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용 |
등록한 뒤, http://127.0.0.1:.../internal.git으로 302 리다이렉트하는 외부처럼 보이는 URL에서 마이그레이션합니다. 루프백으로의 직접 마이그레이션은 거부됩니다. 리다이렉트를 따라간 클론은 거부되지 않습니다. 증거 파일이 공격자의 저장소에 저장됩니다.
file:// 디스크 읽기가 아닙니다. /api/internal에 대한 X-Gitea-Internal-Auth가 아닙니다 (git은 해당 헤더를 설정하지 않습니다). 인증되지 않은 RCE가 아닙니다. git이 본문을 저장했다는 것을 별도로 입증하지 않는 한 메타데이터 RCE도 아닙니다.
같은 태그의 잔여물: keys IDOR, hostmatcher 0.0.0.0/8.
v1.27.3은 2026 GHSA 물결을 마감했습니다: CVE-2026-60004 (diffpatch 훅 RCE, CISA KEV), CVE-2026-59774 (미인증 Org-mode #+INCLUDE), fork-PR Actions 게이트, 리버스 프록시 X-WEBAUTH-USER 기본값. 해당 사항들은 **1.27.3+**에 머무르면 됩니다. 그래도 저는 그 태그를 계속 파고들었습니다.
CVE-2026-59765는 Go uri.Open을 수정했습니다. CVE-2026-22874는 Go reservedIPNets를 수정했습니다. git의 리다이렉터는 여전히 FIXME입니다. 변경 로그의 "disable HTTP redirects on pull mirror sync"는 이 함수가 아닙니다.
랩은 Gitea를 8.8.4.2에 두어 8.8.4.10의 미끼 호스트가 hostmatcher에게 외부로 보이게 합니다. 내부 git HTTP는 Gitea netns에서 루프백 전용으로 바인딩됩니다 (network_mode: service:gitea, 포트 9418). 127.0.0.1로의 직접 마이그레이션은 반드시 실패해야 합니다. 리다이렉트를 따라간 클론은 반드시 성공해야 합니다. redir.py는 /bait.git을 http://127.0.0.1:9418/internal.git으로 302 리다이렉트합니다. 증거 파일 WITNESS에는 GHSA-GITEA-GIT-REDIR-SSRF가 포함되어 있습니다.
이미 기록된 잘못된 시도들: ALLOW_LOCALNETWORKS true (그러면 허용 목록이 사라짐); file://; X-Gitea-Internal-Auth; 리버스 셸. 다 극에 불과합니다. 직접 루프백 마이그레이션이 거부되는 것이 대조군입니다.
클라이언트 버그는 제품 버그처럼 보입니다. http.client를 가리는 헬퍼는 패킷을 전혀 보내지 않습니다. HTTPResponse의 .recv()는 .read()가 아닙니다. 한 번 언급하는 이유는 이것이 시간을 잡아먹었고, 잠시 동안 1.27.3이 일을 끝낸 것처럼 보였기 때문입니다.
cd lab
./run.sh
오직 http://127.0.0.1:18103만 대상으로 지정합니다. ALLOW_LOCALNETWORKS=false.
negative-loopback status=422 You can not import from disallowed hosts
migrate-bait status=201 clone_addr=http://8.8.4.10/bait.git
fetch raw/WITNESS status=200 GHSA-GITEA-GIT-REDIR-SSRF
SUCCESS Gitea #2 git HTTP redirect SSRF
제출 시점의 DNS를 경계로 삼지 마십시오. http.followRedirects=false를 강제하고(그리고 GitLab이 여전히 작동하도록 클론 URL을 .git으로 정규화), 또는 모든 홉에서 hostmatcher를 다시 실행하는 다이얼러를 통해 git HTTP를 프록시하십시오.
HandleGitCmdHTTPRedirection · IsMigrateURLAllowedGNU Affero GPL v3.0. LICENSE를 참조하십시오. 루프백 실험실 전용. 보증 없음.