Overview
CVE-2018-1196 describes a symlink attack in the embedded launch script used by Spring Boot when the application is installed as a Linux service. The vulnerability exists in Spring Boot releases 1.5.x up to 1.5.9 and in 2.0.0.M1 through 2.0.0.M7, where the launch script could be manipulated by a user with shell access to the service account (run_user). If the service script writes or resolves files through symlinks in places like PID files or logs, an attacker could overwrite or take ownership of arbitrary files on the same system, potentially escalating privileges or tampering with the running application. This is particularly risky on hosts where the service user has shell access and the launcher script is installed in a world-writable or symlink-following path. This vulnerability aligns with the class of issues described by CWE-59 (improper handling of resource references leading to unintended file access or modification).
Affected Versions
Spring Boot 1.5.x up to 1.5.9 (inclusive); Spring Boot 2.0.0.M1 through 2.0.0.M7
Code Fix Example
Spring Boot API Security Remediation
import java.nio.file.Path;
import java.nio.file.Paths;
public class LaunchScriptDemo {
public static void main(String[] args) {
String vulnerableScript =
"#!/bin/bash\n" +
"APP_HOME=\\"/opt/myapp\\"\n" +
"RUN_USER=\\"myapp\\"\n" +
"LOG_FILE=\\"/var/log/myapp/app.log\\"\n" +
"PID_FILE=\\"/var/run/myapp/app.pid\\"\n" +
"mkdir -p \"$(dirname \"$PID_FILE\")\"; mkdir -p \"$(dirname \"$LOG_FILE\")\"\n" +
"# Vulnerable: creates a symlink in the log path that an attacker can target\n" +
"ln -s /etc/shadow \"$LOG_FILE\" 2>/dev/null || true\n" +
"exec su -s /bin/bash -c \"$APP_HOME/bin/myapp\" \"$RUN_USER\"\n";
String fixedScript =
"#!/bin/bash\n" +
"APP_HOME=\\"/opt/myapp\\"\n" +
"RUN_USER=\\"myapp\\"\n" +
"LOG_FILE=\\"/var/log/myapp/app.log\\"\n" +
"PID_FILE=\\"/var/run/myapp/app.pid\\"\n" +
"mkdir -p \"$(dirname \"$PID_FILE\")\"; mkdir -p \"$(dirname \"$LOG_FILE\")\"\n" +
"# Fixed: validate and resolve the log path before use; do not follow or create symlinks in target location\n" +
"if [ -L \"$LOG_FILE\" ]; then\n" +
" REAL=\\$(readlink -f \"$LOG_FILE\\")\n" +
" case \"$REAL\" in\n" +
" /var/log/myapp/*) ;;" +
" *) echo \"Unsafe log path: $LOG_FILE\" >&2; exit 1;;\n" +
" esac\n" +
"fi\n" +
"touch \"$LOG_FILE\"\n" +
"exec su -s /bin/bash -c \"$APP_HOME/bin/myapp\" \"$RUN_USER\" > \"$LOG_FILE\" 2>&1 &\n";
System.out.println("Vulnerable Script:\n" + vulnerableScript);
System.out.println("\nFixed Script:\n" + fixedScript);
}
}