Skip to main content

Uncontrolled external site redirect

Need

Controlled and secure external site redirects

Context

  • Usage of TypeScript for statically typed JavaScript development
  • Usage of Express for building web applications and handling HTTP requests

Description

Non compliant code

import express from 'express';

const app = express();

app.get('/redirect', (req, res) => {
const redirectUrl = req.query.url;
res.redirect(redirectUrl);
});

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

The vulnerability in this code is an uncontrolled external site redirect.

In the code, there is a route defined for "/redirect" which accepts a query parameter called "url". When a GET request is made to this route, the code retrieves the value of the "url" parameter from the request query and uses it as the destination for the redirect.

The problem is that the code does not validate or sanitize the value of the "url" parameter. This means that an attacker can manipulate the value of the "url" parameter to redirect users to any site of their choice, including malicious websites.

For example, an attacker can craft a URL like "/redirect?url=http://malicious-site.com" and when a user clicks on this link, they will be redirected to the malicious site without their knowledge or consent.

To fix this vulnerability, the code should validate and sanitize the value of the "url" parameter before using it for redirection. This can be done by implementing a whitelist of allowed URLs or by using predefined parameters for redirection instead of allowing user-controlled input.

Steps

  • Validate the redirect URL before using it in the redirect
  • Use a predefined list of allowed redirect URLs
  • Sanitize the redirect URL to remove any potentially malicious characters or scripts
  • Implement a whitelist approach for redirect URLs instead of a blacklist approach
  • Consider using a safer alternative to the 'redirect' function, such as 'res.sendFile' or 'res.render'

Compliant code

import express from 'express';

const app = express();

const allowedRedirectUrls = [
'https://example.com',
'https://example.org',
'https://example.net'
];

app.get('/redirect', (req, res) => {
const redirectUrl = req.query.url;

if (allowedRedirectUrls.includes(redirectUrl)) {
res.redirect(redirectUrl);
} else {
res.status(400).send('Invalid redirect URL');
}
});

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

The fixed code addresses the vulnerability by implementing proper control over external site redirects.

First, the code imports the Express framework and creates an instance of the application.

Next, an array called allowedRedirectUrls is defined, which contains a list of predefined URLs that are considered safe for redirection.

The code sets up a route for the /redirect endpoint using the app.get method. When a GET request is made to this endpoint, the code retrieves the url query parameter from the request.

To ensure the safety of the redirect, the code checks if the redirectUrl is included in the allowedRedirectUrls array using the includes method. If the URL is found in the array, the code calls the res.redirect method to perform the redirect to the specified URL.

If the redirectUrl is not found in the allowedRedirectUrls array, the code responds with a 400 status code and sends the message "Invalid redirect URL" using the res.status and res.send methods.

Finally, the code starts the server on port 3000 and logs a message to indicate that the server is running.

By using predefined parameters and checking against a predefined list of safe URLs, the code ensures that only trusted URLs can be used for redirection, mitigating the risk of uncontrolled redirects to malicious sites.

References