
Forgejo 16.0.5 - 높음 - 원격 - SSRF - OpenID 디스커버리가 공격자가 제어하는 URL을 가져옴
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-openid-discovery-ssrf
분류: SSRF 도달 범위: 원격
Forgejo 16.0.5 (8d24b7d) - Forgejo
[openid] ENABLE_OPENID_SIGNIN이 켜져 있을 때, 인증되지 않은 POST /user/login/openid는 공격자의 URL을 yohcop openid-go v1.0.1에 전달한다. 해당 라이브러리의 패키지 수준 헬퍼는 http.DefaultClient를 사용한다. 이 경로에는 hostmatcher가 없다. Webhook과 마이그레이션은 아웃바운드 HTTP를 필터링한다. OpenID는 그렇지 않다.
로그인 폼에 접근할 수 있는 사람은 Forgejo 호스트에서 loopback, RFC1918, CGNAT, IMDS를 대상으로 Yadis GET을 유도할 수 있다.
| ID | 아직 CVE 없음 |
| 분류 | SSRF |
| 도달 범위 | 원격 (OpenID 로그인이 활성화된 경우 인증 불필요) |
| CWE | CWE-918 |
| CVSS | 높음: 8.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N |
| 제품 | Forgejo |
| 영향받음 | ENABLE_OPENID_SIGNIN이 설정된 v16.0.5 (8d24b7d)까지; Gitea CVE-2026-58314의 잔재 |
| 인증 | 인증 불필요 |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용 |
계정이 필요 없다. OpenID URL을 POST한다. Forgejo 호스트가 이를 가져온다.
| 권한 | 메서드 / 싱크 | 정찰 / 무결성 / 가용성 | 랩 입증 또는 추론 |
|---|---|---|---|
| loopback을 대상으로 Yadis GET 유도 | openid=http://127.0.0.1:18080/로 인증되지 않은 POST /user/login/openid | 정찰 (Forgejo 호스트에서의 아웃바운드 HTTP) | 랩 입증. Oracle이 127.0.0.1에서 Accept: application/xrds+xml과 함께 GET /를 확인 |
| RFC1918, CGNAT, link-local, IMDS 프로브 | 동일한 http.DefaultClient Discover, IP 필터 없음 | 정찰 | 클라이언트로부터 추론. 랩은 loopback만 사용 |
| 로그인된 상태의 add-OpenID에서 반복 | POST /user/settings/security/openid도 RedirectURL을 호출하고 allowedOpenIDURI를 건너뜀 | 정찰 | 핸들러로부터 추론. 랩은 인증되지 않은 로그인 POST를 사용 |
| 로그인 오류에서 응답 본문 읽기 | CVE-2021-45325 이후, 오류가 더 이상 fetch를 덤프하지 않음 | 정찰 | 랩 입증 종료. 이 잔재는 요청이며 HTML 유출이 아님 |
이 핀에서 종료됨: OpenID association CSRF (openIDState 세션 nonce), webhook/migrate hostmatcher (여전히 그곳에서 사용됨), git followRedirects=false, migrate LookupIP CVE-2026-82556. 랩은 OpenID 로그인을 완료하지 않으며 셸을 반환하지 않는다.
웹 설치 프로그램 체크박스는 기본적으로 켜져 있다 (EnableOpenIDSignIn = MustBool(!InstallLock) 잠금 해제 상태에서, 이후 app.ini에 기록됨). 잠금 후, 생략된 키는 false이다. Docker app.ini 템플릿에는 [openid] 섹션이 없으므로, 마법사 없이 미리 잠긴 이미지는 운영자가 키를 설정하지 않는 한 꺼져 있다. 빈 WHITELISTED_URIS는 모든 URI를 허용한다.
v16.0.5는 OpenID association CSRF를 종료했다. 나는 그래도 그 표면을 계속 지켜보았다. Gitea PR 38406 / CVE-2026-58314는 hostmatcher로 필터링된 클라이언트를 전용 openid-go 인스턴스에 넣었다. 이 핀은 여전히 패키지 수준 헬퍼를 호출한다.
이미 기록된 잘못된 방향: association CSRF 재신고 (그 nonce는 트리에 있음); Docker 미리 잠긴 이미지를 기본값으로 취급 (마법사가 체크박스를 켬); 이전 OpenID 오류 문자열 유출 기대; 리버스 셸. 연극.
python3 forgejo-openid-discovery-ssrf-Abraxas-Labs.py
또는:
cd lab
./run.sh
오직 http://127.0.0.1:19330만 대상으로 한다. 이미지 codeberg.org/forgejo/forgejo:16.0.5. Oracle은 Forgejo netns를 공유하고 127.0.0.1:18080을 바인딩한다.
IOC post-openid status=200
IOC xrds-hits count=1
SUCCESS forgejo-openid-discovery-ssrf how=live post=/user/login/openid openid=http://127.0.0.1:18080/ path=/ accept=application/xrds+xml peer=127.0.0.1 post-status=200 FORGEJO-OPENID-DISCOVERY-WITNESS
Gitea PR 38406과 동일: hostmatcher로 필터링된 http.Client를 전용 openid-go 인스턴스에 넣는다. WHITELISTED_URIS를 두 번째 게이트로 유지한다. loopback, RFC1918, CGNAT, link-local, 메타데이터를 차단한다.
modules/auth/openid/openid.goGNU Affero GPL v3.0. LICENSE 참조. Loopback 랩 전용. 보증 없음.