Container Escape in Phoenix with Dynamodb
Container Escape in Phoenix with Dynamodb — how this specific combination creates or exposes the vulnerability
A container escape in Phoenix involving DynamoDB typically occurs when an application running inside a container processes untrusted input that is later used to interact with DynamoDB in a way that exposes broader host or cluster resources. This pattern is relevant to the BOLA/IDOR and Unsafe Consumption checks in middleBrick, which test whether API endpoints safely handle identifiers and deserialize untrusted payloads.
Consider an API endpoint in Phoenix that accepts a user-supplied table_name to query DynamoDB. If the endpoint directly interpolates this value into the request without validation, an attacker may attempt path or injection-based escapes. While DynamoDB itself does not execute shell commands, a compromised DynamoDB interaction can be a pivot point. For example, an attacker might manipulate permissions or use the exposed table name to probe other backend services reachable from the container network, especially if the container has overly broad IAM roles or environment variables that leak host paths.
In a real-world scenario, a container might run a Phoenix service with an IAM role that permits dynamodb:GetItem on a specific table. If the service deserializes user-controlled JSON into DynamoDB key conditions without schema validation (e.g., using the dynamodb library in Elixir), an attacker could supply crafted attribute values that trigger unexpected behavior in downstream services. This aligns with the SSRF and Property Authorization checks, which verify that requests do not lead to unintended network interactions or data exposure.
The combination of Phoenix, DynamoDB, and containers amplifies risk when logging or error handling inadvertently exposes host filesystem paths or environment details. For instance, a DynamoDB conditional check that fails might return stack traces containing file paths, revealing container mount points that could be exploited to escape the container boundary. middleBrick’s Data Exposure and Input Validation checks are designed to detect such risky patterns before deployment.
Dynamodb-Specific Remediation in Phoenix — concrete code fixes
Remediation focuses on strict input validation, avoiding direct use of user input in DynamoDB operations, and ensuring the container runs with least privilege. Below are concrete Elixir examples using the official AWS SDK for DynamoDB in Phoenix.
1. Validate and sanitize table names
Never allow user input to directly name a DynamoDB table. Use an allowlist or regex to confirm the table name matches expected patterns.
defmodule MyApp.Dynamo do
@allowed_tables ~w(users settings logs)a
def get_item(table_name, key) when table_name in @allowed_tables do
dynamo = AwsClient.dynamo()
AwsClient.get_item(dynamo, table_name, key)
else
_ -> {:error, :invalid_table}
end
end
2. Use parameterized key conditions
Avoid string interpolation when building query requests. Instead, use the SDK’s expression attribute values.
defmodule MyApp.Dynamo do
import ExAws.Dynamo
def query_user_items(user_id) do
table = "users"
key_condition = "user_id = :uid"
expression_attr_values = %{":uid" => user_id}
query(table, key_condition)
|> expression_attribute_values(expression_attr_values)
|> ExAws.request()
end
end
3. Restrict IAM role permissions
Ensure the container’s IAM role grants only the specific DynamoDB actions required for the task, scoped to the exact table resources.
# Example IAM policy snippet (JSON)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query"
],
"Resource": "arn:aws:dynamodb:region:account-id:table/users"
}
]
}
4. Harden error handling and logging
Do not expose internal paths or stack traces in responses. Filter DynamoDB exceptions to avoid leaking environment details.
defmodule MyApp.Dynamo do
def safe_get_item(table_name, key) do
try do
AwsClient.get_item(table_name, key)
rescue
e in AwsError ->
# Log full error internally, return generic message externally
Logger.error("DynamoDB error: #{inspect(e)}")
{:error, :request_failed}
end
end
end
5. Use middleware to sanitize inputs
In Phoenix pipelines, add validation before controller actions reach DynamoDB calls.
defmodule MyAppWeb.ValidationPlug do
import Plug.Conn
def init(opts), do: opts
def call(conn, _opts) do
table_name = conn.params["table"] || ""
if String.match?(table_name, ~r/^[a-zA-Z0-9_-]+$/) do
conn
else
halt(conn |> put_resp_content_type("application/json") |> send_resp(400, Jason.encode!(%{error: "invalid table"})))
end
end
end