HIGH command injectionphoenixmutual tls

Command Injection in Phoenix with Mutual Tls

Command Injection in Phoenix with Mutual Tls — how this specific combination creates or exposes the vulnerability

Command Injection occurs when an attacker can inject and execute arbitrary system commands through an application. In a Phoenix application using Mutual TLS (mTLS), the risk can emerge not from the TLS layer itself, but from how the application uses client identity information obtained after mTLS authentication.

Mutual TLS verifies both the client and the server. Once the server has verified the client certificate, it often extracts details such as the Distinguished Name (DN), Common Name (CN), or Serial Number from the client certificate. If these values are used to construct system commands—such as logging commands, invoking external scripts, or calling binaries—and they are not properly sanitized, an attacker who presents a malicious certificate can inject shell metacharacters (e.g., ;, &, |, `, or $()) that lead to Command Injection.

For example, a developer might log certificate details using an OS command:

cmd = "openssl x509 -subject -in " & cert_path
System.cmd("sh", ["-c", cmd])

If cert_path is derived from user-controlled certificate fields and contains shell metacharacters, an attacker can break out of the intended command and execute arbitrary code. This is a classic OS Command Injection scenario (OWASP API Top 10 A03:2023). Even with mTLS ensuring only trusted clients connect, the application must treat extracted certificate attributes as untrusted input.

Another scenario involves authorization logic where the client CN is used to determine access rights and also passed to a shell command for reporting or filtering. An attacker with a valid certificate but malicious CN could exploit this to run unintended commands. middleBrick detects such patterns during scans, including checks related to Input Validation and Unsafe Consumption, and highlights Command Injection as a high-severity finding when detected.

Mutual Tls-Specific Remediation in Phoenix — concrete code fixes

Remediation focuses on never passing untrusted data—including certificate-derived fields—into system commands. Use structured data and safe libraries instead of shell commands, and strictly validate or encode any input that must be used in external calls.

1. Avoid Shell Commands Entirely

Replace OS command execution with native Erlang/Elixir libraries. For certificate parsing, use the public_key and ssl modules instead of invoking openssl via System.cmd.

# Unsafe: building a shell command with certificate-derived data
cert_path = "/tmp/certs/#{cn}.pem"
System.cmd("openssl", ["x509", "-subject", "-in", cert_path])

# Safe: use Erlang's public_key to parse the certificate
{:ok, cert_bin} = File.read(cert_path)
{:ok, cert} = :public_key.pkix_decode_cert(cert_bin, :otp)
subject = :public_key.pkix_verify_signature(cert) # example usage
# Process subject as structured data; no shell involved

2. Strict Input Validation and Encoding

If you must construct a command, validate and strictly encode all external inputs. Use allowlists for known-safe values and encode shell metacharacters. Prefer passing arguments as a list to System.cmd to avoid shell interpretation.

# Unsafe: direct interpolation
System.cmd("logger", ["User: #{user_cn}"])

# Safe: validate CN format and pass as argument without shell interpolation
if valid_cn?(user_cn) do
  System.cmd("logger", ["User: " <> user_cn])
else
  # handle invalid input
end

defp valid_cn?(cn) when is_binary(cn) do
  # Allow only alphanumeric, hyphen, underscore, and dot
  Regex.match?(~r/^[a-zA-Z0-9_.-]+$/, cn)
end

3. Principle of Least Privilege

Run the Phoenix server with minimal OS permissions. Even if injection occurs, this limits the impact. Combine mTLS client authorization with application-level role checks rather than relying on shell-level controls.

# config/config.exs
config :my_app, MyAppWeb.Endpoint,
  http: [port: 4000],
  transport_options: [socket_opts: [:binary, {:certfile, "path/to/server.pem"}, {:cacertfile, "path/to/ca.pem"}]]

# In your controller, after verifying mTLS, extract CN safely and enforce authorization
conn = fetch_certificate(conn)
cn = get_client_cn(conn)
if authorized_for?(cn, action) do
  # proceed with business logic
else
  send_resp(conn, 403, "Forbidden")
end

middleBrick scans can identify risky patterns such as shell command construction with certificate-derived inputs and map findings to frameworks like OWASP API Top 10 and SOC 2. The scans include checks for Authentication, Input Validation, and Unsafe Consumption, helping teams detect Command Injection risks in mTLS-enabled services.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Does mTLS itself prevent Command Injection?
No. Mutual TLS authenticates and encrypts communication, but it does not prevent Command Injection. After mTLS authentication, any data derived from client certificates (such as CN or serial) must still be treated as untrusted input and validated or encoded before any external command construction.
How can middleBrick help detect Command Injection in a Phoenix app using mTLS?
middleBrick scans the API endpoints without authentication, testing inputs and observing outputs for injection indicators. It checks Input Validation and Unsafe Consumption among 12 parallel security checks, and highlights Command Injection with severity and remediation guidance, including risks related to certificate-derived data used in commands.