Quando falamos em segurança da informação, frequentemente pensamos em criptografia, firewalls e autenticação. Porém, a segurança de arquivos e objetos é um pilar igualmente crítico, pois lida diretamente com a confidencialidade, integridade e disponibilidade dos dados armazenados. Nesta aula, vamos explorar três conceitos fundamentais: path traversal, canonicalization e permissions. Esses temas são essenciais para qualquer profissional que desenvolva, configure ou audite sistemas, pois vulnerabilidades nesses pontos podem permitir acesso não autorizado, leitura de arquivos sensíveis ou até execução de código arbitrário.

Vamos começar entendendo como um atacante pode explorar caminhos de arquivos para escapar das restrições do sistema, depois veremos como a canonicalização pode mitigar esses riscos, e por fim discutiremos as permissões como camada final de controle. Ao final, você terá uma visão clara de como aplicar boas práticas de segurança em sistemas que lidam com arquivos e objetos.

Path Traversal

Path traversal, também conhecido como directory traversal, é uma vulnerabilidade que permite a um atacante acessar diretórios e arquivos fora do diretório raiz esperado de uma aplicação. Isso ocorre quando o aplicativo usa entradas fornecidas pelo usuário (como parâmetros de URL, cabeçalhos HTTP ou campos de formulário) para construir caminhos de arquivo sem validação adequada. O atacante pode manipular essas entradas para incluir sequências como ../ (que em sistemas Unix representa o diretório pai) e navegar pela estrutura de diretórios do servidor.

Por exemplo, imagine uma aplicação web que exibe arquivos de um diretório público chamado /var/www/html/files. Se a aplicação construir o caminho concatenando o parâmetro file diretamente, um atacante pode enviar file=../../../../etc/passwd e, se o sistema não proteger a subida de diretórios, o servidor retornará o conteúdo do arquivo de senhas do sistema. Esse tipo de ataque é extremamente perigoso, pois pode expor informações sensíveis, credenciais, ou até permitir o upload de arquivos maliciosos.

Para mitigar o path traversal, é essencial validar e sanitizar qualquer entrada que será usada em operações de sistema de arquivos. Boas práticas incluem: nunca confiar em entradas do usuário, usar APIs de alto nível que abstraem o sistema de arquivos, e aplicar uma lista branca de arquivos permitidos. Além disso, é recomendável usar funções de normalização de caminho (canonicalização) antes de acessar o arquivo, como veremos a seguir.

Exemplo de código vulnerável em Python (apenas ilustrativo):

import os

def read_file(filename):
    # VULNERÁVEL: concatenação direta
    path = "/var/www/files/" + filename
    with open(path, "r") as f:
        return f.read()

Exemplo de código seguro, usando validação e canonicalização:

import os

def read_file(filename):
    base_dir = "/var/www/files"
    # Remove qualquer tentativa de subir diretórios
    if ".." in filename:
        raise ValueError("Acesso negado")
    path = os.path.join(base_dir, filename)
    # Canonicaliza e verifica se o caminho está dentro do diretório base
    real_path = os.path.realpath(path)
    if not real_path.startswith(base_dir):
        raise ValueError("Acesso negado")
    with open(real_path, "r") as f:
        return f.read()

Canonicalization

Canonicalization é o processo de converter um caminho de arquivo (ou qualquer dado) em sua forma canônica, ou seja, a forma mais simples e absoluta, sem elementos como ., .., links simbólicos ou redundâncias. Em segurança, a canonicalização é crucial porque diferentes representações de um mesmo caminho podem ser usadas para contornar filtros de segurança. Por exemplo, /var/www/../www/files é equivalente a /var/www/files, mas um filtro simples que bloqueia .. pode ser enganado se o atacante usar ..%2f (codificação de URL) ou outras variações.

Ao canonicalizar um caminho, você o reduz a uma forma única e sem ambiguidades. Isso permite que a aplicação compare o caminho final com uma lista de diretórios permitidos de forma segura. Em sistemas Unix, funções como realpath() (em C) ou os.path.realpath() (em Python) resolvem links simbólicos e removem componentes como . e ... Em Java, temos File.getCanonicalPath(). Em Node.js, path.resolve() e fs.realpathSync().

É importante notar que a canonicalização deve ser feita no servidor, e não no cliente, e que o resultado deve ser validado novamente. Além disso, a canonicalização pode introduzir problemas se o caminho não existir ou se houver permissões especiais. Por isso, é comum combinar canonicalização com verificação de prefixo (por exemplo, garantir que o caminho canônico comece com o diretório base).

Exemplo em Python de canonicalização segura:

import os

def safe_path(base, user_input):
    # Junta o base com a entrada do usuário
    candidate = os.path.join(base, user_input)
    # Canonicaliza o caminho
    real = os.path.realpath(candidate)
    # Garante que o caminho permanece dentro do base
    if not real.startswith(base):
        return None
    return real

