NetCatTest

Anonimato & OPSEC

Vulnerabilidades do I2P: CVE-2023-36325 e anonimato

Análise técnica da CVE-2023-36325, isolamento de replay, correlação temporal e auditoria de uma instalação I2P, com testes locais e fontes primárias.

Por Daniel Felipe 10 min leitura

A segurança de uma rede de anonimato não termina na criptografia. Um serviço pode manter o conteúdo cifrado e ainda revelar pistas sobre o computador que o hospeda, por diferenças de processamento, metadados ou comportamento temporal. O histórico do I2P oferece exemplos concretos dessa fronteira: uma CVE em um mecanismo antirrepetição, pesquisas sobre correlação de disponibilidade e mudanças defensivas na implementação.

Esta análise examina a CVE-2023-36325, explica o que a correção protege e propõe testes locais para compreender a classe de falha. Também diferencia a implementação Java I2P do i2pd, escrito em C++. A presença de uma vulnerabilidade em um deles não demonstra automaticamente que o outro esteja afetado.

O que o I2P tenta esconder

É preciso separar o roteador participante de uma destination, a identidade criptográfica utilizada por uma aplicação. O funcionamento da rede depende de informações para contactar roteadores, enquanto a associação entre uma aplicação e seu roteador deve permanecer protegida. Conhecer o endereço de um participante não equivale a identificar o operador de determinado serviço.

Os túneis são unidirecionais. Comunicação nos dois sentidos utiliza caminhos de entrada e saída, com proteção em camadas. A netDB distribui RouterInfo, usado para alcançar roteadores, e LeaseSets, usados para alcançar destinations por seus túneis. Essa distinção está descrita na introdução oficial à arquitetura do I2P.

Uma revisão profissional deve representar esses elementos como domínios de confiança separados. A pergunta relevante não é apenas se um pacote pode ser decifrado. É também se uma observação feita na camada pública do roteador revela algo que deveria pertencer exclusivamente à aplicação anônima. Caches, tempos, contadores e mensagens de erro entram nessa avaliação.

CVE-2023-36325: confusão de contexto no filtro de replay

A CVE-2023-36325 afeta versões do Java I2P anteriores à 2.3.0. O problema envolvia a reutilização de estado do filtro de Bloom entre contextos de mensagens. Um identificador visto pelo caminho de um cliente podia influenciar o tratamento de uma mensagem recebida diretamente pelo roteador.

Esse comportamento fornecia uma pista para associar o cliente ao roteador. A correção, publicada em 25 de junho de 2023, separou o processamento conforme a origem: túnel de cliente, túnel exploratório e recepção direta. O projeto descreve limitações práticas, incluindo falsos positivos e reinicializações, e informa que a correlação normalmente exigia vários dias. A fonte técnica é o anúncio oficial da versão 2.3.0.

O caso ilustra um vazamento de estado. A aplicação não precisava entregar um endereço IP dentro do conteúdo para que o comportamento do software fornecesse informação adicional. Isso exige avaliar diferenças observáveis entre caminhos, mesmo quando cada caminho parece correto isoladamente.

ElementoLeitura técnica
Produto afetadoJava I2P anterior à correção 2.3.0
Classe de falhaConfusão entre domínios de processamento
Consequência documentadaPista de associação entre serviço e roteador
Conclusão que não decorre do casoQuebra geral das cifras ou identificação instantânea de todos os usuários

Por que uma proteção contra repetição pode vazar informação

Uma proteção antirreplay registra identificadores já processados e rejeita repetições. Em uma implementação simplificada, a decisão depende de duas variáveis: o identificador recebido e o histórico armazenado. Se duas sessões privadas dividem esse histórico indevidamente, uma delas passa a produzir respostas que dependem da atividade da outra.

O princípio de projeto é a separação de domínio. Uma chave lógica pode incorporar o contexto definido pelo host, além do identificador. Esse contexto deve ser derivado de uma origem autenticada ou de um caminho interno confiável. Permitir que a própria mensagem escolha livremente seu domínio de validação criaria outra fronteira fraca.

Também é necessário definir o ciclo de vida do estado: prazo de validade, limite de memória, descarte e concorrência. Um teste que cobre apenas a primeira inserção não descobre efeitos após reinício, colisões, saturação ou interleaving de tarefas. Em estruturas probabilísticas, uma rejeição isolada pode ter outra explicação; a análise precisa considerar a taxa de falso positivo e a incerteza.

