Session Fixation in Adonisjs with Cockroachdb
Session Fixation in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
Session fixation occurs when an application allows an attacker to force a user to use a known session identifier. In Adonisjs applications using Cockroachdb as the session store, the risk arises from how session identifiers are assigned and persisted across authentication boundaries. When session data is stored in Cockroachdb, the session record is typically keyed by a deterministic or weakly random session ID. If Adonisjs does not rotate the session identifier after authentication, an attacker who knows or sets a session ID can hijack it after the victim logs in.
With Cockroachdb, the distributed SQL layer ensures strong consistency for session reads and writes, but this does not inherently prevent fixation. The vulnerability is not in Cockroachdb itself, but in how the application uses the session store. For example, if the session ID is generated once and reused across login events, an attacker who sets a cookie like __session=attacker_chosen_value can later retrieve the authenticated session data from Cockroachdb after the victim authenticates. This is especially relevant when session cookies are transmitted over non-HTTPS channels or when the application does not enforce secure cookie attributes.
Adonisjs applications that rely on the default session provider without additional hardening may inadvertently expose session identifiers in logs, URLs (if using query params), or browser history. Cockroachdb’s role here is purely as a durable store; the risk is introduced by insecure session lifecycle management. For instance, failing to invalidate the pre-authentication session upon login leaves the old identifier active and exploitable. Similarly, if session writes are not properly synchronized or if the application uses a misconfigured TTL, stale session records may persist and be reused.
To illustrate, consider an Adonisjs route that sets a session before login:
import { session } from '@ioc:Adonis/Addons/Session'
export async function setSessionBeforeLogin({ session }) {
session.put('pre_auth', true)
session.commit()
}
If the same session ID is used after login without regeneration, the pre_auth flag remains tied to the attacker’s identifier. Cockroachdb will retain this state, and the attacker can later access authenticated endpoints using the same cookie. This pattern is detectable through security scans that correlate session behavior with authentication flows, such as those run by middleware auditing tools or API security scanners like middleBrick, which can flag missing session rotation and insecure session storage practices.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on ensuring session identifier rotation and strict isolation between unauthenticated and authenticated sessions. In Adonisjs, configure the session to use Cockroachdb with safeguards that force regeneration on privilege change. Below is a secure setup using the @adonisjs/session provider with a Cockroachdb-backed Lucid connection.
First, ensure your database client is configured for Cockroachdb with TLS and proper isolation levels to avoid race conditions during session updates:
// config/database.ts
import { DbConnectionSources } from '@ioc:Adonis/Lucid/Database'
const databaseConfig: DbConnectionSources = {
cockroachdb: {
connectionString: process.env.COCKRACKERDB_URL,
ssl: {
rejectUnauthorized: true,
},
driver: 'pg',
pool: {
afterCreate: (conn, clientFromPool) => {
clientFromPool.query('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE')
},
},
},
}
export default databaseConfig
Next, define a session store that uses this Cockroachdb connection and enforce regeneration during authentication:
// config/session.ts
import { sessionConfig } from '@ioc:Adonis/Addons/Session'
const sessionConfig: sessionConfig = {
driver: 'database',
database: {
connection: 'cockroachdb',
table: 'sessions',
key: 'sid',
},
cookie: {
name: '__session',
httpOnly: true,
secure: true,
sameSite: 'strict',
path: '/',
domain: process.env.COOKIE_DOMAIN,
},
enabled: true,
rolling: true,
}
export default sessionConfig
In your authentication controller, explicitly regenerate the session after successful login to break any pre-authentication identifier:
import { session } from '@ioc:Adonis/Addons/Session'
import { BaseAuthController } from '@ioc:Adonis/Addons/Auth'
export default class SessionsController extends BaseAuthController {
public async login({ request, session, auth }) {
const { email, password } = request.only(['email', 'password'])
const user = await auth.attempt(email, password)
// Critical: rotate session to prevent fixation
await session.regenerate()
session.put('userId', user.id)
session.put('authenticated', true)
await session.commit()
return { success: true, user: user.serialize() }
}
}
Additionally, implement middleware that invalidates legacy sessions when privilege levels change, such as during role escalation or logout. For logout, delete the Cockroachdb session record explicitly:
import { session } from '@ioc:Adonis/Addons/Session'
export async function logout({ session }) {
await session.destroy()
return { success: true }
}
These steps ensure that even if an attacker sets a session ID, it becomes inert after authentication. middleBrick can help validate these controls by scanning your API endpoints and checking for missing session rotation and insecure storage patterns, producing findings aligned with frameworks like OWASP API Top 10 and PCI-DSS.