Skip to main content

Sensitive information sent via URL parameters - Session

Need

Secure transmission of sensitive information in session tokens

Context

  • Usage of Dart for building cross-platform mobile, web, and desktop applications
  • Usage of Shelf for managing and organizing data in Node.js applications

Description

Non compliant code

import 'package:shelf/shelf.dart' as shelf;

shelf.Response handleRequest(shelf.Request request) {
var sessionToken = request.url.queryParameters['sessionToken'];

// Do something with the sessionToken

return shelf.Response.ok('Request handled');
}

In the code above, we are using the Shelf framework to handle HTTP requests in a Dart backend application.

The handleRequest function is designed to handle incoming requests. It extracts the session token (JWT) from the URL query parameters using request.url.queryParameters['sessionToken'].

The problem with this approach is that the session token is being sent via the URL. URLs are often logged by web servers and can also be stored in the user's browser history. This exposes the session token to potential attackers who gain access to these logs or the user's machine.

This is a significant security vulnerability because the session token is sensitive information that should be kept secret. If an attacker gets hold of a user's session token, they can impersonate that user and potentially perform malicious actions on their behalf.

Steps

  • Instead of sending the JWT session token via URL parameters, send it in the HTTP header. This prevents the token from being cached in the browsing history.
  • Use the 'Authorization' header field to transmit the session token. The value of this field should be 'Bearer ' followed by the JWT session token.
  • Ensure that the server is configured to accept and parse the 'Authorization' header field from incoming requests.
  • Update the client-side code to send the session token in the 'Authorization' header field instead of the URL parameters.
  • Finally, test the updated code to ensure that it works as expected and the session token is no longer exposed in the URL.

Compliant code

import 'package:shelf/shelf.dart' as shelf;

shelf.Response handleRequest(shelf.Request request) {
var authHeader = request.headers['authorization'];
if (authHeader == null || !authHeader.startsWith('Bearer ')) {
return shelf.Response.forbidden('Missing or invalid Authorization header');
}

var sessionToken = authHeader.substring(7);

// Do something with the sessionToken

return shelf.Response.ok('Request handled');
}

The updated code now retrieves the JWT session token from the 'Authorization' HTTP header field instead of the URL parameters. This is done by calling request.headers['authorization'].

The code then checks if the 'Authorization' header is null or if it does not start with 'Bearer '. If either of these conditions is true, the server responds with a 403 Forbidden status code and a message indicating that the 'Authorization' header is missing or invalid. This is done using shelf.Response.forbidden('Missing or invalid Authorization header').

If the 'Authorization' header is present and correctly formatted, the code extracts the JWT session token from it by calling authHeader.substring(7). This removes the 'Bearer ' prefix from the header value, leaving only the session token.

The session token can then be used as before, but it is now transmitted in a way that prevents it from being cached in the browsing history.

Remember to update the client-side code to send the session token in the 'Authorization' header field instead of the URL parameters. Also, ensure that the server is configured to accept and parse the 'Authorization' header field from incoming requests.

Finally, test the updated code to ensure that it works as expected and the session token is no longer exposed in the URL.

References