Skip to content
winfunc
Disclosure record · Sylius

Administrator password-reset link poisoning enables account takeover

The password-reset email derived its absolute authority from the anonymous request Host header

SyliusDisclosedSource record

CVSS 3.1 base score

High
8.8/ 10

Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Record

Project
Sylius
Severity
High8.8
CVE
None listed
Disclosed
Trace
3 steps

Summary

Source

reset-password operation

src/Sylius/Bundle/ApiBundle/Resources/config/api_platform/resources/admin/AdminUserPassword.xml:27

Sink

adminPasswordReset template

src/Sylius/Bundle/CoreBundle/Resources/views/Email/adminPasswordReset.html.twig:41

An unauthenticated attacker could request an administrator password reset with an attacker-controlled Host header. The legitimate email then contained the real reset token under the attacker's HTTPS origin, allowing token capture when the administrator clicked it.

Root cause. Reset token generation and email rendering happened synchronously inside the initiating request. Twig's absolute url() helper used the request-derived router context, while the application supplied neither a strict trusted-host policy nor a canonical security-link origin.

Remediation evidence. Sylius confirmed the report, published GHSA-77w3-2367-7xvq with an explicit Winfunc Research credit, and released fixes in 1.12.25, 1.13.17, 1.14.20, 2.1.16, and 2.2.9.

Severity

Attack vectorAV
Network
Attack complexityAC
Low
Privileges requiredPR
None
User interactionUI
Required
ScopeS
Unchanged
ConfidentialityC
High
IntegrityI
High
AvailabilityA
High

Metric values as published in the disclosure vector. Meters show how far each value raises exposure.

Source-to-sink trace

  1. Source · attacker-controlledsrc/Sylius/Bundle/ApiBundle/Resources/config/api_platform/resources/admin/AdminUserPassword.xml:27

    reset-password operation

  2. Step 01src/Sylius/Bundle/ApiBundle/Resources/config/api_platform/resources/admin/AdminUserPassword.xml:27

    The public reset operation accepts the victim administrator email while the request carries attacker-selected authority metadata.

    python
    POST /api/v2/admin/administrators/reset-password
    Host: attacker.example
    
  3. Step 02src/Sylius/Bundle/ApiBundle/CommandHandler/Account/RequestResetPasswordEmailHandler.php

    The handler generates a fresh token and dispatches the email command within the same poisoned request context.

    php
    $token = $this->tokenGenerator->generate();
    $this->commandBus->dispatch(new SendResetPasswordEmail($email, $token));
    
  4. Step 03src/Sylius/Bundle/CoreBundle/Resources/views/Email/adminPasswordReset.html.twig:41

    The absolute URL helper embeds the attacker-controlled authority together with the valid secret token.

    python
    {{ url('sylius_admin_password_reset', {'token': user.passwordResetToken}) }}
    
  5. Sinksrc/Sylius/Bundle/CoreBundle/Resources/views/Email/adminPasswordReset.html.twig:41

    adminPasswordReset template

Impact

Reported impact

The attacker can replace the administrator's password and exercise that account's administrative privileges. Downstream access to customer data, orders, configuration, and user management depends on the victim administrator's assigned roles.

Attack surface

The unauthenticated Sylius administrator password-reset API on deployments that accepted arbitrary Host headers.

Preconditions

The attacker knows the administrator's email and controls an HTTPS origin. The victim must click the legitimate reset email; no mailbox access, existing session, or Sylius credential is required.

Attack path

  1. 1

    Request a reset for the target administrator while supplying the attacker's Host value.

  2. 2

    Sylius sends the legitimate mailbox a link whose authority is the attacker origin.

  3. 3

    Capture the fresh token when the administrator follows the link.

  4. 4

    Redeem the token at the real public reset endpoint with an attacker-chosen password.

  5. 5

    Authenticate as the compromised administrator.

Proof of concept

Reproduction5 stages
  1. 01

    Environment setup

    Use an isolated affected Sylius instance, a test administrator mailbox, and an attacker-controlled local HTTPS origin.

  2. 02

    Target configuration

    Route a request with an arbitrary Host value to Sylius without an upstream host allowlist, matching the vulnerable deployment condition.

  3. 03

    Exploit delivery

    Send the public reset request with Host: attacker.example, then follow the received email and record the token-bearing request made to the attacker origin.

  4. 04

    Expected response

    The email link points to the attacker host and contains a valid administrator reset token that the real reset endpoint accepts.

  5. 05

    Outcome

    Patched releases construct the security link from trusted canonical configuration, so request authority cannot redirect a valid reset token to another host.

Remediation

Guidance

Upgrade to a version listed in GHSA-77w3-2367-7xvq, configure a canonical application origin, and enforce trusted hosts at both the application and reverse proxy.

Before and after−1+7
{{ url('sylius_admin_password_reset', {'token': token}) }}const hostname = $this->channelContext->getChannel()->getHostname();$path = $this->router->generate(  'sylius_admin_render_password_reset',  ['token' => (string) $user->getPasswordResetToken()],  UrlGeneratorInterface::ABSOLUTE_PATH,);return ($this->unsecuredUrls ? 'http://' : 'https://') . $hostname . $path;
View original source record

Check the upstream record for the project's current remediation status.

Your codebase

Investigate the paths that matter in your codebase.

Winfunc can trace relevant code paths, preserve supporting evidence, and prepare remediation suggestions for engineering review within an agreed scope.