Uncontrolled external site redirect - Typescript
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
Insecure Code Example
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'
Secure Code Example
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
Last updated
2023/09/18