Is HttpServletRequest.getRequestURL() spoofable?

919 Views Asked by At

The question is self explanatory, I hope. I am setting up a Spring Security enviroment with a CAS-server. Because the exact same application is deployed on the same server, but the server is accessible via different host names (.de domain, .com domain, possibly more than that) and we want to deploy the same application on test systems and the local one as well, I built a dynamic service, where the service URL is derived from request URL.

public static String makeDynamicUrlFromRequest(ServiceProperties serviceProperties, HttpServletRequest request) {
        String serviceUrl = "https://backup-url.de/login";
        URI uri = null;
        try {
            uri = new URI(request.getRequestURL().toString());
        } catch (URISyntaxException e) {
            logger.error("Someone tried accessing a disallowed service!", e);
        }

        if(uri != null){
            serviceUrl = uri.getScheme() + "://" + uri.getHost() + "/login";
        }

        return serviceUrl;
    }

Is it possible to spoof this? If it is, does an additional regex-check provide me with the necessary security against this?

1

There are 1 best solutions below

4
Niko O On

@developerwjk
"If they modified the request url how would you have gotten the request?"
An HTTP server is just a program that listens on a TCP port, waits for some incoming text and writes out some text as a response. (A trivial web server can be written in like 20 lines of code.) It only sees the IP address and port of whatever connected to it. That could even be a proxy, or some other sort of middle-ware. If you don't tell the program "by the way, I reached you through the URL http://my.com/myapp/servlet" then it just doesn't know e.g. how a browser will reach it.

@Schaka I don't know about your particular setup, but for jetty9, the result of getRequestURL is determined from the request URL in the request header, and - if the former is missing - the URL in the Host parameter. That is, if you connect to my.com and send the following request:

POST http://spoofed1.tld/myapp/servlet HTTP/1.1
Host: spoofed2.tld

(Keep in mind that the Host parameter is mandatory.)
Then getRequestURL will return http://spoofed1.tld/myapp/servlet

And if you send this:

POST /myapp/servlet HTTP/1.1
Host: spoofed2.tld

Then jetty itself will respond with

HTTP/1.1 302 Found
Location: http://spoofed2.tld/myapp/servlet
Content-Length: 0
Server: Jetty(<some version number>)

So the answer is yes, HttpServletRequest.getRequestURL() is spoofable! by modifying the request URL and/or the Host request header.