WSTG - Latest

Testing for Cookies Attributes

ID
WSTG-SESS-02

Summary

Web Cookies (herein referred to as cookies) are often a key attack vector for malicious users (typically targeting other users) and the application should always take due diligence to protect cookies.

HTTP is a stateless protocol, meaning that it doesn’t hold any reference to requests being sent by the same user. In order to fix this issue, sessions were created and appended to HTTP requests. Browsers, as discussed in testing browser storage, contain a multitude of storage mechanisms. In that section of the guide, each is discussed thoroughly.

The most used session storage mechanism in browsers is cookie storage. Cookies can be set by the server, by including a Set-Cookie header in the HTTP response or via JavaScript. Cookies can be used for a multitude of reasons, such as:

  • session management
  • personalization
  • tracking

In order to secure cookie data, the industry has developed means to help lock down these cookies and limit their attack surface. Over time cookies have become a preferred storage mechanism for web applications, as they allow great flexibility in use and protection.

The means to protect the cookies are:

Test Objectives

  • Ensure that the proper security configuration is set for cookies.

How to Test

Below, a description of every attribute and prefix will be discussed. The tester should validate that they are being used properly by the application. Cookies can be reviewed by using an intercepting proxy, or by reviewing the browser’s cookie jar.

Secure Attribute

The Secure attribute tells the browser to only send the cookie if the request is being sent over a secure channel such as HTTPS. This will help protect the cookie from being passed in unencrypted requests. If the application can be accessed over both HTTP and HTTPS, an attacker could be able to redirect the user to send their cookie as part of non-protected requests.

HttpOnly Attribute

The HttpOnly attribute is used to help prevent attacks such as session leakage, since it does not allow the cookie to be accessed via a client-side script such as JavaScript.

This doesn’t limit the whole attack surface of XSS attacks, as an attacker could still send request in place of the user, but limits immensely the reach of XSS attack vectors.

Domain Attribute

The Domain attribute is used to compare the cookie’s domain against the domain of the server for which the HTTP request is being made. If the domain matches or if it is a subdomain, then the path attribute will be checked next.

Note that only hosts that belong to the specified domain can set a cookie for that domain. Additionally, the domain attribute cannot be a top level domain (such as .gov or .com) to prevent servers from setting arbitrary cookies for another domain (such as setting a cookie for owasp.org). If the domain attribute is not set, then the hostname of the server that generated the cookie is used as the default value of the domain.

For example, if a cookie is set by an application at app.mydomain.com with no domain attribute set, then the cookie would be resubmitted for all subsequent requests for app.mydomain.com, but not its subdomains (such as hacker.app.mydomain.com), or to otherapp.mydomain.com. (However, older versions of Edge/IE behave differently, and do send these cookies to subdomains.) If a developer wanted to loosen this restriction, then they could set the domain attribute to mydomain.com. In this case the cookie would be sent to all requests for app.mydomain.com and mydomain.com subdomains, such as hacker.app.mydomain.com, and even bank.mydomain.com. If there was a vulnerable server on a subdomain (for example, otherapp.mydomain.com) and the domain attribute has been set too loosely (for example, mydomain.com), then the vulnerable server could be used to harvest cookies (such as session tokens) across the full scope of mydomain.com.

Path Attribute

The Path attribute plays a major role in setting the scope of the cookies in conjunction with the domain. In addition to the domain, the URL path that the cookie is valid for can be specified. If the domain and path match, then the cookie will be sent in the request. Just as with the domain attribute, if the path attribute is set too loosely, then it could leave the application vulnerable to attacks by other applications on the same server. For example, if the path attribute was set to the web server root /, then the application cookies will be sent to every application within the same domain (if multiple application reside under the same server). A couple of examples for multiple applications under the same server:

  • path=/bank
  • path=/private
  • path=/docs
  • path=/docs/admin

Expires Attribute

The Expires attribute is used to:

  • set persistent cookies
  • limit lifespan if a session lives for too long
  • remove a cookie forcefully by setting it to a past date

Unlike session cookies, persistent cookies will be used by the browser until the cookie expires. Once the expiration date has exceeded the time set, the browser will delete the cookie.

SameSite Attribute

The SameSite attribute can be used to assert whether a cookie should be sent along with cross-site requests. This feature allows the server to mitigate the risk of cross-origin information leakage. In some cases, it is used too as a risk reduction (or defense in depth mechanism) strategy to prevent cross-site request forgery attacks. This attribute can be configured in three different modes:

  • Strict
  • Lax
  • None
Strict Value

The Strict value is the most restrictive usage of SameSite, allowing the browser to send the cookie only to first-party context without top-level navigation. In other words, the data associated with the cookie will only be sent on requests matching the current site shown on the browser URL bar. The cookie will not be sent on requests generated by third-party sites. This value is especially recommended for actions performed at the same domain. However, it can have some limitations with some session management systems negatively affecting the user navigation experience. Since the browser would not send the cookie on any requests generated from a third-party domain or email, the user would be required to sign in again even if they already have an authenticated session.

Lax Value

The Lax value is less restrictive than Strict. The cookie will be sent if the URL equals the cookie’s domain (first-party) even if the link is coming from a third-party domain. This value is considered by most browsers the default behavior since it provides a better user experience than the Strict value. It doesn’t trigger for assets, such as images, where cookies might not be needed to access them.

None Value

The None value specifies that the browser will send the cookie in all contexts, including cross-site requests (the normal behavior before the implementation of SameSite). If Samesite=None is set, then the Secure attribute must be set, otherwise modern browsers will ignore the SameSite attribute, e.g. SameSite=None; Secure.

By design cookies do not have the capabilities to guarantee the integrity and confidentiality of the information stored in them. Those limitations make it impossible for a server to have confidence about how a given cookie’s attributes were set at creation. In order to give the servers such features in a backwards-compatible way, the industry has introduced the concept of Cookie Name Prefixes to facilitate passing such details embedded as part of the cookie name.

Host Prefix

The __Host- prefix expects cookies to fulfill the following conditions:

  1. The cookie must be set with the Secure attribute.
  2. The cookie must be set from a URI considered secure by the user agent.
  3. Sent only to the host who set the cookie and MUST NOT include any Domain attribute.
  4. The cookie must be set with the Path attribute with a value of / so it would be sent with every request to the host.

For this reason, the cookie Set-Cookie: __Host-SID=12345; Secure; Path=/ would be accepted while any of the following ones would always be rejected: Set-Cookie: __Host-SID=12345 Set-Cookie: __Host-SID=12345; Secure Set-Cookie: __Host-SID=12345; Domain=site.example Set-Cookie: __Host-SID=12345; Domain=site.example; Path=/ Set-Cookie: __Host-SID=12345; Secure; Domain=site.example; Path=/

Secure Prefix

The __Secure- prefix is less restrictive and can be introduced by adding the case-sensitive string __Secure- to the cookie name. Any cookie that matches the prefix __Secure- would be expected to fulfill the following conditions:

  1. The cookie must be set with the Secure attribute.
  2. The cookie must be set from a URI considered secure by the user agent.

Strong Practices

Based on the application needs, and how the cookie should function, the attributes and prefixes must be applied. The more the cookie is locked down, the better.

Putting all this together, we can define the most secure cookie attribute configuration as: Set-Cookie: __Host-SID=<session token>; path=/; Secure; HttpOnly; SameSite=Strict.

Tools

Intercepting Proxy

Browser Plug-in

References