wger: trainer_login open redirect - ?next= parameter not validated against host
Summary
The trainer_login view in wger redirects to request.GET['next'] directly via HttpResponseRedirect() without calling url_has_allowed_host_and_scheme(). After the trainer successfully enters impersonation mode, their browser is redirected to any attacker-controlled URL supplied in the ?next= parameter, enabling Referer exfiltration and phishing.
Details
File: wger/core/views/user.py, approximately line 203
# VULNERABLE - wger/core/views/user.py
if not own:
request.session['trainer.identity'] = orig_user_pk
if request.GET.get('next'):
return HttpResponseRedirect(request.GET['next']) # no host/scheme validation
After the impersonation logic succeeds, the view performs no validation of the next parameter before issuing the redirect. An attacker who can deliver a crafted link (e.g. /en/user/2/trainer-login?next=https://evil.example/steal) to a trainer can redirect the trainer's browser to any external host immediately after the impersonation session is established. The Location header contains the raw attacker-controlled URL.
Affected endpoint:
GET /en/user/<user_pk>/trainer-login->wger.core.views.user.trainer_login(the?next=redirect branch)
Suggested patch:
--- a/wger/core/views/user.py
+++ b/wger/core/views/user.py
+from django.utils.http import url_has_allowed_host_and_scheme
+
if not own:
request.session['trainer.identity'] = orig_user_pk
- if request.GET.get('next'):
- return HttpResponseRedirect(request.GET['next'])
+ next_url = request.GET.get('next')
+ if next_url and url_has_allowed_host_and_scheme(
+ next_url, allowed_hosts={request.get_host()}, require_https=request.is_secure()
+ ):
+ return HttpResponseRedirect(next_url)
return HttpResponseRedirect(reverse('core:index'))
Adding @require_POST to trainer_login (see also VULN-030) moves the next parameter to the POST body where CSRF protection applies and eliminates the combined CSRF + open-redirect attack surface entirely.
PoC
Tested on wger/server:latest Docker image. Victim: trainer1 (gym.gym_trainer permission).
Step 1 - Authenticate as trainer:
POST /en/user/login HTTP/1.1
Host: target
Content-Type: application/x-www-form-urlencoded
username=trainer1&password=[REDACTED]&csrfmiddlewaretoken=[REDACTED]
-> 302 Found; Set-Cookie: sessionid=[trainer1_session]
Step 2 - Trainer clicks (or is delivered) the crafted link:
GET /en/user/2/trainer-login?next=https://evil.example/steal HTTP/1.1
Host: target
Cookie: sessionid=[trainer1_session]
-> 302 Found
Location: https://evil.example/steal
Step 3 - Attacker server logs Referer:
Referer: http://target/en/user/2/trainer-login?next=https://evil.example/steal
(victim user_pk and next URL exposed)
Reproducibility: 2/2 runs.
Impact
An attacker who can deliver a crafted URL to a trainer (phishing email, malicious gym management system integration, social engineering) can redirect the trainer's browser to an attacker-controlled domain after the trainer enters impersonation mode. The redirect leaks:
- The wger URL structure (including the impersonated user's
user_pk) via the browserRefererheader. - The session-rebound cookie (if the attacker page subsequently triggers an authenticated request with
credentials: 'include'targeting wger, any same-site cookie without SameSite=Strict is attached).
Combined with the trainer-login scope bypass (submitted separately), this primitive allows an attacker to silently impersonate arbitrary gym=None users and then land the trainer on an attacker page for credential harvesting.
Affected deployments: every wger instance where gym.gym_trainer is delegated to non-admin users.
Severity: Medium (CVSS 5.4). Network-reachable, low complexity, low privilege (trainer role), requires victim interaction (click), scope change (attacker's origin).
Betroffene Software
Klicken Sie auf eine Technologie, um alle zugehörigen Schwachstellen anzuzeigen.
| Plattform | Paket | Anfällige Versionen | Behoben in |
|---|---|---|---|
| Python (PyPI) | wger | < 2.6 | 2.6 |
Verweise
- CVSS-Vektor
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N- Schwäche (CWE)
CWE-601- Plattform
- Python (PyPI)
- Paket
wger- Veröffentlicht
- 06.05.2026
- Aktualisiert
- 11.10.2026 15:17
Quellen und Lizenzen
OSV / GitHub Advisory Database - GHSA-vqv8-j3mj-wjxj - CC BY 4.0
Schwachstellenhistorie: wger
Alle veröffentlichten Schwachstellen dieses Pakets (Python (PyPI)), neueste zuerst. Zeigt, ob es ein einmaliger Ausrutscher ist oder ein Paket, das man im Auge behalten muss.
- Einträge insgesamt
- 20
- Erste → letzte
- 11.2022 10.2026
- Ohne Fix
- 16
- In Angriffen ausgenutzt
- 0
Verteilung nach Schweregrad
- Kritisch 2
- Hoch 8
- Mittel 9
- Niedrig 1
Veröffentlichungen pro Jahr
- 2022: 1
- 2023: 2
- 2024: 0
- 2025: 0
- 2026: 17
-
wger: trainer_login open redirect - ?next= parameter not validated against host dieser Eintrag
Erkennen Sie Schwachstellen in Ihrer Anwendung
Mit der DockRay-Integration und aktivierter Softwareinventarisierung prüft DockRay gemeldete Komponentenversionen auf bekannte Schwachstellen und benachrichtigt Sie über bestätigte Treffer. Die Abdeckung hängt von der unterstützten Technologie und den verfügbaren Meldungen ab.