Além de caminhos de arquivos, a canonicalização também é importante em outros contextos, como URLs, endereços de e-mail e nomes de domínio. Em segurança, o princípio é sempre usar a forma canônica para comparações e autorizações.

Permissions

Permissões (permissions) são as regras que controlam quais usuários ou processos podem acessar, modificar ou executar arquivos e objetos. Em sistemas operacionais, as permissões são fundamentais para garantir a segurança, pois definem o princípio do menor privilégio: cada usuário deve ter apenas as permissões necessárias para realizar suas tarefas. Em sistemas Unix, as permissões são tradicionalmente representadas por três conjuntos de permissões (leitura, escrita e execução) para três categorias de usuários (dono, grupo e outros).

Em aplicações web e serviços, as permissões de arquivos devem ser configuradas cuidadosamente. Por exemplo, arquivos de configuração com credenciais devem ter permissões restritas (ex.: 600 ou 640) para evitar que outros usuários do sistema leiam. Diretórios de upload devem ser configurados para impedir execução de scripts (por exemplo, não permitir execução no diretório). Além disso, ao lidar com objetos em bancos de dados ou sistemas de armazenamento em nuvem, as permissões podem ser definidas por meio de ACLs (Access Control Lists) ou políticas de acesso.

Erros comuns de permissão incluem: usar permissões muito permissivas (como 777), que permitem que qualquer usuário leia, escreva ou execute; não verificar permissões ao acessar arquivos; e não considerar o contexto de execução (por exemplo, scripts executados pelo servidor web).

Exemplo de configuração de permissões em um sistema Unix:

# Restringir acesso a um arquivo de configuração
chmod 600 /etc/app/config.db

# Definir dono e grupo
chown root:app /etc/app/config.db

# Diretório de upload sem permissão de execução para outros
mkdir /var/www/uploads
chmod 755 /var/www/uploads
chown www-data:www-data /var/www/uploads

Em sistemas de arquivos, também é importante entender as permissões especiais, como setuid, setgid e sticky bit, que podem introduzir riscos adicionais. O setuid, por exemplo, permite que um executável rode com os privilégios do dono, o que pode ser perigoso se mal configurado.

Boas Práticas e Observações Finais

A segurança de arquivos e objetos exige uma abordagem em camadas. Sempre valide entradas, canonicalize caminhos antes de usá-los e aplique permissões estritas. Além disso, monitore logs para detectar tentativas de path traversal e revise regularmente as permissões do sistema. Lembre-se de que a segurança não é um estado, mas um processo contínuo.

Referências

Exercícios

  1. Explique o que é path traversal e dê um exemplo de como um atacante poderia explorar essa vulnerabilidade em uma aplicação web.
  2. ✓ Resposta: Path traversal é uma vulnerabilidade que permite a um atacante acessar arquivos fora do diretório permitido, usando sequências como ../ para subir na hierarquia. Por exemplo, se uma aplicação constrói o caminho /var/www/files/{user_input} sem validar, um atacante pode enviar ../../../../etc/passwd e ler o arquivo de senhas.
  3. O que é canonicalização e por que ela é importante para a segurança de arquivos?
  4. ✓ Resposta: Canonicalização é o processo de converter um caminho para sua forma absoluta e simplificada, sem elementos como . e .. ou links simbólicos. É importante porque permite comparar caminhos de forma confiável, evitando que variações enganem filtros. Por exemplo, /var/www/../www/files e /var/www/files são equivalentes; a canonicalização os reduz à mesma forma, permitindo verificar se o caminho está dentro do diretório permitido.
  5. Quais são as três categorias de permissões em sistemas Unix e o que cada uma controla?
  6. ✓ Resposta: As três categorias são: dono (owner), grupo (group) e outros (others). O dono é o usuário que possui o arquivo; o grupo é um conjunto de usuários que compartilham permissões; e outros são todos os demais. Cada categoria pode ter permissões de leitura (r), escrita (w) e execução (x). Exemplo: chmod 750 dá ao dono leitura/escrita/execução, ao grupo leitura/execução, e nenhuma permissão para outros.
  7. Escreva um trecho de código em Python que valide um caminho de arquivo fornecido pelo usuário, garantindo que ele esteja dentro de um diretório base usando canonicalização.
  8. ✓ Resposta:
    import os
    
    def safe_path(base, user_input):
        candidate = os.path.join(base, user_input)
        real = os.path.realpath(candidate)
        if not real.startswith(base):
            raise ValueError("Caminho fora do diretório permitido")
        return real
    
  9. Quais são as boas práticas para configurar permissões em um servidor web que recebe uploads de arquivos?
  10. ✓ Resposta: Boas práticas incluem: usar um diretório dedicado para uploads, definir permissões restritas (ex.: 755) para que o servidor web possa escrever, mas não executar scripts; desabilitar a execução de scripts no diretório (via configuração do servidor, como php_admin_flag engine off); validar os tipos de arquivo e o conteúdo; e usar nomes de arquivo aleatórios ou sanitizados para evitar path traversal.