Prevention of unauthorized external site redirects
import express from 'express';
const app = express();
app.get('/', (req, res) => {
const { host } = req.headers;
const redirectUrl = `https://${host}/redirected`;
res.redirect(301, redirectUrl);
});
app.get('/redirected', (req, res) => {
res.send('You have been redirected!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
The vulnerability in this code is an uncontrolled external site redirect, also known as Host Header Injection. This vulnerability occurs when the server processes requests with the Host header set and redirects clients to any destination specified in the Host header.
In the vulnerable code, the server receives a GET request to the root path ("/") and extracts the value of the Host header from the request headers. It then constructs a redirect URL using the extracted host value and redirects the client to that URL using the
res.redirect
function. The redirect is performed with a 301 status code, indicating a permanent redirect.
The problem with this code is that it blindly trusts the value of the Host header provided by the client. An attacker can manipulate the Host header to redirect the client to an arbitrary external site. This can lead to various security issues.
The impact of this vulnerability includes the ability for an attacker to enumerate the internal network by performing trial and error redirects. They can try different internal IP addresses or hostnames to see if they are valid and accessible. Additionally, this vulnerability can be used to perform a subset of Server Side Request Forgery (SSRF) attacks, where an attacker can make the server send requests to internal resources or other vulnerable systems.
To mitigate this vulnerability, the server should validate and sanitize the Host header value before using it in the redirect. It should only allow redirection to trusted and pre-defined destinations, rather than blindly redirecting based on the client-provided Host header.
import express from 'express';
const app = express();
const trustedDomains = ['example.com', 'trusteddomain.com']; // Add your trusted domains here
app.get('/', (req, res) => {
const { host } = req.headers;
if (!trustedDomains.includes(host)) {
res.status(403).send('Forbidden');
return;
}
const redirectUrl = 'https://example.com/redirected'; // Replace with your safe redirect URL
res.redirect(301, redirectUrl);
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
The fixed code is written in TypeScript using the Express framework. It addresses the vulnerability by implementing a server-side check to prevent uncontrolled external site redirects.
Here's an explanation of the code:
1. We import the Express module and create an instance of the Express application.
import express from 'express';
const app = express();
trustedDomains
that contains the list of domains we consider safe for redirection. You should add your trusted domains to this array.
const trustedDomains = ['example.com', 'trusteddomain.com'];
app.get()
method. This handler will be executed when a GET request is made to the root path.
app.get('/', (req, res) => {
// Code for handling the request goes here
});
host
header from the request headers.
const { host } = req.headers;
host
value is included in the
trustedDomains
array. If it is not, we send a 403 Forbidden response and return from the handler.
if (!trustedDomains.includes(host)) {
res.status(403).send('Forbidden');
return;
}
host
value is found in the
trustedDomains
array, we define a
redirectUrl
variable with the safe URL to redirect to. Replace
'https://example.com/redirected'
with your desired safe redirect URL.
const redirectUrl = 'https://example.com/redirected';
res.redirect()
method to perform a 301 redirect to the
redirectUrl
.
res.redirect(301, redirectUrl);
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
host
header will be allowed to proceed with the redirect.