Clickjacking in Phoenix with Cockroachdb
Clickjacking in Phoenix with Cockroachdb — how this specific combination creates or exposes the vulnerability
Clickjacking is a client-side UI redress attack where an invisible or disguised element tricks a user into interacting with a page they did not intend to interact with. In a Phoenix application that uses Cockroachdb as the backend database, the risk emerges from how UI layers and authentication flows are composed rather than from Cockroachdb itself, which is a distributed SQL database and does not render UI. When Phoenix templates or live views embed third‑party content, or when authorization checks are limited to controller actions without considering embedded frames, an attacker can embed your authenticated pages in an iframe and overlay interactive elements, leveraging the user’s session and permissions on Cockroachdb via the Phoenix app.
For example, if a Phoenix page that performs a sensitive Cockroachdb mutation (such as updating user roles or transferring funds) is loaded inside an invisible iframe, and the page relies solely on session cookies for authentication without anti‑clickjacking defenses, an attacker’s page can capture clicks on hidden buttons or links. Because Cockroachdb does not have its own UI, the danger is that the Phoenix application’s UI mishandling propagates to database operations: the attacker’s crafted UI triggers unintended state changes in Cockroachdb via the Phoenix app’s endpoints. This is especially relevant when OpenAPI specs generated for the Phoenix API expose admin or write endpoints without clarifying UI context, and when runtime findings from a middleBrick scan highlight missing frame‑option headers or missing content security policy directives that could mitigate embedding.
Consider a live view that directly executes a Cockroachdb query based on user input without verifying the request origin. If the view is embedded, inputs can be manipulated by the attacker. middleBrick’s checks for Input Validation and Property Authorization are useful here because they can detect whether the endpoint sufficiently validates referrer headers and enforces same‑origin policies. The presence of an unauthenticated LLM endpoint in your API surface, if exposed inadvertently, can additionally widen the attack surface by allowing automated extraction of UI behavior or session context that may aid clickjacking strategies. Therefore, securing Phoenix against clickjacking involves both UI‑level frame controls and strong authorization checks before any Cockroachdb mutation occurs.
Cockroachdb-Specific Remediation in Phoenix — concrete code fixes
Remediation focuses on ensuring that Phoenix UI layers protect actions that result in Cockroachdb mutations, and that API endpoints validate context before executing queries. Below are concrete examples using Phoenix controllers and live views, with embedded Cockroachdb interactions via Ecto.
Controller-level protection with frame options and CSRF
Ensure every controller that performs Cockroachdb writes sets the X‑Frame‑Options header and includes CSRF tokens. In Phoenix, you can set these per controller or globally in the endpoint pipeline.
defmodule MyAppWeb.ControllerBase do
use MyAppWeb, :controller
before_action :set_security_headers
defp set_security_headers(conn, _opts) do
conn
|> put_resp_header("x-frame-options", "DENY")
|> put_resp_header("content-security-policy", "frame-ancestors 'self'")
end
end
Controllers that issue changes to Cockroachdb should require authentication and verify ownership or role permissions before proceeding. For example:
defmodule MyAppWeb.AccountController do
use MyAppWeb, :controller
alias MyApp.Accounts
alias MyApp.Repo
plug :require_authenticated_user when action in [:update_profile]
def update_profile(conn, %{"user" => user_params}) do
user = conn.assigns.current_user
# Ensure the update targets the same Cockroachdb row the user owns
case Accounts.update_user(user, user_params) do
{:ok, _} ->
conn |> put_flash(:info, "Profile updated") |> redirect(to: ~p"/profile")
{:error, changeset} ->
render(conn, "edit.html", changeset: changeset)
end
end
end
Live view protection with origin checks
When using Phoenix LiveView that triggers Cockroachdb writes, validate the request origin and use assign-based authorization rather than relying solely on params.
defmodule MyAppWeb.DashboardLive do
use MyAppWeb, :live_view
alias MyApp.Repo
import Ecto.Query
def mount(_params, session, socket) do
if valid_origin?(session["origin"]) do
{:ok, assign(socket, can_save: true)}
else
{:ok, assign(socket, can_save: false)}
end
end
def handle_event("save", %{"data" => data}, socket) do
if socket.assigns.can_save do
# Perform Cockroachdb update via Ecto
Repo.transaction(fn ->
Repo.update!(Ecto.Changeset.change(socket.assigns.record, data))
end)
{:noreply, socket}
else
{:noreply, put_flash(socket, :error, "Invalid request origin")}
end
end
defp valid_origin?(origin) do
# Allow only same-origin or trusted referrer patterns
case origin do
"https://app.example.com" -> true
_ -> false
end
end
end
API endpoint validation with context
For JSON API endpoints that directly affect Cockroachdb, validate the Origin header and enforce a strong Content-Security-Policy in the API pipeline as well. Combine this with proper ownership checks.
defmodule MyAppWeb.Api.V1.TransferController do
use MyAppWeb, :controller
plug :validate_incoming_origin
def transfer(conn, %{"amount" => amount, "to_id" => to_id}) do
from_id = conn.assigns.current_user.id
if from_id != to_id and amount > 0 do
# Execute Cockroachdb transaction
case MyApp.Transactions.transfer(from_id, to_id, amount) do
{:ok, _} -> json(conn, %{status: "ok"})
{:error, reason} -> conn |> put_status(:bad_request) |> json(%{error: reason})
end
else
conn |> put_status(:bad_request) |> json(%{error: "invalid request"})
end
end
defp validate_incoming_origin(conn, _opts) do
case get_req_header(conn, "origin") do
[origin] when origin in ~w(https://app.example.com) -> conn
_ -> conn |> halt() |> send_resp(403, "Forbidden")
end
end
end
By aligning UI protections with strict backend validation, the combination of Phoenix and Cockroachdb remains robust against clickjacking. Security scans with middleBrick can surface missing headers or overly permissive CSP rules that would otherwise leave these integrations exposed.