Input Path Not Normalized

ID

java.input_path_not_normalized

Severity

low

Resource

Path Resolution

Language

Java

Tags

CWE:180, NIST.SP.800-53

Description

Improper normalization of external input prior to its usage.

This can lead to security risks such as directory traversal and filtering bypass attacks if inputs are not standardized before validation.

Rationale

When handling external inputs, it is crucial to standardize (or normalize) these inputs to a canonical form before performing any validation. This guards against potential bypass techniques where malicious inputs are encoded in alternative formats, circumventing blacklisting and other simplistic filters.

Consider the following flawed Java example:

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.text.Normalizer;
import java.io.FileInputStream;

public class Sample {
    public void method (HttpServletRequest req) throws IOException {
        String input = req.getParameter("input");
        String s = "\uFE64" + input + "\uFE65";

        // Validate
        if (s.matches("")) { // Pattern is incomplete for demonstration
            // Found blacklisted tag
            throw new IllegalStateException();
        } else {
            // ...
        }

        // Normalize - done too late in the flow
        s = Normalizer.normalize(s, Form.NFKC);
        FileInputStream in = new FileInputStream(s);
    }
}

In this example, the input parameter is potentially manipulated with encoded characters (\uFE64 and \uFE65), posing a risk as it bypasses simplistic filtering meant to detect unsafe inputs.

The normalization occurs only after validation, allowing encoded patterns to slip through checks.

Remediation

To address this vulnerability, inputs should be normalized prior to their validation and use. This ensures any encoded or non-standard representations are converted into a consistent format suitable for secure processing.

Here’s how you can implement a secure approach in Java:

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.text.Normalizer;

public class SecureSample {
    public void secureMethod(HttpServletRequest req) throws IOException {
        String input = req.getParameter("input");

        // Normalize input first
        String input = Normalizer.normalize("\uFE64" + input + "\uFE65", Normalizer.Form.NFKC);

        // Perform validation on normalized input
        if (input.contains("<script>")) { // example pattern to check blacklisted content
            throw new IllegalStateException("Potentially malicious input detected");
        }

        // Resolve path to prevent directory traversal
        Path basePath = Paths.get("/var/www/");
        Path inputPath = Paths.get(input).normalize();
        Path resolvedPath = basePath.resolve(inputPath).normalize();

        // Ensure the resolved path is within the base directory
        if (!resolvedPath.startsWith(basePath) || Files.isRegularFile(resolvedPath)) {
            throw new SecurityException("Unauthorized file access attempt detected!");
        }

        // Safely proceed with file operations
        try (FileInputStream in = new FileInputStream(resolvedPath.toString())) {
            // Perform file operations
        }
    }
}

This secure approach ensures that the input is immediately normalized to prevent encoding bypass before any validation processes occur. Additionally, it implements safe path resolution to mitigate potential directory traversal attacks, adhering to security best practices.