In the previous article, we learned some basics of authentication and prevention methods of access control in web applications through authentication. In this article, let's talk about session management in access control of web applications.
Server-side session management is the standard process. The traditional way of keeping the state in a web application depends on storing information in a session object on the server. The client receives a unique identifier for each session object. When the browser includes this identifier in every request, the server can tie multiple requests together in a session. This identifier is called a Session Identifier(SID).
One way of including the SID in every request is to store it in a cookie. The alternative way is to add the identifier in every URL on every page. This method is less recommended because of its high complexity and higher risk of leaking the SID to third parties.
Let us look at the cookie session management mechanism. Image above explains the cookie session management mechanism. When the user first opens the application, there is no session. So, when the server receives the first request, it generates a new session object. A session object is assigned a SID. The server sends this SID back to the browser. From now on, every request from the browser to the server will include this identifier. The server uses this identifier to look up the correct session object and access its data. For example, when the user logs in to the application, the session object gets updated. It now contains the authenticated state, as well as the account information of the user. The information stored in the session object is crucial for making authorization decisions throughout the application.
The server sets the session cookie by sending the Set-Cookie response header. The header contains the name of the cookie and the session identifier value. The Cookie header will store the name and value of this cookie, and the browser attaches this Cookie header to outgoing requests to the same domain. There is no predefined name for a cookie containing a session identifier. Commonly used names are SESSIONID, PHPSESSIONID, JSESSIONID, etc. Below is an example of a cookie header.
Session Hijacking
The security of this session management mechanism depends on the secrecy of the SID. If an attacker obtains the user's SID, they can take control of the session. It means full access to the application in the user's name. Session hijacking is one of the most critical threats against cookie-based session management. Hijacking occurs when an attacker compromises a session token by stealing or predicting it to gain unauthorized access to the server on behalf of its owner. Session hijacking can happen in multiple ways.
The first one is the insecure generation of a new SID. If a SID is predictable in some way, an attacker can calculate past and future identifiers. This attack is known as brute-forcing the session identifier. Applications that use a custom algorithm to generate session identifiers are often vulnerable to this attack. The proper way to generate session identifiers is to use a secure random number generator. Most frameworks that offer built-in session management do this correctly.
Another one is the insecure transmission or storage of the SID. Sending the SID in clear text over the network allows interception by an eavesdropper. A successful session fixation attack gives the attacker access to the victim's account, which means access to higher-level privileges or the ability to look at sensitive data.
Another potential attack vector is cross-site scripting - stealing the cookie from JavaScript. A cross-site scripting vulnerability enables attackers to inject client-side scripts into web pages viewed by other users. When the attacker can control a piece of JavaScript running on a page of the application, he can abuse this to access the cookies. A visual representation of cross-site scripting attacks is shown below.
To prevent cross-site scripting attacks, set a flag - "HttpOnly", to the Set-Cookie header. This flag marks the cookie as valid for network requests but not script-based access. It is a good idea to set the “HttpOnly” flag on all cookies that do not need to be accessed from JavaScript. It is a best practice to set the HttpOnly flag on all cookies that do not require JavaScript access.
In general, Session cookies should always have both the “Secure” and “HttpOnly” flags enabled. This ensures that they will only be sent on HTTPS requests, and cannot be accessed from JavaScript.
Alternate session management mechanisms
The cookie-based session management is easier to handle when the application is small. But when you start deploying an application on a large scale, things become more complicated.
For example, as shown above, when an application distributes across multiple servers, the initial request is directed to a specific server in the cluster. This server then creates a session object and returns a session ID. But the second request now contains an ID that points to a session object generated by the first server. There are several strategies to tackle this problem. One way is to use sticky sessions, where all requests within a session go to the same server. Another way is sharing the session state between servers. But there is also another way - client-side session management. The client stores the session state in this new paradigm instead of the server being responsible for storage. This way, the server no longer needs to keep track of session data. It fits well within the move towards stateless API-based systems. This blog will be longer if we dive deeper into client-side session management. Let's examine how this approach affects security.
The most significant difference between the two paradigms is the locality of the session object. The server stores one while the client saves the other. The session object stored on the server is considered trusted data. There is no way for the attacker to manipulate the contents of the session object directly. However, with a session object stored on the client, the attacker can change a session object before sending it to the application. As a result, the information kept in the session object is no longer reliable and should not be relied upon. The server should check the integrity of the session object before using any of its data. Adding a server-generated signature to the session object is a common way to implement this integrity check.
The second difference is the level of control over, active sessions. With server-side sessions, it is straightforward to consult a list of active sessions or to revoke a specific session. With the client-side sessions, there is no easy way to list active sessions because these sessions are only visible when the client makes a request.
A key difference to be aware of arises from the implementation of a client-side session management mechanism. Many applications have replaced cookies with custom headers to transport session objects. While this avoids some of the security challenges with cookies, it also complicates matters for the developer. Cookies are handled automatically by the browser, while custom headers are not. So, with custom headers, the developer needs to retrieve the session object from the server, store it somewhere, and attach it to outgoing requests. The choices made to implement these operations have some ramifications for security. In general, client-side sessions have their own challenges and security trade-offs. Client-side sessions are often advocated because they push a part of the load from the server to the client. Client-side access control is useful for usability reasons but not for security reasons.
In conclusion, effective session management is a cornerstone of securing web applications and protecting user data. By implementing robust session control mechanisms, we can significantly reduce the risk of unauthorized access and data breaches.
But the journey doesn't end here. Our exploration of access control in web applications continues with our next blog, where we delve into the crucial realm of authorization. We'll uncover how to control what authenticated users can do and access your application. So, stay tuned for our upcoming blog on authorization in the access control of web applications. Your path to comprehensive web application security is just beginning!