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.
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 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.
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.
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 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.