Command Injection in Spring Boot with Cockroachdb
Command Injection in Spring Boot with Cockroachdb — how this specific combination creates or exposes the vulnerability
Command injection occurs when untrusted input is concatenated into operating system commands executed by the application. In a Spring Boot application using CockroachDB, the risk typically arises not from CockroachDB itself, but from unsafe practices in application code that happen to interact with the database while also invoking external processes. For example, a developer might use database-stored metadata (such as hostnames, file paths, or script names) to construct shell commands via Runtime.getRuntime().exec() or ProcessBuilder. If an attacker can influence the database content that feeds into these commands, they may inject arbitrary shell instructions.
Consider a scenario where a Spring Boot service stores backup script paths or host identifiers in CockroachDB. If the application later retrieves these values and uses them unsafely in command execution, an attacker who can modify the database (via SQL injection or administrative access) can alter the stored data to include malicious shell payloads. When the application then invokes the command, the injected shell code runs with the application’s privileges. Even without direct SQL injection, an attacker might control an input field that is later used to build a command string, and the application might query CockroachDB to enrich the command context, creating a multi-stage injection path.
The combination of Spring Boot’s flexible runtime and CockroachDB’s distributed nature does not inherently introduce new injection classes, but it can expand the attack surface. For instance, if an application uses the database to store configuration for external toolchains (e.g., backup utilities, data import scripts), and then uses Java’s ProcessBuilder to run those tools, unsanitized data from CockroachDB can become a source of command injection. Additionally, logging or diagnostic features that include raw user input alongside database identifiers may inadvertently expose patterns that facilitate injection in downstream processes. The key issue is always the unsafe construction of operating system commands using data that ultimately originates from or is influenced by the database.
Cockroachdb-Specific Remediation in Spring Boot — concrete code fixes
Remediation focuses on avoiding shell command construction entirely and strictly validating and sanitizing any data that originates from CockroachDB before it reaches process execution. The safest approach is to use Java’s built-in facilities without a shell, or to use parameterized scripts with fixed paths.
1. Avoid Shell Invocation
Never concatenate strings to form shell commands. Instead, use ProcessBuilder with a list of arguments, which avoids shell interpretation of special characters. Even when using values stored in CockroachDB, pass them as explicit arguments rather than embedding them in a command string.
// Unsafe: building a command string that may include database-derived values
String unsafeCmd = "pg_dump -h " + dbHost + " -U " + dbUser + " mydb";
Runtime.getRuntime().exec(unsafeCmd); // Dangerous
// Safe: use ProcessBuilder with explicit arguments
ProcessBuilder pb = new ProcessBuilder("pg_dump", "-h", dbHost, "-U", dbUser, "mydb");
pb.redirectErrorStream(true);
Process process = pb.start();
// Handle input/output streams appropriately
2. Validate and Restrict Database-Driven Values
If your application retrieves configuration from CockroachDB, enforce strict allowlists on values that can be used in process execution. For example, if the database stores a script name, verify it against a predefined set of permitted scripts.
// Assume this value comes from a CockroachDB row
String scriptName = resultSet.getString("script_name");
// Whitelist validation
Set<String> allowedScripts = Set.of("backup_daily.sh", "cleanup.sh");
if (!allowedScripts.contains(scriptName)) {
throw new IllegalArgumentException("Invalid script name");
}
// Safe execution with fixed base path
ProcessBuilder pb = new ProcessBuilder("/opt/scripts/" + scriptName, "--arg", safeValue);
Process process = pb.start();
3. Use Parameterized Queries for Database Access, Not Command Building
Ensure that all interactions with CockroachDB in Spring Boot use parameterized queries (e.g., via JdbcTemplate or Spring Data JPA) to prevent SQL injection, which is a separate but related risk. This keeps data integrity intact and prevents attackers from manipulating query results to influence command construction.
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class DbConfigRepository {
private final JdbcTemplate jdbcTemplate;
public DbConfigRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public DbConfig findById(Long id) {
String sql = "SELECT host, user FROM db_config WHERE id = ?";
return jdbcTemplate.queryForObject(sql, (rs, rowNum) -> {
DbConfig config = new DbConfig();
config.setHost(rs.getString("host"));
config.setUser(rs.getString("user"));
return config;
}, id);
}
}
record DbConfig(String host, String user) { }
4. Secure Logging and Diagnostics
If logging includes data from CockroachDB, ensure sensitive or user-controlled fields are sanitized to avoid leaking patterns that could aid injection attempts. Avoid logging raw command strings that include database-derived values.
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 |