flawopen.com/path-traversal/Java

● CWE-918 · Alta
Pesquisa · FlawOpen

Path Traversal in Java

How unvalidated File constructors in Java allow traversal, and how to verify boundaries using getCanonicalFile and Path.startsWith.

💡 Explicação em Linguagem Simples (ELI5)

Imagine um scanner de chave de hotel que só deveria abrir quartos no segundo andar. Se um hóspede digita '../../master-safe' no teclado da porta, uma fechadura vulnerável sobe pelo corredor e abre o cofre principal da gerência.

Conceitos Centrais e Termos

Web Application Security
Componente de arquitetura principal afetado pelo CWE-918.
CWE-918
Classificação padrão Common Weakness Enumeration (CWE) para path-traversal-java.
Defense-in-Depth
Verificação de engenharia em múltiplas camadas e isolamento de limites em tempo de execução.

Fluxo de Ataque Passo a Paso

Step 1

Entrada de Caminho de Arquivo do Cliente

Um endpoint aceita um nome de arquivo ou identificador de recurso fornecido pelo usuário por parâmetro HTTP.

Step 2

Injeção de Sequência de Travessia

O invasor injeta sequências de diretório relativo como '../', '..%2f' ou caminhos absolutos no parâmetro.

Step 3

Violação do Limite do Sistema de Arquivos

O backend concatena o nome sem resolver o caminho canônico nem validar que o destino permaneça no diretório base.

Step 4

Divulgação ou Sobrescrita Arbitrária de Arquivos

O runtime abre e transmite arquivos sensíveis do sistema (como /etc/passwd ou credenciais) diretamente ao cliente.

Código-Fonte: Vulnerável vs. Seguro

✕ IMPLEMENTAÇÃO VULNERÁVEL
// VULNERABLE: Direct File instantiation with user parameter
import java.io.File;
import javax.servlet.http.*;

public class FileServlet extends HttpServlet {
    private static final File BASE_DIR = new File("/var/app/public/files");

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        String filename = req.getParameter("file");
        // Attacker sends: ../../../../etc/passwd
        File target = new File(BASE_DIR, filename);

        // Directly serves arbitrary system file!
        serveFile(target, resp);
    }
}
✓ PATCH SEGURO E ROBUSTO
// HARDENED: Canonicalize file and enforce directory prefix check
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import javax.servlet.http.*;

public class FileServlet extends HttpServlet {
    private static final File BASE_DIR = new File("/var/app/public/files");

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String filename = req.getParameter("file");
        if (filename == null || filename.isBlank()) {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }

        // 1. Resolve canonical path (resolves .. and all symlinks)
        File target = new File(BASE_DIR, filename).getCanonicalFile();
        File canonicalBase = BASE_DIR.getCanonicalFile();

        // 2. Strict boundary check using Java NIO Path
        if (!target.toPath().startsWith(canonicalBase.toPath())) {
            resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Path traversal detected");
            return;
        }

        if (!target.isFile()) {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        serveFile(target, resp);
    }
}

Lista de Verificação de Segurança para Engenharia

References