Insecure session expiration time - TypeScript

Insecure session expiration time - TypeScript

Need

Enforce secure session expiration time

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();

app.use((req, res, next) => {
  req.session.lastActivity = new Date();
  next();
});

app.get('/dashboard', (req, res) => {
  if (req.session.lastActivity) {
    const currentTime = new Date();
    const timeDifference = currentTime.getTime() - req.session.lastActivity.getTime();
    const minutesInactive = Math.floor(timeDifference / (1000 * 60));

    if (minutesInactive > 5) {
      // Perform session expiration logic here
    }
  }

  // Render dashboard page
});

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

The vulnerability in this code is an insecure session expiration time. The code sets the lastActivity property of the session to the current date and time whenever a request is made to the server. However, it does not perform any action to close or expire the session after a certain period of inactivity.

In the /dashboard route, the code checks if the lastActivity property exists in the session. If it does, it calculates the time difference between the current time and the last activity time to determine the number of minutes the session has been inactive. If the number of minutes exceeds 5, the code should perform session expiration logic, but it is currently missing.

This vulnerability allows an attacker to exploit the inactive sessions. They can obtain user information and potentially perform unauthorized actions, such as uploading files to the application.

To fix this vulnerability, the code should include session expiration logic inside the if (minutesInactive > 5) block. This logic should close or expire the session, ensuring that inactive sessions are terminated after the specified time limit.

Steps

  • Install and import the 'express-session' package.
  • Configure the session middleware in the Express app.
  • Set the 'maxAge' option for the session to 5 minutes.
  • Use the 'req.session.touch()' method to update the session's last activity time on every request.
  • Add a middleware to check the session expiration time and end the session if it has expired.
  • Update the code inside the '/dashboard' route to handle expired sessions.
  • Test the updated code to ensure sessions expire after 5 minutes of inactivity.

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: {
    maxAge: 5 * 60 * 1000, // 5 minutes
  },
}));

app.use((req, res, next) => {
  req.session.lastActivity = new Date();
  next();
});

app.use((req, res, next) => {
  if (req.session.lastActivity) {
    const currentTime = new Date();
    const timeDifference = currentTime.getTime() - req.session.lastActivity.getTime();
    const minutesInactive = Math.floor(timeDifference / (1000 * 60));

    if (minutesInactive > 5) {
      req.session.destroy(); // End the session if it has expired
    } else {
      req.session.touch(); // Update the session's last activity time
    }
  }

  next();
});

app.get('/dashboard', (req, res) => {
  if (!req.session.lastActivity) {
    // Handle expired session
    return res.redirect('/login');
  }

  // Render dashboard page
  res.render('dashboard');
});

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

The fixed code addresses the vulnerability by implementing a session expiration mechanism. Here's an explanation of the code:

1. The code imports the necessary modules, including Express and Express session.

2. An Express application is created.

3. The express-session middleware is added to the application using app.use(). It is configured with a secret key, resave set to false, saveUninitialized set to true, and a cookie configuration with a maximum age of 5 minutes.

4. A middleware function is added using app.use() to update the lastActivity property of the session with the current timestamp on every request.

5. Another middleware function is added using app.use() to check the session's last activity time. If the session has been inactive for more than 5 minutes, the session is destroyed using req.session.destroy(). Otherwise, the session's last activity time is updated using req.session.touch().

6. An example route for the dashboard is added using app.get(). It checks if the lastActivity property exists in the session. If it doesn't exist, it means the session has expired, and the user is redirected to the login page. Otherwise, the dashboard page is rendered.

7. The application listens on port 3000.

In summary, the code sets the session expiration time to 5 minutes and updates the session's last activity time on every request. If the session remains inactive for more than 5 minutes, it is destroyed. This ensures that user sessions expire after a specified period of inactivity, mitigating the vulnerability.

References