If you can make the browser make a request to http://targetaddress.com/whatever
. The browser will default make a plain HTTP request, not an HTTPS one as there is no cached response for /whatever
, only for /
.
This can be achieved in several ways. One way is to MITM between the browser and any website accessible through plain HTTP and insert an <img>
tag. Another way is to trick the user to enter targetaddress.com/whatever
in the address bar through social engineering.
As soon as the browser makes a clear-text request to the target domain, the MITM has won the game.
HTTP enables a client to perform actions on entities. Which action is performed depends on the HTTP method specified in the request. Which entity the action is performed on depends on the URL specified in the request.
Different URLs can reference the same entity, but the browser does not know this. When a browser caches an HTTP response, it does so for a given URL.
http://www.target.com/
is an URL. http://target.com/
is another one. http://www.target.com/whatever
is yet another one. So is http://www.target.com/?
.
Now, suppose there is a cached entry for http://www.target.com/
in a browser. Does it implies there is one for any of the other URLs listed above? No, it does not.
Thus, getting back to the question, making the browser send a plain text request in the case where a permanent redirect is returned by a Web application on the HTTP port is a matter of crafting an URL which does not match a cache entry and tricking the user to visit this URL.
Proof this works:
127.0.0.1 - - [13/Apr/2016:10:01:17 +0200] "GET / HTTP/1.1" 301 226 "-" "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
127.0.0.1 - - [13/Apr/2016:10:01:35 +0200] "GET / HTTP/1.1" 301 226 "-" "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
127.0.0.1 - - [13/Apr/2016:10:02:10 +0200] "GET /whatever HTTP/1.1" 301 234 "-" "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
127.0.0.1 - - [13/Apr/2016:10:02:36 +0200] "GET /whatever HTTP/1.1" 301 234 "-" "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
127.0.0.1 - - [13/Apr/2016:10:08:16 +0200] "GET / HTTP/1.1" 301 226 "-" "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
127.0.0.1 - - [13/Apr/2016:10:08:25 +0200] "GET /? HTTP/1.1" 301 227 "-" "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
I have been able to make six (arbitrary number) clear text HTTP requests to the same Web site with the same browser even though a permanent redirect is configured for everything. (And no, I did not clear the browser's cache!)
Other obvious ways to work around a permanent redirect include tricking the user into switching to anonymous browser mode (no cache) or switching to another browser ("I have issues when accessing the app with IE. Can you have a look?").