Skip to main content

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.

References