SSRF

How to Fix SSRF in Spring Boot [Month Year] [CVE-2018-1196]

[Fixed month year] Updated CVE-2018-1196

Overview

CVE-2018-1196 describes a symlink-based attack in Spring Boot's embedded launch script used to run applications as Linux services (systemd or init.d). The script included with Spring Boot 1.5.9 and earlier and 2.0.0.M1 through 2.0.0.M7 could be coerced to write to arbitrary files on the same system via symlinks, allowing the run_user (the user account used to start the service) to overwrite and potentially take ownership of files outside the intended scope. This risk primarily affects deployments where the Spring Boot application is installed as a service using the embedded script and the run_user has shell access. If the application is not installed as a service, or if a fixed, non-embedded deployment path is used, the vulnerability does not apply. The vulnerability is categorized under CWE-59 (Improper Handling of Tenancy/Privilege Escalation through symlinks) and is distinct from SSRF in typical usage, but it can have similar privilege escalation implications on the host.

Affected Versions

Spring Boot 1.5.9 and earlier and 2.0.0.M1 through 2.0.0.M7

Code Fix Example

Spring Boot API Security Remediation
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class ServiceLauncher {
    public static void main(String[] args) throws Exception {
        String mode = (args.length > 0) ? args[0] : "vulnerable";
        String target = (args.length > 1) ? args[1] : "/tmp/run_user";
        if ("vulnerable".equalsIgnoreCase(mode)) {
            writeVulnerable(target);
        } else {
            writeFixed(target);
        }
        System.out.println(mode + " mode completed");
    }

    // Vulnerable pattern: writes to a user-controlled path without validation (symlink risk)
    public static void writeVulnerable(String userPath) throws IOException {
        Path target = Paths.get(userPath);
        // Potentially follows a symlink to a sensitive location
        Files.createDirectories(target.getParent());
        Files.write(target, "RUN_AS_SERVICE".getBytes(),
                StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
    }

    // Fixed pattern: restrict writes to a safe base dir and normalize against symlinks
    public static void writeFixed(String userPath) throws IOException {
        Path base = Paths.get("/var/lib/myapp");
        Path target = base.resolve(userPath).normalize();
        if (!target.startsWith(base)) {
            throw new SecurityException("Attempt to escape base directory");
        }
        Files.createDirectories(target.getParent());
        Files.write(target, "RUN_AS_SERVICE".getBytes(),
                StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
    }
}

CVE References

Choose which optional cookies to allow. You can change this any time.