Insecure session management
Need
Secure session management
Context
- Usage of Dart 2.0 for building high-performance, cross-platform applications
- Usage of Shelf for managing and organizing data in Node.js applications
- Usage of shelf_session for managing session data in a Shelf application
Description
Non compliant code
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf_session/shelf_session.dart';
// Create session middleware
var sessionMiddleware = sessionMiddlewareMemory();
var handler = const shelf.Pipeline()
.addMiddleware(sessionMiddleware)
.addHandler(_handleRequest);
shelf.Response _handleRequest(shelf.Request request) {
var session = request.context['session'] as Session;
var token = session['token'];
// No expiration is set on the session token
return shelf.Response.ok('Hello, ${token}!');
}
void main() {
shelf.serve(handler, 'localhost', 8080);
}
The above Dart code uses the shelf
and shelf_session
packages to create a simple server with session management. The server listens on localhost
port 8080
and responds to each request with a greeting message that includes the session token.
The vulnerability lies in the _handleRequest
function, where a session token is retrieved from the request but no expiration is set on it. This means that even after a user terminates their session, the token remains valid and can be used to make subsequent requests. This is a serious security issue as it could allow an attacker to reuse old session tokens to impersonate users and perform actions on their behalf.
Steps
- Introduce a mechanism to invalidate the session token once the user logs out or after a certain period of inactivity.
- You can use the 'expire' method provided by the 'shelf_session' package to set an expiration time for the session token.
- Ensure that the server checks the validity of the session token with each request. If the token is expired, the server should reject the request.
- Implement a mechanism to refresh the session token periodically while the user is active. This can help prevent session hijacking.
Compliant code
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf_session/shelf_session.dart';
// Create session middleware
var sessionMiddleware = sessionMiddlewareMemory();
var handler = const shelf.Pipeline()
.addMiddleware(sessionMiddleware)
.addHandler(_handleRequest);
shelf.Response _handleRequest(shelf.Request request) {
var session = request.context['session'] as Session;
var token = session['token'];
// Check if the session token is expired
if (session.isExpired) {
return shelf.Response.forbidden('Session expired');
}
// Refresh the session token periodically
session.refresh();
return shelf.Response.ok('Hello, ${token}!');
}
void main() {
shelf.serve(handler, 'localhost', 8080);
}
The updated code introduces a mechanism to handle session expiration and refresh the session token periodically.
In the _handleRequest
function, we first retrieve the session from the request context. We then check if the session token is expired using the isExpired
property of the Session
object. If the session token is expired, we return a 403 Forbidden response.
Next, we refresh the session token using the refresh
method of the Session
object. This ensures that the session token is periodically updated while the user is active, which can help prevent session hijacking.
Finally, we return a response with a greeting message that includes the session token. This is just for demonstration purposes and in a real-world application, you would typically not include the session token in the response.
In the main
function, we start the server and listen for requests on localhost port 8080. The server uses the handler
function to handle incoming requests, which includes the session middleware for managing sessions.