Session Fixation in Fastapi with Cockroachdb
Session Fixation in Fastapi with Cockroachdb — how this specific combination creates or exposes the vulnerability
Session fixation occurs when an application accepts a user-supplied session identifier without validation, allowing an attacker to force a victim into using a known session. In a Fastapi application using Cockroachdb as the session store, the risk arises when session identifiers are accepted via query parameters, headers, or cookies and then written to Cockroachdb without regeneration upon authentication.
Consider a Fastapi route that creates a session record in Cockroachdb based on a client-supplied session_id parameter:
import uuid
from fastapi import Depends, FastAPI, Request, Response
from pydantic import BaseModel
import cockroach_driver as crdb
app = FastAPI()
# Cockroachdb connection (example using cockroachdb driver)
def get_db():
conn = crdb.connect(
host="localhost",
port 26257,
database="sessiondb",
user="root"
)
return conn
class SessionCreate(BaseModel):
session_id: str
@app.post("/login")
async def login(request: Request, response: Response, data: SessionCreate, db=Depends(get_db)):
user_id = "user-123"
# Vulnerable: using attacker-controlled session_id without regeneration
db.execute(
"INSERT INTO sessions (session_id, user_id) VALUES (%s, %s)",
(data.session_id, user_id)
)
response.set_cookie("session_id", data.session_id)
return {"status": "logged_in"}
If the client can supply session_id, an attacker can craft a link with a known token, trick the victim into visiting it after authentication, and then use that token to hijack the session. Cockroachdb does not inherently protect against this; it stores whatever identifier Fastapi provides. The vulnerability is not in Cockroachdb itself but in how Fastapi handles and persists session identifiers without enforcing server-side regeneration.
Additionally, if Fastapi reads an existing session ID from a cookie and uses it directly to query Cockroachdb without checking for freshness or binding to the authenticated user, an attacker can fixate a session and later exploit it. This becomes particularly dangerous when combined with predictable session identifiers or missing transport security, as Cockroachdb will faithfully persist the attacker-chosen value.
To detect such issues, middleBrick scans the unauthenticated attack surface of Fastapi endpoints and maps findings to frameworks such as OWASP API Top 10. In a scan of an endpoint that accepts a session identifier in a header or cookie, middleBrick may flag the absence of session regeneration and highlight the risk in the context of the API’s authentication checks.
Cockroachdb-Specific Remediation in Fastapi — concrete code fixes
Remediation focuses on ensuring that session identifiers are generated server-side after successful authentication and never trusted from the client. When using Cockroachdb as the session store, Fastapi should create a new, cryptographically random session ID upon login and store it alongside the user identifier.
Below is a secure pattern using Cockroachdb with parameterized queries and server-generated session IDs:
import secrets
from fastapi import Depends, FastAPI, Request, Response, HTTPException
import cockroach_driver as crdb
app = FastAPI()
def get_db():
conn = crdb.connect(
host="localhost",
port=26257,
database="sessiondb",
user="root"
)
return conn
@app.post("/login")
async def login(request: Request, response: Response, db=Depends(get_db)):
# Authenticate user (example placeholder)
user = authenticate_user(request) # implement your own auth logic
if not user:
raise HTTPException(status_code=401, detail="Invalid credentials")
# Generate a new, unpredictable session ID
new_session_id = secrets.token_urlsafe(32)
# Store the new session in Cockroachdb, keyed to the user
db.execute(
"INSERT INTO sessions (session_id, user_id) VALUES (%s, %s)",
(new_session_id, user.id)
)
# Set secure cookie attributes
response.set_cookie(
key="session_id",
value=new_session_id,
httponly=True,
secure=True,
samesite="lax"
)
return {"status": "logged_in"}
@app.get("/profile")
async def profile(response: Response, request: Request, db=Depends(get_db)):
session_id = request.cookies.get("session_id")
if not session_id:
raise HTTPException(status_code=401, detail="Missing session")
# Query Cockroachdb using a parameterized query
cursor = db.execute(
"SELECT user_id FROM sessions WHERE session_id = %s",
(session_id,)
)
row = cursor.fetchone()
if row is None:
raise HTTPException(status_code=401, detail="Invalid session")
return {"user_id": row[0]}
Key points:
- Use
secrets.token_urlsafeto generate session IDs, avoiding client-controlled values. - Always use parameterized queries with Cockroachdb to prevent injection and ensure safe handling of session identifiers.
- Set secure cookie flags (
httponly,secure,samesite) to limit exposure in transit and to JavaScript. - Regenerate the session ID after privilege changes (e.g., after login) to prevent fixation.
middleBrick’s CLI can be used to verify that endpoints do not accept session identifiers from the client. By running middlebrick scan <url>, you can obtain a security risk score and findings that highlight missing session regeneration and cookie configuration issues. For teams requiring deeper integration, the GitHub Action can enforce that new API deployments do not introduce session fixation risks, while the MCP Server allows AI coding assistants to flag vulnerable patterns during development.