Back to qualys.com

Detecting Insecure Cookies with Qualys Web Application Scanning

Cookies are ubiquitous in today’s modern web applications. If an attacker can acquire a user’s session cookie by exploiting a cross-site scripting (XSS) vulnerability, by sniffing an unencrypted HTTP connection, or by some other means, then they can potentially hijack a user’s valid session. Obviously, this can have negative implications for an organization and its users, including theft of sensitive application data or unauthorized/harmful actions.

Qualys Web Application Scanning reports when it discovers a cookie delivered over an HTTPS channel without the “secure” attribute set. This detection is useful for verifying correct coding practices for individual web applications & developers, and across your entire organization. Cookies marked with the secure attribute will never be sent over an unencrypted (non-HTTPS) connection, which keeps them safe from prying eyes that may be sniffing network traffic.

Qualys WAS supports the following detections (QIDs) related to missing “secure” cookie attribute:

QID 150122

This QID is reported if a standard cookie is set via HTTPS without the “secure” attribute.

QID 150161

This QID is reported if a session cookie is set via HTTPS without the “secure” attribute. Some of the common session cookie names that are used for session management are:

JSESSIONID for Java-based web apps
ASP.NET_SessionId for Microsoft ASP.NET web apps
PHPSESSID for PHP-based web apps

QID 150120

This QID is reported if a session cookie is authentication related and is set via HTTPS without the “secure” attribute. The session cookies reported under this QID are quite different from normal session cookies as these cookies are used to validate a user’s authenticated session with a web app. In case of an authenticated state while accessing a web resource, the “PHPSESSID” cookie is used to validate the authenticated session. If the cookie is set via HTTPS without the “secure” attribute, QID 150120 will be reported for the cookie. However, in an unauthenticated state while accessing web resources, the “PHPSESSID” cookie is simply used to maintain a session across multiple requests (in this case, QID 150161 would be reported).

Non-Sensitive Cookies

It is possible that some of the cookies set by a web application are not sensitive and pose no risks if they are compromised. However, Qualys WAS may still report them as missing the “secure” attribute under one of the above QIDs.

An example of a non-sensitive cookie is a “language” cookie that holds a user’s preferred display language (English or German for example). This cookie can be safely set by a web application without the “secure” attribute, because it has no security implications. This type of finding can be easily ignored using “Ignore” option in Qualys WAS. More details about ignoring a vulnerability can be found in the WAS online help.

Background… what are cookies?

A cookie is a bit of data that a web application sends to your web browser. The browser may store it and send it back with the next HTTP request to the same web app.

Cookies are set and stored as name=value pairs.  Depending on the nature of the connection to the server, the browser may or may not send the cookies in subsequent requests to the web server. The cookies are used by the server-side web application to identify the user and determine their state and preferences. Multiple cookies can be set by a web application separated by semicolons in the HTTP response.

The primary uses of cookies are as authentication tokens, session validation, and as temporary data containers for web applications. When the web application uses a stateless protocol such as HTTP to serve its clients, it has to maintain a state across multiple requests. Cookies allow for a conversational state between the client and the web server and it can consists of multiple requests and responses between them.

How are cookies an attack vector?

Cookies are used for web application authentication and session management. If attackers are able to acquire session cookies by means such as exploiting a cross-site scripting vulnerability or sniffing an unencrypted session (i.e. HTTP), they could use the cookies to hijack a valid session of a victim user.

Cookies are also used to maintain the state across multiple requests from the same user. If an attacker is able to access the cookies and manipulate its values, this could lead to poor web application performance.

Considering the sensitive nature of cookies, they must be transferred over an encrypted channel to protect the information they contain.

How do you ensure cookies are secure?

To ensure all cookies are sent over secure channels, an attribute should be set for each cookie called “secure”.
This attribute forces browsers to send the cookie only if the request is being sent over HTTPS.

Examples

Below is a PHP code snippet and the corresponding raw HTTP request and response. This illustrates how a cookie can be set by a web application improperly with the “secure” attribute missing.

setcookie("LamCookie", "123", time()+3600, "/", "example.com", 0, 1);

Image 1 – request and response received without “secure” attribute on the “LamCookie” cookie.

The following PHP code snippet sets “secure” attribute properly. Note the 6th argument passed to setcookie() is a “1”, which sets the “secure” attribute for the “TestCookie” cookie.

setcookie("TestCookie", "DummyValue", time()+3600, "/", "example.com", 1, 1);

Image 2 – request and response received with “secure” attribute on the “TestCookie” cookie.

Setting a cookie with the secure attribute

Below are a few examples from different languages that demonstrate how to set a cookie with the secure attribute in the response:

In JSP

final Cookie cookie=new Cookie("TestCookie", "12345678");
cookie.setMaxAge(0);
cookie.setPath("/");
cookie.setSecure(true);

In ASP.Net

public HttpResponseMessage Get( )
{
   var resp = new HttpResponseMessage();
   var cookie = new CookieHeaderValue("TestCookie", "12345");
   cookie.Expires = DateTimeOffset.Now.AddDays(1);
   cookie.Domain = Request.RequestUri.Host;
   cookie.Path = "/";
   cookie.secure = true;

   resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });
   return resp;
}

Leave a Reply