Vulnerabilidade RCE no qBittorrent: erro de validação de certificado SSL ignorado por 14 anos
(sharpsec.run)- O DownloadManager do qBittorrent ignorou erros de validação de certificado SSL de 6 de abril de 2010 até 12 de outubro de 2024, por cerca de 14 anos e 6 meses, tornando vários fluxos de download uma superfície de ataque em cenários de interceptação de rede
- O problema recebeu o identificador CVE-2024-51774 e sua exploração exige acesso MITM ou spoofing de DNS
- Foram afetados caminhos que usam o DownloadManager, como busca, download de
.torrent, feeds RSS e download de favicon, e até certificados expirados ou autoassinados podiam ser aceitos - No Windows, o prompt de instalação do Python e o fluxo RSS de verificação de atualizações podem levar ao download de executáveis ou à manipulação de links de atualização se a resposta das URLs codificadas no binário for alterada
- É mais seguro atualizar baixando manualmente o v5.0.1 diretamente no navegador do que usar o prompt interno de atualização do app
Bypass de validação de certificados por mais de 14 anos
- A classe DownloadManager do qBittorrent vinha ignorando todos os erros de validação de certificado SSL desde o commit
9824d86, em 6 de abril de 2010 - O comportamento padrão mudou para validar certificados no commit
3d9e971, em 12 de outubro de 2024 - O primeiro patch release era o qBittorrent v5.0.1, lançado 2 dias antes da data de publicação do texto
- O problema foi registrado como CVE-2024-51774
- As condições de exploração são acesso MITM ou spoofing de DNS
A ampla superfície de ataque criada pelo DownloadManager
- O uso do DownloadManager é amplo, então foram afetados busca, download de
.torrent, feeds RSS e download de favicon - Esses caminhos podiam aceitar certificados expirados, autoassinados ou ambos
- Os principais vetores de impacto se dividem em instalação do Python no Windows, atualização de software, feeds RSS e superfície de ataque na descompressão de bibliotecas
Download de executável no fluxo de instalação do Python no Windows
- No Windows, se não houver uma versão suficientemente recente do Python instalada, o qBittorrent exibe uma janela perguntando se o usuário quer instalar ou atualizar o Python para usar plugins de busca
- Se o usuário clicar em Yes, opção marcada por padrão, ou pressionar Enter, o aplicativo baixa o instalador do Python de uma URL
python.orgcodificada no binário - Após o download, o qBittorrent renomeia o arquivo para
.exee o executa, apagando o arquivo temporário ao final - Esse comportamento existe de junho de 2015 até hoje, afetando da
v3.2.1até av5.0.0 - Em outras variantes de sistema operacional, se o Python estiver ausente ou não for recente o bastante, o widget de busca é desativado, e o mesmo comportamento não parece reproduzível
- O executável pode ser salvo em um caminho como
C:\Users\_user_\AppData\Local\Temp\is-G61QK.tmp - Pode ser por causa do comportamento do
QProcess, mas duas threads do executável podem ser criadas, apenas uma encerra e a outra pode permanecer em estado de sleeping
Manipulação de URL via RSS de verificação de atualização
- Versões instaladas do qBittorrent no Windows ou Linux, quando não são arquivo
appImage, verificam atualizações por padrão ao iniciar - A verificação de atualização funciona baixando um documento XML de uma URL RSS do Fosshub codificada no binário e analisando as informações de release do programa
- Se o XML trouxer uma versão superior à atualmente em execução, o fluxo extrai a URL de atualização e pergunta ao usuário se deseja visitar essa URL, sem filtragem ou validação adicional
- Se o usuário aceitar o prompt, essa URL é aberta no navegador padrão
- O usuário tende a esperar um arquivo
.exedentro de um contexto de confiança, por ter vindo de um link fornecido pelo software - Se um invasor redirecionar para um site de compartilhamento de arquivos como o MediaFire, o usuário pode baixar um executável controlado pelo atacante como se fosse uma atualização
- Como o qBittorrent é open source, é fácil adicionar uma backdoor à versão mais recente e recompilá-la
- Os desenvolvedores fornecem chaves para verificar assinaturas dos binários, mas a proteção só funciona se o usuário realmente validar e respeitar uma falha de verificação
Injeção em feeds RSS e links
- Todos os feeds RSS analisados pelo aplicativo passam pelo DownloadManager, então podem ser sequestrados
- As URLs visitadas pela vítima podem ser observadas e catalogadas, e URLs de RSS tendem a ser estáticas e persistirem por muito tempo
- O elemento
linkde cada item é analisado diretamente e pode ser baixado quando o usuário dá duplo clique - Mesmo sem adulteração MITM, uma URL arbitrária inserida por um autor ou por um atacante que poluiu o feed RSS assinado pelo usuário pode ser aberta com um único duplo clique
- A CVE-2019-13640 era uma vulnerabilidade que permitia execução remota de comandos por meio de metacaracteres de shell no nome do torrent ou no parâmetro atual do tracker, e um atacante MITM poderia inserir dados maliciosos no RSS, ampliando o risco de combinação
Download do banco GeoIP e superfície de ataque na descompressão
- Ao iniciar, o qBittorrent baixa automaticamente por padrão de uma URL codificada no binário um banco de dados MaxMind GeoIP binário com extensão
.gze o descomprime - Se houver uma vulnerabilidade na descompressão zlib, um atacante pode mirar essa superfície com um arquivo arbitrário de até 64 MB
- O exemplo citado, CVE-2022-37434, foi um buffer overflow Critical com CVSS 9.8 em 2022, mas não se aplica aqui porque a função
inflateGetHeader()não é chamada - O código que analisa o banco de dados binário da MaxMind após a descompressão está bem protegido em 2024, mas isso não era necessariamente verdade no passado, e pode ter havido superfície de ataque adicional
- Em um commit da função
gzip::decompress(), o buffer de destino mudou de uma alocação estática na stack para uma alocação dinâmica na heap, e havia checagens antes da escrita, então não era explorável
Cenários de ataque automatizáveis
- Tanto a URL do instalador do Python quanto a URL do feed RSS de atualização são codificadas no binário, então um script malicioso em ambiente MITM pode enumerar versões vulneráveis e atacar
- A URL do feed RSS dificilmente seria visitada fora do momento em que o qBittorrent está em execução, então pode servir como impressão digital do software
- Como não havia validação de certificado, o atacante pode fazer spoofing do servidor de destino sem precisar de uma implantação Man-On-The-Side mais complexa, como QUANTUM
- Pela natureza das URLs codificadas no binário, é possível interceptar seletivamente apenas as requisições não validadas do qBittorrent sem alertar a vítima por falhas de conexão segura no navegador ou em outros aplicativos
- Com a opção
-sdo mitmproxy junto de um script Python, é possível automatizar o seguinte- Trocar o
.exedo Python por um executável arbitrário: RCE com um único clique - Substituir automaticamente a URL do RSS de atualização do qBittorrent: sequestro de navegador/RCE, com interação moderada do usuário
- Substituir todos os links ou links específicos no visualizador RSS do qBittorrent: RCE até 2019, sequestro de downloads
- Trocar o
Upgrade e formas de mitigação
- É necessário atualizar para o qBittorrent v5.0.1
- Recomenda-se fazer o upgrade por download manual direto no navegador, e não pelo prompt interno de atualização do app
- Como alternativa, é possível usar clientes como Deluge e Transmission, que não têm essa vulnerabilidade
- Não é fácil tratar ataques que exigem MITM apenas como risco teórico, considerando o histórico recente e casos concretos em alguns países
- Houve contato com o mantenedor do repositório, mas não houve resposta sobre a intenção de publicar um advisory de segurança no GitHub
1 comentários
Comentários do Hacker News
A classe DownloadManager do qBittorrent ignorou todos os erros de validação de certificado SSL em todas as plataformas por 14 anos e 6 meses, desde o commit 9824d86 em 6 de abril de 2010
Parece bem grave
O que chama atenção é que isso não era um bug, e sim uma “funcionalidade”
void downloadThread::ignoreSslErrors(QNetworkReply* reply,QList errors) {
// Ignore all SSL errors
reply->ignoreSslErrors(errors);
}
https://github.com/qbittorrent/qBittorrent/commit/9824d86a3c...
Não quero minimizar essa vulnerabilidade, mas considerar como única linha de defesa uma combinação válida de certificado TLS e nome de domínio em um caminho que permite execução remota de código beira o desastre
No mínimo, se um aplicativo baixa e executa algo da internet, ele deveria fixar uma versão específica e validar o hash do arquivo baixado antes de executá-lo
Então isso significa que atualização automática é impossível?
Acho que o critério mínimo é verificação de assinatura
Se o software for atualizado com frequência suficiente, também haverá oportunidades suficientes para rotação de chave
No Windows, dá para usar um certificado de assinatura de código na ferramenta de build e deixar o sistema operacional validar o binário baixado
Só que é preciso usar um servidor de timestamp na assinatura de código, senão ela quebra quando o certificado expira
Aqui eu diria que a verificação de hash é difícil por causa da natureza potencial de um ataque man-in-the-middle
Se o atacante puder ver e alterar o conteúdo da requisição, a checagem de hash deixa de servir para algo além de confirmação de integridade
De modo geral, parece que não se dá atenção suficiente, do ponto de vista de segurança, à forma como apps desktop fazem requisições de atualização automática ou checagem para domínios específicos
Há cenários como o autor original deixar de renovar o domínio e ele acabar sendo tomado de forma maliciosa, mas ainda não encontrei uma boa solução para isso
Seria surpreendente se fosse possível saber quantas pessoas foram realmente afetadas por isso ao longo de cerca de 15 anos
Fico pensando o quão importante foi a validação de SSL para um atacante que consegue se misturar na parte mais suspeita da internet
Coisas demais “simplesmente funcionam” porque ninguém liga, e agora que isso ganhou visibilidade, a situação só pode piorar para quem não faz atualização automática
Esse código servia para baixar o Python de python.org, e embora a exploração fosse possível, ela teria que ser bastante direcionada e já exigiria algum nível de acesso ao alvo
Para explorar de outras formas, seria preciso algo como sequestrar o domínio python.org, e provavelmente todo mundo perceberia
Se alguém foi afetado, provavelmente foi em ataques direcionados
Boa parte do texto parece inflada; há de fato algo problemático, mas a expressão “execução remota de código no qBittorrent” é tecnicamente correta, porém alarmista em excesso
Parece quase impossível obter dados reais, mas seria interessante se fosse possível ver isso
Se você já olhou o código do qBittorrent, sabe que era um código terrível
Havia funções sem comentários por várias páginas, com espaçamento de linhas apertado, e aquilo parecia as anotações de prisão de um paciente psicótico injustamente encarcerado
Mesmo na pequena parte que eu vi, algumas páginas comprimidas, não havia nenhuma checagem de valor de retorno
Pelo que lembro, se um campo recebesse um valor correto de 3 letras em vez do valor correto habitual de 2 letras, o programa travava cerca de um minuto depois
Há uns 20 anos eu já tinha programado em C++ por dinheiro duas vezes, e depois da mensagem do mantenedor do tipo “então vá olhar você mesmo”, rodei no depurador
Cheguei ao ponto em que a GUI lia tanto o valor errado quanto o valor correto, e ao seguir aquele valor percebi que, de repente, -1 estava sendo passado para todo lado, e o programa simplesmente continuava por um bom tempo
No fim, o lado executado com o valor errado travou em uma função bem distante, junto com uma mensagem de erro que parecia coisa de um paciente psicótico injustamente encarcerado
Depois disso, um dos desenvolvedores reais do qBittorrent corrigiu aquilo na versão seguinte, mas, de todo modo, era esse o nível do código
Só consta “BUGFIX: Don't ignore SSL errors (sledgehammer999)”
https://www.qbittorrent.org/news
Pessoalmente, acho que deveria haver um aviso de segurança
Mesmo com a verificação correta de certificado, baixar e executar um executável remoto é, por definição, uma vulnerabilidade de execução remota de código
O Syncthing também usa esse modelo; ele provavelmente verifica certificados, mas atualização automática sem supervisão é logicamente difícil de distinguir de um RAT/trojan
A parte da vulnerabilidade só existe quando um terceiro pode explorar
Como de qualquer forma você precisa confiar no fornecedor do software, atualização automática por si só não é uma vulnerabilidade de execução remota de código
Embora isso não tenha sido a causa direta desta vulnerabilidade, parece que aplicações como esta, que se comunicam com muitos nós potencialmente maliciosos, teriam muito a ganhar com segurança de memória
Só que as implementações atuais parecem todas escritas em C++
O texto também aborda esse tipo de possibilidade de vulnerabilidade no item 4
Até o Deluge, escrito em Python, depende do libtorrent, feito em C++
Não sei se existe um fork moderno do antigo cliente Azureus baseado em Java
Hoje em dia, muitos clientes BitTorrent separam a GUI do processo daemon que faz o processamento real dos torrents, então talvez dê para chegar a um bom equilíbrio entre segurança, desempenho e experiência do usuário fazendo o daemon em Java e conectando-o a uma GUI nativa
Mesmo procurando por alto, dá para achar algumas bibliotecas BitTorrent puras em Go
Existe o rqbit, escrito em Rust e sem dependência do libtorrent: https://github.com/ikatson/rqbit
Fazendo uma pergunta preguiçosa em vez de pesquisar por conta própria para fomentar a discussão: por onde se começaria para criar uma alternativa ao libtorrent?
Também tenho curiosidade se já houve tentativas ou casos de sucesso, e se existem clientes realmente funcionais usando outras implementações
Especialmente nos itens mais para o fim, isso parece um pouco exagerado
O item 1, “loader de executável malicioso com recurso oculto”, diz que o cliente baixa o Python de python.org via HTTPS
Não é bom, e o fato de estar fixado em 3.12.4 também é um problema, mas não vejo um caminho claro de exploração que não exija tanto ataque man-in-the-middle quanto interação do usuário
O item 2, “sequestro do navegador + download de executável”, diz que o cliente baixa um arquivo RSS via HTTPS e, sob certas condições, pergunta ao usuário se deve abrir a URL contida nesse arquivo
É ainda menos arriscado que o item 1, e mesmo que se faça um ataque man-in-the-middle no usuário e o convença a clicar em “update”, no fim das contas só dá para mostrar uma página web
O item 3, “injeção de URL arbitrária em feed RSS”, parece ser um caso em que o pesquisador confundiu o comportamento esperado do cliente RSS
O item 4, “superfície de ataque da biblioteca de descompressão”, significaria que, se fosse possível encontrar uma vulnerabilidade no zlib, daria para fazer coisas muito piores do que atacar um cliente de torrent
Descompressão de entrada é, em princípio, uma operação presumida como segura
A primeira coisa que me vem à cabeça é algo como um servidor HTTP que suporte compressão de stream
Sim
Não quero soar negativo demais, mas parece que “pesquisadores” de segurança estão agarrando até possibilidades remotíssimas por um pouco de notoriedade
Eu teria mais respeito se isso tivesse sido documentado com honestidade, mas a forma como foi feito aqui só causa incômodo
Se os erros de certificado não tivessem sido ignorados, esses itens teriam sido triviais
Como o problema original é ignorar erros de SSL, na prática todos os downloads via HTTPS foram rebaixados a downloads via HTTP, e isso permite ataque mesmo sem man-in-the-middle
Em outras palavras, a ausência de validação SSL deu aos revisores uma falsa sensação de segurança sobre URLs HTTPS
Concordo
Chamar isso de “vulnerabilidade de execução remota de código” é um exagero absurdo
Da próxima vez vão dizer que há uma “vulnerabilidade de execução remota de código” porque um navegador web permite baixar e executar programas de sites arbitrários que podem ou não ser seguros?
Ou vão anunciar de novo que, se você vive num país autoritário, o governo pode fazer coisas ruins?
O qBittorrent é um cliente 1000 vezes mais rápido do que as outras opções mencionadas na matéria, então é chocante ver a qualidade dessas questões tão baixa
Quem entrega o desempenho é o libtorrent-rasterbar (libtorrent.org)
Para compilar e rodar a versão mais recente, https://github.com/userdocs/qbittorrent-nox-static é um script auxiliar razoável que usa Docker para gerar um binário estático
Eu queria rodar o 5.0.0 usando o libtorrent 1.2, e esse script foi de longe o jeito mais fácil