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.