logo

Database

Insecurely generated cookies - HttpOnly

Need

Protection of session cookies from access by client-side scripts

Context

• Usage of Kotlin 1.9+ on the JVM for building web applications

• Usage of the javax.servlet API for cookies

Description

1. Non compliant code

import javax.servlet.http.Cookie
import javax.servlet.http.HttpServletResponse

fun addSessionCookie(response: HttpServletResponse, sessionId: String) {
    // Without HttpOnly, any script on the page can read the session id
    val cookie = Cookie("SESSIONID", sessionId).apply {
        secure = true
        path = "/"...

The `addSessionCookie` function below creates the cookie that carries the session identifier and marks it `Secure`, but it never calls `isHttpOnly = true`, so the cookie is sent without the `HttpOnly` attribute. Without `HttpOnly`, the browser exposes the cookie to JavaScript through `document.cookie`. Any cross-site scripting flaw in the application, or a compromised third-party script such as an analytics or advertising library, can read the session identifier and send it to an attacker, who then uses it from their own browser to take over the session.

2. Steps

• Set `isHttpOnly = true` on every `Cookie` that carries a session, authentication or CSRF token before calling `addCookie`.

• Configure container-managed session cookies as `HttpOnly`, for example with `server.servlet.session.cookie.http-only=true`.

• Build sensitive cookies in a single helper function so the attributes cannot be forgotten in individual handlers.

• Combine `HttpOnly` with the `Secure` and `SameSite` attributes and with a restrictive Content-Security-Policy.

3. Secure code example

import javax.servlet.http.Cookie
import javax.servlet.http.HttpServletResponse

fun addSessionCookie(response: HttpServletResponse, sessionId: String) {
    val cookie = Cookie("SESSIONID", sessionId).apply {
        isHttpOnly = true
        secure = true
        path = "/"...

The corrected function sets `isHttpOnly = true` on the cookie, so the browser sends it with each request but refuses to expose it to JavaScript. Scripts injected into the page can no longer read or copy the session identifier. `HttpOnly` does not fix cross-site scripting, since an injected script can still act on behalf of the user while the page is open, but it prevents the theft that would let an attacker keep using the session from elsewhere. The cookie remains `Secure`, so it is only sent over HTTPS. For container-managed sessions, the same attributes are configured once, for example with `server.servlet.session.cookie.http-only=true` in Spring Boot.