Session Management has always been one of the OWASP Top 10. Take a look of the most recent two OWASP Top 10s.
- Top 10, 2013: A2 – Broken Authentication and Session Management
- Top 10, 2017: A2 – Broken Authentication
Under the description of A2 of Top 10, 2017, it says,
“Application functions related to authentication and session management are often implemented incorrectly, allowing attackers to compromise passwords, keys, or session tokens, or to exploit other implementation flaws to assume other users’ identities temporarily or permanently.”
Even though “session management” is no longer part of the A2 title, the content of session management remains a critical part of the A2 security risk.
HTTP and Session Management
HTTP is designed as a stateless protocol, which means web servers do not maintain any information about the previous request. It has no memory of whether a user has just logged in the application. Modern web applications require maintaining the state of authentication and authorization during the user access of the application. This is accomplished by the session management capabilities that track the state of login and possibly other data, i.e., login name.
HTTP vs. HTTPS
The HTTP protocol is not secure. If a web application implements the login function using the HTTP protocol, the login credentials will be passed as plaintext in the wire. Clearly, we should not use HTTP to perform the login function. This is why Google asked everyone to switch from HTTP to HTTPS.
Transmitting data using the HTTPS protocol solves many vulnerability issues but not all of them. If an HTTPS page embeds HTTP links, various security issues can happen. Here is Google’s advice: “Embed only HTTPS content on HTTPS pages.”
Are you safe now, if you adopt HTTPS throughout the application? The answer is no. We will revisit this issue in our first test case.
Word of Caution
- As discussed above, do not use HTTP anywhere on your website, unless the site contains only public information without any form of authentication. If the application has both public and sensitive information, the better choice is to split the application into two. One for public information, and the other for sensitive information.
- Do not invent your own session management capabilities. Always use popular and well-known web development frameworks. I have seen a couple of brilliant, senior developers try to implement their own session management capabilities and fail miserably.
- Session validation should occur at the server. If a web page needs to validate whether a critical action is submitted from the authorized user, the validation must be performed at the server-side. Sorry for those who love the Single Page Applications (SPAs). Session validation at the client site improves the UI experience but not the security risk.
Two Recent Reports
Here are two interesting reports that illustrate the lack of understanding of session management.
On December 7, 2019, Ricardo Iramar reported his venture into the bug bounty program. He reported five cases at that time. All those five cases were for companies delegating their subdomains to contractors for their services. In order to achieve single-sign-on (SSO), they passed the authenticated cookies around. This is a major misuse of session IDs. OWASP recommends using OAuth, OpenId, SAML, or FIDO in this case, instead of passing cookies around.
Un-validated Session Id
On April 21, 2020, Ribeiro reported multiple critical vulnerabilities in IBM Data Risk Manager. One of the critical vulnerabilities is related to missing session-id validation (Test Case 5 below). The author of the report used the word “SOMETHING” as the session ID, and it passed the authentication. IBM refused to accept the report initially and later claimed the refusal of the report was a processing error.
Vulnerability Severity Level
Before discussing security vulnerabilities, let’s define a simple measurement of the severity level of vulnerabilities: high, medium, and low. Security vulnerabilities that are categorized as high severity should be resolved as soon as possible. Medium severity issues should be resolved in a short period of time, for example, 30 days. Low severity issues can have more time to resolve.
The following 10 test cases or test categories assume the application is using a well-known or popular development framework. If it is not the case, additional test cases, manual code review, and security scans will be required.
1. Cookie Attributes – Severity: Low
Setting the Secure flag to true will prevent the session ID from passing to the HTTP URLs. The problem with this flag is the protection only protects the cookie from HTTP links. In the case of HTTPS links, cookies will still be passed to the other sites. That is what the new attribute SameSite comes in.
The RFC6265 defines the meaning of the site as the combination of domain suffix and the part of the domain just before it. For example, the site of www.example.com is example.com. Hence, your-project.example.com and my-project.example.com originated from the same site. This is only a general statement. Determining whether two URL strings refer to the same site is quite complicated. Fortunately, there are multiple open source projects that provide answers to this question.
Three values can be used for the SameSite attribute.
Cookies can be passed among all pages of the same site.
Sometimes cookies need to be passed to other domains. For example, the application wants to pass cookies to Facebook by following a hyperlink. This behavior is generally for navigation to external sites.
Cookies will always be sent to HTTPS hyperlinks for any website.
After setting Secure, HttpOnly, and SameSite=Strict, your cookies are protected, right? It is not the case. A man-in-the-middle can intercept and change the cookie. This is frustrating, right? Here comes another set of cookie attributes (cookie prefixes).
Set-Cookie: __Secure-ID=123; Secure; Domain=example.comhe __Secure- prefix makes a cookie accessible from HTTPS sites only. An HTTP site cannot read or update a cookie if the cookie name starts with __Secure-. Only HTTPS sites can read the cookie, but requests from the subdomain can change the cookies.
Set-Cookie: __Host-ID=123; Secure; Path=/
The __Host- prefix does the same as the __Secure- prefix and more. A __Host- a prefixed cookie is only accessible and updatable by the same domain it originated from. This means that an HTTPS subdomain can no longer overwrite the cookie value.
There is one more HTTP header that we need to discuss: HTTP Strict Transport Security (HSTS). This is not a cookie attribute. However, discussing cookie vulnerabilities without discussing HSTS is an incomplete discussion.
The HSTS setting can prevent users from connecting over unencrypted connections. Without this setting, an attacker may be able to rewrite HTTPS links as HTTP links. But isn’t this already protected by the above cookie attributes? Please be aware of one of the security practices: Defense in Depth. The more layers of obstacles to deter attacks, the better the security of the application can be. The recommended setting for HSTS is:
Strict-Transport-Security: max-age=15768000; includeSubDomains
The optional “
preload” flag indicates the site consents to have their domain preloaded. Be aware that inclusion in the preload list cannot easily be undone.
2. Session Fixation – Severity: High
If a web application does not assign a new session ID after a user successfully signs in, the application has the session fixation vulnerability. An attacker can obtain a valid session ID, inducing a user to use the session ID to login, and then hijacking the validated session.
To avoid the session fixation attack, session IDs must be changed after login and logout. The way to remediate the vulnerability is to use either 301 or 302 as part of the login action. The logout action does not need to use 301 or 302, but it must invalidate the session ID. I do not see a major advantage of either 301 or 302, but 302 seems to be better if caching for the login page is disabled.
Remember that the login action changes the state of the HTTP connection; Hence, the POST method should be used. We will explain this in the next test.
3. Session Id Exposure – Severity: High, if the session ID can be used to login. Medium or Low, if the session ID cannot be used to login
Before discussing session ID in URL, we need to clarify the difference between the HTTP GET and POST methods. If you google the difference between the two from a Java programming perspective, you may get the following answer.
“Both GET and POST method is used to transfer data from client to server in HTTP protocol, but the main difference between POST and GET method is that GET carries request parameter appended in URL string while POST carries request parameter in message body which makes it more secure way of transferring data from client to server in HTTP protocol.”
This isn’t a wrong answer, and it does mention the POST method is more secure. However, it misses the key concept: The GET method is used for viewing something, without changing it, while POST is used for changing something. Which method is the better choice for authentication, which changes the state of the session?
Browser vendors certainly do not expect using the GET method for authentication and hence various security vulnerabilities exist. Because the GET method appends parameters to the URL string, log files and bookmarks save the parameters. More importantly, if the session ID appears in the URL string, all third party scripts loaded from external sites will receive the session ID in the Referer header. In addition, all external links clicked from that page will cause the session ID to be sent to the external sites too.
In some cases, the session ID is passed by form submission, and developers may not be aware that the session ID is leaked. This is because the session ID appears on the address bar and disappears in a split second.
One scenario I have seen is the login form submission coming from a popular and old development framework.
<form id="login" ... action=".../login.action;jsessionid=..." />
Here the jssessionid is created by the development framework, but it should be removed.
For form submission, one remediation is to include the following settings in the web.xml file.
For Tomcat, the solution may be setting disableURLRewriting=”true” in the context.xml file.
The solutions provided above do not cover all possible cases. Stay tuned for Part 2 where we will dig into further possible cases!