If you're working with security audits and vulnerability scanners, you might come across the term "unvalidated redirect" or "invalidated redirect". But what exactly is that?
A normal redirect
Let's first look at a normal redirect. A normal HTTP redirect would locate you to a specific different URL, for example redirecting from HTTP to HTTPS:
$ curl -I http://www.geekersdigest.com
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Thu, 17 Feb 2022 10:02:20 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://www.geekersdigest.com/
The Location header shows the redirect destination. This destination is usually known in advance, configured by the website owner. The Location header is therefore set on the server side.
Unvalidated redirect
An unvalidated redirect is when the Location header is manipulated from the client side. A reason for this to happen is when the web server (or .htaccess file) is improperly configured.
The following example shows how the Location response can be manipulated from a HTTP request:
$ curl -H "Host: www.geekersdigest.com" https://webserver.example.com -k -I
HTTP/2 302
server: nginx
date: Wed, 16 Feb 2022 10:14:57 GMT
content-type: text/html
content-length: 154
location: http://www.geekersdigest.com/
The curl command above makes a HTTPs request to webserver.example.com, but changes the "Host" header. As this domain (www.geekersdigest.com) is not known in any configuration on webserver.example.com, the default server configuration is used. Due to a bad configuration on this web server, the response now contains a redirect to the same value as we used in the "Host" header: That's the unvalidated redirect.
Verify your default server configuration
The reason that an unvalidated redirect was even possible, was a wrongly configured default server configuration, such as this:
server {
listen 443 default_server;
access_log /var/log/nginx/localhost.access.log;
error_log /var/log/nginx/localhost.error.log;
ssl on;
ssl_certificate /etc/nginx/ssl.crt/snakeoil.crt;
ssl_certificate_key /etc/nginx/ssl.key/snakeoil.key;
location / {
rewrite ^.*/ http://$host/ redirect;
}
}
Here the server administrator tried to handle HTTPS connections on the default server (such as the server's IP address) and redirect it to the requested "Host". This would work fine when accessing the webserver through the IP address (e.g. https://192.168.1.100) but anything else results in an unvalidated redirect.
To fix this, either use a static redirect:
location / {
rewrite ^.*/ http://192.168.1.100/ redirect;
}
Or let the server display a default HTTP page (or simply return a static status code):
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}