Laboratório local: observar e corrigir uma colisão entre contextos

O exemplo abaixo é um modelo didático original em Python. Utiliza conjuntos exatos, sem filtro de Bloom, I2NP ou acesso à rede. Portanto, demonstra a propriedade de isolamento, mas não reproduz o exploit da CVE nem substitui testes da implementação real.

class FiltroCompartilhado:
    def __init__(self):
        self.vistos = set()

    def aceitar(self, contexto, identificador):
        if identificador in self.vistos:
            return False
        self.vistos.add(identificador)
        return True

class FiltroSeparado:
    def __init__(self):
        self.vistos = {}

    def aceitar(self, contexto, identificador):
        if contexto not in {"cliente", "exploratorio", "direto"}:
            raise ValueError("Contexto invalido")
        estado = self.vistos.setdefault(contexto, set())
        if identificador in estado:
            return False
        estado.add(identificador)
        return True

compartilhado = FiltroCompartilhado()
assert compartilhado.aceitar("cliente", "lab-16")
assert not compartilhado.aceitar("direto", "lab-16")

separado = FiltroSeparado()
assert separado.aceitar("cliente", "lab-16")
assert separado.aceitar("direto", "lab-16")
assert separado.aceitar("exploratorio", "lab-16")
assert not separado.aceitar("cliente", "lab-16")
print("Isolamento entre contextos validado")

O resultado esperado é explícito. No primeiro modelo, uma operação no domínio cliente altera a resposta do domínio direto. No segundo, a repetição dentro do mesmo domínio continua rejeitada, enquanto o identificador pode existir em domínios distintos. Corrigir isolamento sem preservar a proteção contra repetição seria uma regressão funcional.

Para levar esse raciocínio a um projeto real, uma suíte de regressão deve incluir duas conexões simultâneas, expiração do estado, entradas inválidas e quotas. O teste precisa observar a propriedade prometida pela interface e usar mensagens sintéticas, sem coletar identidades de participantes da rede pública.

I2PERCEPTION: o comportamento de disponibilidade como canal lateral

O estudo Time will Tell, de Wang e colaboradores, publicado como preprint em dezembro de 2025, descreve I2PERCEPTION. A pesquisa relaciona padrões de entrada e saída de roteadores com períodos de disponibilidade de serviços. O experimento utilizou 15 floodfills e serviços controlados ao longo de aproximadamente oito meses. Os autores informam divulgação responsável e tratamento dos problemas reportados.

O resultado experimental não permite afirmar que todo serviço atual pode ser identificado com a mesma precisão. Versão, observação incompleta e comportamento de execução fazem diferença. A pesquisa é distinta da CVE de replay: usa uma relação temporal, enquanto a CVE explora estado compartilhado no processamento de identificadores.

Como análise de engenharia, há uma lição mais ampla: dois sistemas que mudam de estado juntos podem produzir uma pista de associação. Reiniciar aplicação e infraestrutura sempre no mesmo segundo, por exemplo, cria uma dependência operacional que merece revisão. Isso não prova uma identificação; define uma hipótese que precisa ser confrontada com alternativas e controles.

Uma correlação perfeita também pode ser ambígua

Este segundo modelo utiliza oito amostras binárias totalmente fictícias. A medida é apenas a fração de posições iguais, sem o algoritmo ou as medições da pesquisa. Duas máquinas diferentes apresentam a mesma sequência, mostrando por que similaridade não deve ser convertida automaticamente em identidade.

def similaridade(a, b):
    if len(a) != len(b) or not a:
        raise ValueError("Amostras incompativeis")
    return sum(x == y for x, y in zip(a, b)) / len(a)

servico = [1, 1, 0, 0, 1, 1, 0, 1]
roteadores = {
    "lab-a": [1, 1, 0, 0, 1, 1, 0, 1],
    "lab-b": [1, 1, 0, 0, 1, 1, 0, 1],
    "lab-c": [1, 0, 1, 0, 1, 0, 1, 0],
}
pontuacoes = {nome: similaridade(servico, dados)
              for nome, dados in roteadores.items()}
melhor = max(pontuacoes.values())
candidatos = [nome for nome, valor in pontuacoes.items()
              if valor == melhor]
assert candidatos == ["lab-a", "lab-b"]
print({"candidatos": candidatos, "conclusao": "ambigua"})

