Listen to this Post
How the Vulnerability Works
The trainer_login view in wger/core/views/user.py (line 203) accepts a `next` parameter via the HTTP GET method. After the impersonation logic completes, the view returns an `HttpResponseRedirect` using the value of `request.GET.get(‘next’)` directly, without any validation of the host or scheme. This missing call to Django’s `url_has_allowed_host_and_scheme()` allows an attacker to supply a fully qualified external URL (e.g., https://evil.example/steal`). When a logged‑in trainer clicks a crafted link like `/en/user/2/trainer-login?next=https://evil.example/steal`, the server responds with a `302 Found redirect whose `Location` header contains the attacker‑controlled URL. The trainer’s browser is immediately sent to the malicious site, leaking the wger URL structure (including the impersonated user’s user_pk) via the `Referer` header. If the attacker’s page later triggers an authenticated request with credentials: 'include', any session cookie without `SameSite=Strict` is attached. Combined with a trainer‑login scope bypass, this primitive can lead to silent impersonation of arbitrary users and credential harvesting. The issue is network‑reachable, requires low attacker privileges (trainer role) and victim interaction (a click), and changes the security scope to the attacker’s origin, yielding a CVSS score of 5.4 (Medium).
DailyCVE Form
Platform: wger
Version: 2.5 and below
Vulnerability : Open redirect
Severity: Medium
date: 2026-04-28
Prediction: 2026-05-15
What Undercode Say
Check if instance is vulnerable curl -I "https://target/en/user/2/trainer-login?next=https://evil.example/steal" Expected: 302 Found with Location: https://evil.example/steal Simulate a trainer login and capture the redirect curl -X GET "https://target/en/user/2/trainer-login?next=https://evil.example/steal" \ -H "Cookie: sessionid=trainer1_session" \ -v
Exploit
GET /en/user/2/trainer-login?next=https://evil.example/steal HTTP/1.1 Host: target Cookie: sessionid=trainer1_session
Server responds with:
HTTP/1.1 302 Found Location: https://evil.example/steal
The trainer’s browser is redirected to https://evil.example/steal`, leaking the `Referer` header which contains the wger URL and the `next` parameter.user_pk
<h2 style="color: blue;">Protection from this CVE</h2>
- Apply the suggested patch: use `url_has_allowed_host_and_scheme()` to validate the `next` parameter before redirecting.
- Alternatively, change the `trainer_login` view to `@require_POST` so the `next` parameter is moved to the POST body where CSRF protection applies.
- Update wger to the latest version once the official patch is released.
- As a workaround, manually add `url_has_allowed_host_and_scheme()` validation in `wger/core/views/user.py` around line 203.
<h2 style="color: blue;">Impact</h2>
An attacker who can deliver a crafted URL to a trainer (e.g., via a phishing email or a malicious gym management integration) can redirect the trainer’s browser to an attacker‑controlled domain immediately after impersonation mode is entered. This leaks the wger URL structure (including the impersonated user’s) via the `Referer` header. If the attacker’s page subsequently makes authenticated requests withcredentials: ‘include’`, any session cookie without `SameSite=Strict` will be attached, enabling session rebound. Combined with a trainer‑login scope bypass, this can lead to silent impersonation of arbitrary `gym=None` users and credential harvesting. Every wger instance where the `gym.gym_trainer` permission is delegated to non‑admin users is affected.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

