Skip to main content

Overview

This vulnerability occurs when an application sets a sensitive cookie (especially session identifiers or authentication tokens) without enabling the HttpOnly attribute. The HttpOnly flag instructs the browser not to allow client-side scripts (like JavaScript) to access the cookie via document.cookie. If this flag is missing, and an attacker successfully executes a Cross-Site Scripting (XSS) payload on the site, they can easily steal the sensitive cookie, leading to session hijacking. 🍪🚫📜➡️👤

Business Impact

Missing the HttpOnly flag on sensitive cookies significantly increases the impact of XSS vulnerabilities:
  • Session Hijacking: An XSS attack can steal the session cookie, allowing the attacker to completely impersonate the user without needing their password.
  • Token Theft: Other sensitive tokens stored in cookies (e.g., anti-CSRF tokens, API access tokens if stored this way) can be stolen and potentially misused.
Setting HttpOnly is a crucial defense-in-depth measure against the consequences of XSS.

Reference Details

CWE ID: CWE-1004 OWASP Top 10 (2021): A05:2021 - Security Misconfiguration Severity: Medium (Increases the impact of XSS)

Framework-Specific Analysis and Remediation

This is a configuration issue related to how cookies are set. Most modern web frameworks either enable HttpOnly by default for their session cookies or provide a clear configuration option to do so. The vulnerability typically arises when:
  1. The framework default is insecure and not overridden.
  2. Developers manually set sensitive cookies without including the HttpOnly flag.
Remediation:
  1. Configure Framework Defaults: Ensure the framework’s session cookie configuration explicitly sets HttpOnly to true.
  2. Set Flag on Custom Cookies: When creating any cookie that contains sensitive data or is used for session management/authentication, always include the HttpOnly attribute. Cookies needed purely for client-side JavaScript manipulation should not contain sensitive data.

  • Python
  • Java
  • .NET(C#)
  • PHP
  • Node.js
  • Ruby

Framework Context

Controlled by SESSION_COOKIE_HTTPONLY and CSRF_COOKIE_HTTPONLY (though CSRF is often read by JS) in Django settings.py. Flask requires manual setting.
# settings.py (Production)
# DANGEROUS: Session cookie accessible via document.cookie in JavaScript.
# If an XSS vulnerability exists, the session ID can be stolen easily.
SESSION_COOKIE_HTTPONLY = False
# app.py (Flask)
from flask import make_response

@app.route('/set-session-like-cookie')
def set_session_like_cookie():
    session_data = generate_sensitive_session_data() # Assume function exists
    response = make_response("Session Set")
    # DANGEROUS: httponly flag is missing (defaults to False).
    # Accessible via document.cookie.
    response.set_cookie('custom_session', session_data, secure=True, samesite='Strict')
    return response

Mitigation and Best Practices

  • Django: Ensure SESSION_COOKIE_HTTPONLY = True (this is the default and should generally not be changed). Consider CSRF_COOKIE_HTTPONLY = False (default) if your frontend JavaScript needs to read the CSRF token from the cookie, but ensure your session cookie is HttpOnly.
  • Flask: Always add httponly=True when calling response.set_cookie for any sensitive cookie. Configure session extensions to use HttpOnly.

Secure Code Example

# settings.py (Django Production - Secure Default)
# SECURE: HttpOnly is True by default for session cookies.
# SESSION_COOKIE_HTTPONLY = True # Explicitly setting is fine too.

# CSRF token often needs to be readable by JS for AJAX
CSRF_COOKIE_HTTPONLY = False # Default and often necessary
# app.py (Flask - Secure Custom Cookie)
from flask import make_response, request

@app.route('/set-session-like-cookie-secure')
def set_session_like_cookie_secure():
    session_data = generate_sensitive_session_data()
    response = make_response("Session Set Securely")
    is_https = request.is_secure or request.headers.get('X-Forwarded-Proto', 'http') == 'https'
    # SECURE: Added httponly=True.
    response.set_cookie('custom_session', session_data,
                       secure=is_https,
                       httponly=True, # Prevent JS access
                       samesite='Strict')
    return response

Testing Strategy

Access your site over HTTPS and log in. Use browser developer tools (Application/Storage tab) to inspect the session cookie (sessionid in Django, connect.sid often in Flask/Node) and any custom authentication cookies. Verify that the “HttpOnly” column/flag is checked/true. Try accessing document.cookie in the browser’s JavaScript console; sensitive cookies should not appear in the list.