Clickjacking in Chi with Cockroachdb
Clickjacking in Chi with Cockroachdb — how this specific combination creates or exposes the vulnerability
Clickjacking is a client-side attack that tricks a user into interacting with a hidden or disguised UI element, often by loading a target site inside an invisible iframe. When the target site uses Cockroachdb-backed services in the Chi web framework, the combination of Chi routes, EEx templates, and Cockroachdb data flows can expose patterns that facilitate clickjacking if framing rules are not explicitly enforced.
Chi does not set default HTTP headers that prevent a page from being embedded. If a view rendered by Chi (e.g., a dashboard or admin page) connects to Cockroachdb to render sensitive data, an attacker can host a malicious page that embeds that Chi route in an <iframe>. Without a Content-Security-Policy frame-ancestors directive or an X-Frame-Options header, the browser will render the page inside the attacker’s frame, enabling UI redressing. User interactions such as clicking a button or submitting a form may be captured by the attacker’s overlays, while the response is proxied through the legitimate Cockroachdb-driven Chi endpoint.
The exposure is not in Cockroachdb itself, which is a distributed SQL database, but in how Chi applications expose endpoints that return HTML intended for top-level browsing. If those endpoints rely on session cookies or API keys without additional anti-CSRF protections, and if they lack frame-busting or CSP headers, the data retrieved from Cockroachdb can be presented in a hostile context. For example, an endpoint like /admin/invoices that queries Cockroachdb for rows and renders them in a table becomes a vector if embedded invisibly, because the user’s authenticated session is included with the request to Chi, and the response may contain sensitive data obtained from Cockroachdb.
Real-world patterns observed in the wild include embedding administrative panels inside invisible iframes and overlaying fake buttons or forms on top of them. Because Chi encourages a clear separation between routing, controller logic, and EEx templates, developers might focus on business logic and data correctness in Cockroachdb queries while overlooking framing risks. The risk is especially acute when Chi routes serve pages that perform state-changing operations (POST/PUT/DELETE) based on GET links, because an attacker can trick a logged-in user into loading a crafted page that triggers those operations via the embedded Chi+Cockroachdb flow.
To assess this during a scan, middleBrick tests whether Chi endpoints that interact with Cockroachdb send frame-ancestors or X-Frame-Options controls, and whether sensitive pages are safely non-embeddable. Findings include missing CSP frame-ancestors, absent X-Frame-Options, and pages that return sensitive data without anti-clickjacking safeguards, all of which increase the risk that data retrieved from Cockroachdb can be exposed via clickjacking.
Cockroachdb-Specific Remediation in Chi
Remediation centers on HTTP headers and UI safeguards in Chi, while ensuring that Cockroachdb interactions remain safe from misuse in embedded contexts. Below are concrete, idiomatic examples using Chi 5 and EEx with Cockroachdb via libpgx.
1) Set CSP frame-ancestors and X-Frame-Options in Chi
For pages that render Cockroachdb data, add a strict Content-Security-Policy header with frame-ancestors and set X-Frame-Options. This prevents browsers from embedding the page in iframes regardless of the source.
defmodule MyAppWeb.Router do
use MyAppWeb, :router
pipeline :browser_with_csp do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, {MyAppWeb.Layouts, :root}
plug :put_secure_browser_headers
end
pipeline :browser_with_frame_protection do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, {MyAppWeb.Layouts, :root}
plug :put_secure_browser_headers
plug MyAppWeb.Plugs.FrameProtection
end
scope "/", MyAppWeb do
pipe_through :browser_with_frame_protection
get "/admin/invoices", InvoiceController, :index
end
end
Define the FrameProtection plug to set headers:
defmodule MyAppWeb.Plugs.FrameProtection do
import Plug.Conn
@moduledoc """
Sets X-Frame-Options and CSP frame-ancestors to prevent clickjacking.
"""
def init(opts), do: opts
def call(conn, _opts) do
conn
|> put_resp_header("x-frame-options", "DENY")
|> put_resp_header(
"content-security-policy",
"default-src 'self'; frame-ancestors 'none'"
)
end
end
2) Use anti-CSRF tokens for state-changing actions
Even with framing protections, ensure POST/PUT/DELETE requests that change state and that fetch or display Cockroachdb data include CSRF tokens. Phoenix generators typically include this, but if building custom forms, embed a token and verify it on submit.
<!-- In an EEx template rendered by Chi -->
<form method="post" action="/admin/invoices/archive">
<input type="hidden" name="_csrf_token" value="<%= Plug.CSRFProtection.get_csrf_token() %>">
<button type="submit">Archive</button>
</form>
On the controller side, validate the token:
defmodule MyAppWeb.InvoiceController do
use MyAppWeb, :controller
plug :verify_csrf when action in [:update, :delete, :archive]
def archive(conn, %{"id" => id}) do
# Query Cockroachdb safely after CSRF verification
case Invoices.archive(id) do
{:ok, _} -> redirect(conn, to: "/admin/invoices")
{:error, reason} -> render(conn, "error.html", reason: reason)
end
end
end
3) Avoid leaking sensitive data in embeddable contexts
If a Chi route queries Cockroachdb and returns sensitive information, ensure it is not served via GET endpoints that could be triggered by an attacker’s iframe. Prefer authenticated POST for sensitive operations, and avoid including sensitive data in URLs or in responses that could be captured via referer headers.
defmodule MyAppWeb.InvoiceController do
use MyAppWeb, :controller
def show(conn, %{"id" => id}) do
# Ensure the caller is authenticated and authorized before querying Cockroachdb
with %{id: user_id} <- conn.assigns.current_user,
{:ok, invoice} <- Invoices.get_for_user(id, user_id) do
render(conn, "show.html", invoice: invoice)
else
_ -> send_resp(conn, 403, "Forbidden")
end
end
end
middleBrick can test these protections by checking for the presence of frame-ancestors and X-Frame-Options headers on Chi routes that interact with Cockroachdb, and flag endpoints that expose sensitive data without anti-clickjacking safeguards.