Atacando um cliente FTP: o MGET pode trazer mais do que você esperava
4 de abril de 2018
0 minutos de leituraIntrodução
É comum ouvirmos falar de vulnerabilidades em clientes HTTP, como navegadores, geralmente exploradas por conteúdo malicioso na Web. Nada de novo nisso. Mas você sabia que os próprios clientes FTP também podem ter vulnerabilidades exploráveis? Servidores maliciosos aos quais os clientes se conectam podem atacá-los.
Nesta publicação, vou mostrar uma vulnerabilidade interessante de travessia de caminho que identificamos e divulgamos de forma responsável a vários fornecedores afetados em novembro de 2017. Essa vulnerabilidade pode afetar diversos aplicativos e bibliotecas, permitindo que um servidor FTP malicioso crie ou sobrescreva arquivos em qualquer lugar do sistema de arquivos local. Como você verá nos detalhes a seguir, o problema decorre da falta de validação e afeta não apenas clientes FTP, mas também muitos outros aplicativos e bibliotecas de diferentes ecossistemas, como Java, npm e outros.
A vulnerabilidade
Certo, vamos ao problema! Queremos criar uma função que baixe o conteúdo de uma pasta FTP remota para uma pasta local. Como a maioria de nós já sabe, o próprio protocolo FTP não oferece um comando para baixar pasta, mas podemos combinar vários outros comandos para atingir esse objetivo.
Podemos:
Listar todos os arquivos da pasta remota (com os comandos FTP
LISTouNLST)Para cada arquivo listado acima: baixar o arquivo e salvá-lo em uma pasta local (com os comandos FTP
GETouMGET)
Um exemplo de código Java que faz isso usando a biblioteca Apache commons-net poderia ser assim:
O código acima percorre cada arquivo retornado pelo servidor e o baixa para uma pasta de destino local. Por exemplo, se o primeiro arquivo na pasta remota se chamar passwd e nossa pasta de destino local for /var/data/sync/, o arquivo será baixado para /var/data/sync/passwd.
Mas e se o servidor FTP se tornar malicioso e, em vez de responder ao comando LIST com passwd, retornar ../../../../etc/passwd como nome do arquivo? O código acima acabará colocando o arquivo em /var/data/sync/../../../../etc/passwd, praticamente sobrescrevendo /etc/passwd com o arquivo recém-baixado.
Você pode dizer que ../../../../etc/passwd não é um nome de arquivo válido — e de fato não é. Mas a RFC não diz que ele não é válido. Tecnicamente, ela não se posiciona sobre o sistema de arquivos e deixa que o cliente e o servidor decidam como lidar com isso. Por exemplo, a resposta de um servidor FTP baseado em Windows a um comando LIST pode ser assim:
Já um sistema baseado em Unix tem esta aparência:
Na verdade, há muitos outros formatos de sistema de arquivos. Veja a lista dos formatos compatíveis com a biblioteca apache commons-net:
Assim, o cliente FTP típico não valida os nomes de arquivo e os retorna como estão, deixando a validação a cargo dos desenvolvedores. Nem é preciso dizer que essa validação acaba sendo esquecida. Isso fica evidente ao analisar projetos hospedados no GitHub ou vários sites com exemplos e trechos de código, como StackOverflow e CodeJava.
Estudo de caso: Apache HIVE
O Apache Hive é um projeto de software de data warehouse desenvolvido sobre o Apache Hadoop para resumir, consultar e analisar dados. O Hive oferece uma interface semelhante a SQL para consultar dados armazenados em vários bancos de dados e sistemas de arquivos integrados ao Hadoop. Entre outros recursos, ele permite copiar dados de servidores FTP usando o comando COPY-FROM-FTP.
Ao analisar o código, encontramos a chamada retrieveFileList().
Dentro da função retrieveFileList, vemos que o nome de arquivo retornado pelo servidor é anexado ao nome do diretório sem nenhuma validação (name = dir + name;). O arquivo é adicionado a uma fila para ser baixado mais tarde.
Mais tarde, na thread de download, o arquivo é retirado da fila e baixado do servidor.
Um possível ataque consiste em sobrescrever o arquivo ssh authorized_keys do usuário root, permitindo fazer login como root posteriormente. Vamos supor que uma instância do Apache Hive se conecte ao nosso servidor FTP todos os dias para baixar dados de comerciantes. Para executar esse ataque, modificaríamos o servidor FTP para enviar ao cliente nomes de arquivo maliciosos com travessia de caminho. Por exemplo, poderíamos responder a um comando LIST com ../../../../../../../home/root/.ssh/authorized_keys.
Quando o Hive executar esse comando (supondo que esteja rodando como root), o arquivo authorized_keys do root será sobrescrito por um arquivo conhecido pelo invasor.
A vulnerabilidade acima foi divulgada de forma responsável à Apache Foundation. Veja a linha do tempo:
Data | Evento |
|---|---|
11/2/2017 | Vulnerabilidade descoberta pela equipe de pesquisa de segurança da Snyk |
11/8/2017 | Lista dos produtos Apache afetados divulgada à fundação. |
2/5/2018 | A Apache nos informou que planejava lançar uma versão corrigida até o fim de fevereiro. |
4/4/2018 | Publicação do artigo. |
Os detalhes também foram publicados no banco de dados CVE em 4/4/2018 para o projeto Apache Hive.CVE-2018-1315: a instrução ‘COPY FROM FTP’ em HPL/SQL pode gravar em qualquer local se o servidor FTP estiver comprometido:
Gravidade: Moderada
Fornecedor: The Apache Software Foundation
Versões afetadas: Hive 2.1.0 a 2.3.2
Descrição: Quando a instrução ‘COPY FROM FTP’ é executada usando a extensão HPL/SQL do Hive, um servidor FTP comprometido ou malicioso pode fazer com que o arquivo seja gravado em qualquer local do cluster em que o comando é executado. Isso acontece porque o código do cliente FTP no HPL/SQL não verifica o local de destino do código baixado. Isso não afeta os usuários hivecli e hiveserver2, pois hplsql é um script de linha de comando separado e precisa ser invocado de outra forma.
Mitigação: Quem usa HPL/SQL com Hive 2.1.0 a 2.3.2 deve atualizar para a versão 2.3.3. Como alternativa, é possível desativar o uso de HPL/SQL por outros meios.
Resumo
Mostramos como uma vulnerabilidade presente em alguns aplicativos e bibliotecas de clientes FTP é causada pela falta de validação adequada dos dados recebidos do servidor FTP. Problemas semelhantes já foram identificados. Por exemplo, em 2002, Steve Christey, engenheiro principal de segurança da informação na MITRE, descobriu que o problema existia em vários clientes FTP, incluindo o cliente FTP nativo do Linux e o wget.
Validar entradas é essencial — e não apenas por segurança. Como desenvolvedor, é muito fácil pensar em como uma pessoa comum usaria nossas APIs, mas também é fundamental prever entradas inesperadas que possam vir de invasores. Ao processar listagens de diretórios recebidas de servidores FTP, valide-as: bloqueie nomes de arquivo que comecem com / ou contenham ...
Comece a participar de desafios de Capture the Flag
Aprenda a resolver desafios de Capture the Flag assistindo sob demanda ao nosso workshop virtual introdutório.