A produção de um relatório exige registrar janela, dados ausentes e explicações concorrentes. Uma indisponibilidade comum pode decorrer de manutenção, de uma falha do ponto de observação ou de congestionamento. Repetir o experimento com controles ajuda a testar a hipótese, mas aumentar a coleta indiscriminadamente não corrige um modelo mal definido.

Disponibilidade, Sybil e diferenças entre falha e ameaça

O modelo de ameaças oficial discute adversários que controlam múltiplos participantes e observam tráfego. Ameaças Sybil, correlação e negação de serviço pertencem a categorias diferentes. A documentação é histórica em alguns trechos e deve ser lida junto às notas atuais de versão, sem tratar suas descrições como um inventário atualizado de cada mitigação.

A versão 2.11.0, de fevereiro de 2026, registra uma primeira rodada de mitigação a ataques de spam, além da exigência de Java 17 e adoção do Jetty 12. Isso é evidência de trabalho defensivo sobre disponibilidade. Não demonstra uma nova CVE nem que uma cifra tenha sido quebrada.

Na classificação de um incidente, mantenha campos separados para conteúdo, identidade e continuidade. Uma fila saturada pode interromper um serviço sem revelar seu operador. Uma associação estatística pode prejudicar privacidade sem permitir modificar mensagens. Um defeito de interface pode comprometer o navegador local sem representar uma falha dos túneis.

Roteiro de auditoria para uma instalação própria

  1. Inventário: registrar implementação, versão efetiva, origem do pacote, Java, plugins e serviços expostos. Não comparar somente o nome comercial.
  2. Atualização: consultar o canal oficial utilizado e verificar a assinatura ou o mecanismo de autenticidade disponibilizado pelo projeto.
  3. Isolamento: limitar console e interfaces administrativas ao acesso necessário. Separar o usuário do serviço e os arquivos das aplicações.
  4. Aplicações: revisar conteúdo que denuncia identidade, chamadas externas, cookies, contas reutilizadas, logs e configurações do navegador.
  5. Continuidade: documentar reinícios, dependências e falhas observadas. Evitar interpretar ausência de resposta como prova de ataque.
  6. Regressão: executar modelos locais, confirmar propriedades e manter a validação de rede limitada a ambientes autorizados.

Na consulta editorial de 7 de outubro de 2026, o anúncio principal mais recente verificado era o 2.13.0, de julho. O repositório Debian oficial esclarece que o pacote 2.13.1 contém o I2P 2.13.0, com incremento por um problema de upload. Versão do pacote e versão do motor precisam ser registradas separadamente. Para instalar, consulte novamente o canal atual.

Perguntas frequentes sobre vulnerabilidades do I2P

A CVE-2023-36325 quebrou a criptografia do I2P?

A falha descrita envolve o processamento de estado e a associação de contextos. Não sustenta uma conclusão de quebra geral das cifras. A remediação deve considerar a implementação afetada e sua atualização.

Ter vários túneis garante anonimato em qualquer aplicação?

Uma aplicação pode revelar identidade pelo próprio conteúdo, por uma conta reutilizada ou por integrações externas. O teste deve incluir as fronteiras entre aplicação, navegador e infraestrutura, além dos mecanismos de transporte.

Posso usar os exemplos para testar a rede pública?

Os exemplos funcionam apenas com dados locais. Eles verificam propriedades de software e ambiguidade de correlação. Não contêm identificação de serviços, sondagem de participantes ou ferramenta de desanonimização.

Conclusão: testar as fronteiras que a cifra não cobre

A análise de anonimato precisa de um objeto de teste bem definido. Para cada observação, descreva quem consegue vê-la, qual estado ela depende e qual associação se pretende impedir. Isso transforma uma afirmação vaga de privacidade em propriedades verificáveis: isolamento de caches, independência entre sessões, controle das interfaces e tratamento explícito da incerteza.

O profissional ganha mais com uma evidência reproduzível e limitada do que com um rótulo genérico de rede insegura. Preserve as versões, os testes e as hipóteses descartadas. O histórico de correções serve para orientar a auditoria, enquanto a avaliação da instalação atual exige verificar seu software e seu modelo de uso.

Escrito por

Daniel Felipe é criador do NetCatTest e produz conteúdos sobre cibersegurança, privacidade digital, OSINT, laboratórios autorizados e ferramentas para estudo técnico responsável.

Compartilhar

Enviar este artigo