Description
A cookie containing sensitive information, such as a session ID or login state, may be sent over unencrypted HTTP if the Secure flag is missing. An attacker able to intercept network traffic, for example on public Wi-Fi, may steal the value and use the session cookie to impersonate the user.
Potential impact
- A session cookie issued over HTTPS may later be sent over HTTP and intercepted, enabling session hijacking.
- A stolen session ID may let an attacker act as the user to view account data, change settings or make payments.
- Additional sensitive values in the cookie, such as permission information or user identifiers, may also be exposed.
Remediation
- Set
Secure: trueon all session and authentication cookies. - Use HTTPS throughout the service. Redirecting HTTP to HTTPS cannot protect a cookie already sent in the HTTP request.
- Also set
HttpOnly: trueto reduce cookie-value theft through JavaScript. It does not prevent XSS itself. - Where possible, use
Secureby default for nonsensitive cookies too. - Maintain the required security attributes in shared cookie creation and deletion helpers. To delete a cookie, match its original name,
DomainandPath.
Examples
Before
go
package main
import (
"net/http"
)
// Before: missing Secure flag
func setSessionCookie(w http.ResponseWriter, sessionID string) {
// Login session cookie without Secure or HttpOnly
cookie := http.Cookie{
Name: "SESSIONID",
Value: sessionID,
Path: "/",
// Secure defaults to false
// HttpOnly defaults to false
}
// This cookie may also be sent in HTTP requests
http.SetCookie(w, &cookie)
}
After
go
package main
import (
"net/http"
"time"
)
// After: explicitly set Secure and HttpOnly
func setSessionCookie(w http.ResponseWriter, sessionID string) {
cookie := http.Cookie{
Name: "SESSIONID",
Value: sessionID,
Path: "/",
Secure: true, // Send only over HTTPS
HttpOnly: true, // Not readable by JavaScript
SameSite: http.SameSiteLaxMode,
Expires: time.Now().Add(30 * time.Minute),
}
http.SetCookie(w, &cookie)
}
// Retain Secure/HttpOnly when deleting the cookie
func deleteSessionCookie(w http.ResponseWriter) {
cookie := http.Cookie{
Name: "SESSIONID",
Value: "",
Path: "/",
Secure: true,
HttpOnly: true,
Expires: time.Unix(0, 0),
MaxAge: -1,
}
http.SetCookie(w, &cookie)
}
Explanation:
- Before:
setSessionCookiecreates the sensitiveSESSIONIDcookie withoutSecure: true, so a browser may send it over HTTP where a network attacker can intercept it. WithoutHttpOnly, an XSS vulnerability may also let JavaScript read the value. - After:
Secure: truelimits transmission to HTTPS, andHttpOnly: trueprevents browser JavaScript from reading the cookie value. The deletion example uses the same name andPath, and both examples omitDomain. That matching identity is needed to remove the original cookie;SecureandHttpOnlyare separate protection attributes.