Skip to main content

Insecure session management

Need

Secure session management

Context

  • Usage of TypeScript for statically typed JavaScript development
  • Usage of Express for building web applications and APIs

Description

Non compliant code

import express from 'express';

const app = express();

let sessionToken: string | null = null;

app.post('/login', (req, res) => {
// Authenticate user and generate session token
sessionToken = 'valid_token';
res.send('Logged in successfully');
});

app.post('/logout', (req, res) => {
// Clear session token without expiring it
sessionToken = null;
res.send('Logged out successfully');
});

app.get('/data', (req, res) => {
if (sessionToken) {
// Access data with valid session token
res.send('Confidential data');
} else {
res.send('Unauthorized');
}
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The vulnerability in this code is an insecure session management issue.

In the /login route, when a user successfully logs in, a session token is generated and stored in the sessionToken variable. However, there is no mechanism to expire or invalidate this token when the user logs out.

In the /logout route, the session token is simply cleared by setting it to null. This means that even after the user logs out, the session token remains valid and can still be used to access protected resources.

In the /data route, the code checks if the sessionToken variable is not null before allowing access to confidential data. Since the session token is not expired or invalidated upon logout, an attacker can still use the valid session token to access the protected data even after the user has logged out.

The impact of this vulnerability is that an attacker can gain unauthorized access to a previously authenticated user's session and obtain confidential information or perform actions on behalf of the user.

To fix this vulnerability, the session token should be properly expired or invalidated upon logout to ensure that it cannot be used again to access protected resources.

Steps

  • Implement session expiration logic
  • Store session token in a secure and encrypted manner
  • Use a secure session management library or framework
  • Invalidate session token on logout

Compliant code

import express from 'express';
import session from 'express-session';

const app = express();

app.use(session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: true,
cookie: { secure: true, maxAge: 3600000 } // Set session expiration time to 1 hour
}));

app.post('/login', (req, res) => {
// Authenticate user and generate session token
req.session.token = 'valid_token';
res.send('Logged in successfully');
});

app.post('/logout', (req, res) => {
// Clear session token and expire the session
req.session.destroy();
res.send('Logged out successfully');
});

app.get('/data', (req, res) => {
if (req.session.token) {
// Access data with valid session token
res.send('Confidential data');
} else {
res.send('Unauthorized');
}
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});

The fixed code addresses the vulnerability of insecure session management by implementing proper session token expiration after the user logs out.

  1. The code imports the necessary modules, including Express and Express-session, to handle the server and session management.

  2. The Express-session middleware is configured with the necessary options:

    • The "secret" option is set to a secure secret key to sign the session ID cookie.
    • The "resave" option is set to false to prevent session data from being saved on every request.
    • The "saveUninitialized" option is set to true to save new, uninitialized sessions.
    • The "cookie" option is set with the "secure" flag to ensure the session cookie is only sent over HTTPS. Additionally, the "maxAge" option is set to 3600000 milliseconds (1 hour) to define the expiration time for the session token.
  3. The "/login" route is defined to handle the user login process. Once the user is authenticated, a valid session token is generated and stored in the "req.session.token" property.

  4. The "/logout" route is defined to handle the user logout process. It destroys the session by calling "req.session.destroy()", which clears the session token and any associated session data.

  5. The "/data" route is defined to handle requests for confidential data. It checks if a valid session token exists in "req.session.token". If the token is present, the server responds with the confidential data. Otherwise, it responds with an "Unauthorized" message.

  6. Finally, the server listens on port 3000, and a message is logged to indicate that the server is running.

By properly destroying the session and clearing the session token upon logout, the fixed code ensures that the session token becomes invalid and cannot be used to access confidential information after the user logs out.

References