Command Injection in Spring Boot with Basic Auth
Command Injection in Spring Boot with Basic Auth — how this specific combination creates or exposes the vulnerability
Command Injection occurs when untrusted input is passed to a system shell or command processor without validation or escaping. In a Spring Boot application that uses HTTP Basic Authentication, the combination of externally supplied credentials and command execution paths can amplify risk if developers inadvertently incorporate header values or derived authentication data into shell commands.
Basic Auth sends credentials as a base64-encoded string in the Authorization header. While base64 is not encryption and can be easily decoded, the header itself may be logged, echoed, or processed by application code. If a developer uses the decoded username or password to construct shell commands—such as invoking a native tool via Runtime.getRuntime().exec or ProcessBuilder—an attacker who can influence these credentials (for example, through account creation, password reset, or a compromised client) may inject shell metacharacters like ;, &, or | to execute arbitrary commands on the host.
Spring Boot applications often integrate with external systems for provisioning, monitoring, or reporting. If the codebase retrieves the username via SecurityContextHolder or from the decoded Basic Auth token and passes it directly to a shell command, the attack surface expands. For example, consider a scenario where an admin username is used as part of a filename or a command argument without sanitization. An attacker with a valid or injectable username can escalate to command execution, leading to unauthorized file manipulation, data exfiltration, or host compromise.
Even when authentication itself succeeds, improper handling of credential-derived data in backend workflows can expose command injection vulnerabilities. This is particularly relevant when combined with other unchecked input parameters, such as request payloads or query strings, that together form a malicious command chain. The risk is not inherent to Basic Auth but arises from insecure coding practices around credential usage.
Basic Auth-Specific Remediation in Spring Boot — concrete code fixes
Remediation focuses on avoiding shell command construction with untrusted data and using safe alternatives wherever possible. If native command execution is unavoidable, rigorously validate and sanitize any component derived from authentication headers.
Secure Spring Boot Basic Auth implementation
Use Spring Security’s built-in mechanisms and avoid manual parsing of the Authorization header. The following example configures HTTP Basic Authentication safely:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.anyRequest().authenticated()
)
.httpFormLogin(Customizer.withDefaults())
.httpBasic(Customizer.withDefaults());
return http.build();
}
@Bean
public UserDetailsService users() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("alice")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
In this configuration, credentials are handled by Spring Security, and no raw header values are manually decoded or used in business logic. The UserDetailsService provides authentication without exposing raw credentials to application code.
Avoiding command construction with authentication data
Never use authentication-derived values in shell commands. If you must execute native processes, prefer passing data via standard input or environment variables that are explicitly set from trusted sources, and avoid concatenating strings that include usernames or passwords.
Instead of this unsafe pattern:
String username = getBasicAuthUsername(); // derived from header
String command = "echo Hello " + username;
Process p = Runtime.getRuntime().exec(command);
Use a controlled process invocation with a predefined command and arguments:
ProcessBuilder pb = new ProcessBuilder("echo", "Hello");
Process p = pb.start();
If you need to pass dynamic, user-specific data, validate it strictly against an allowlist and avoid shell interpretation entirely.
Validation and logging safeguards
Ensure that logging frameworks do not inadvertently output the Authorization header. Configure log sanitization to redact credentials. Also, validate inputs that may be used in any external invocation, even if they originate from authenticated contexts.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |