Search code examples
webpackwebpack-dev-serverwebsecurity

What is the purpose of webpack-dev-server's allowedHosts security mechanism?


What security risk is webpack-dev-server trying to mitigate by enforcing specific Host header values?

By default, webpack-dev-server only allows connections whose Host header specifies a local loopback address (localhost, 127.0.0.1, etc). All other hosts get this response: "Invalid Host header". But of course the --allowed-hosts/allowedHosts configuration allows this restriction to be broadened.

This appears to be based solely on the Host header. I can set a custom Host header with curl, and the request succeeds:

curl -X GET -H "Host: http://0.0.0.0:9001/" http://me.internal.example.com:9001/

So I'm curious — if allowedHosts doesn't prevent connections from curl or other custom user agents, what problem does it solve? It seems aimed only at normal users using normal browsers, to protect them from a site served at the wrong host. But a Man-In-The-Middle attack could just as easily proxy the connection and override the Host header.

To prevent MITM attacks, you'd use https (with a certificate that's trusted by the browser). But in that case, the certificate would seem to mitigate the MITM attack by itself.

I'm sure I'm missing something, so any further explanation is appreciated.


Solution

  • Short version:

    The attack is: An evil website reads data from your local webpack-dev-server using AJAX.


    Long version:

    This is the normal security mechanism that is used with websockets.

    The attack

    The attack works like this: You are currently signed in on stackoverflow.com. An attacker sends you an email with a link: Hey, watch these cute kittens <a href="evil-attacker.com">here</a>. Of course you immediately click the link. The page on evil-attacker.com contains a Javascript that connects to stackoverflow.com and writes answers in your name (because you are signed in) that make you look bad.

    Same-origin-policy

    Stackoverflow.com could protect you against this kind of attack by checking that the Origin header of the POST request that creates the answer is "stackoverflow.com". In this case it would be "evil-attacker.com" and the post would be rejected.

    But what if the Stackoverflow developers have been on holiday for many years and stackoverflow.com is not maintained any more - no one has implemented such a protection.

    Luckily the browser developers were not on holiday and they implemented an additional type of protection - the same-origin policy. It just means that the browser will not allow evil-attacker.com to connect to stackoverflow.com (a different domain) to make malicious posts.

    CORS

    If Stackoverflow wants to allow certain websites to run actions in your name, for example to allow meta.stackoverflow.com to show your username from stackoverflow.com, they have to use CORS preflight requests.

    Websockets

    Websockets are a new technology - there are no old (unmaintained) web sites that use websockets. Therefore there is no need for a same-origin policy to protect old web sites from such attacks.

    So when the Websocket protocol was specified, they decided to use the simpler Origin check described above.

    For this to work, the Websocket server has to know from which origins it may be legitimately accessed.