Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

webpack-dev-server vulnerable to DNS rebinding attack #887

Closed
@edmorley

Description

@edmorley

This issue was disclosed privately to@sokra via email on 2017-04-17, and a fix released in webpack-dev-server v2.4.3 / v1.16.4, which were released 2017-04-17.

I'm filing this issue retrospectively to clarify why the additional security check is necessary, in the hope that it makes people reconsider before turning it off (eg#882,#883).

--

Hi Tobias

Thank you for reaching out inwebpack/webpack#4599.

The issue I've noticed is in webpack-dev-server - specifically:

  • it uses the node native http library - passing the hostname (defaultlocalhost) to http's listen() [1].
  • whilst the listen() docs [2] only refer tohostname, the actual behaviour is "resolve hostname to IP, bind to that IP and accept any connections to that IP regardless of the hostname used for the request" [3].
  • webpack-dev-server doesn't perform any verification of theHost header itself.
  • therefore it is vulnerable to DNS rebinding attacks, similar to that fixed in Rails [4] and Django [5].

Implications:

  • a malicious site can steal static content served by webpack-dev-server.
  • this can include any file from the directory where webpack-dev-server was run, not just those that would end up indist/ (is this intentional, seems like an additional bug?).
  • worse, if webpack-dev-server's proxy feature [6] is being used, then this exposes any remote code execution vulnerabilities in the backend stack. This is particularly dangerous, since I would imagine it's common to usechangeOrigin: True [7], which would bypass any Host header checks in the backend app - and so make typical Rails and Django setups RCE-vulnerable.

STR:

  1. Install nodejs 7.x, webpack 2.3.2 and webpack-dev-server 2.4.2.
  2. Create a new project based onhttps://webpack.js.org/guides/get-started/#using-webpack-with-a-config
  3. Run./node_modules/.bin/webpack-dev-server
  4. In another terminal, try requests like:
  • curl -i zzz.malicious-site.com:8080/ --resolve zzz.malicious-site.com:8080:127.0.0.1
  • curl -i zzz.malicious-site.com:8080/package.json --resolve zzz.malicious-site.com:8080:127.0.0.1
  • curl -i zzz.malicious-site.com:8080/.git/config --resolve zzz.malicious-site.com:8080:127.0.0.1

Expected:
HTTP 400s or similar for each curl request, along with a "Invalid Host header" response body - similar to what Django's runserver does.

Actual:
HTTP 200s for cases where the file exists, along with the file contents.

Note: In the examples above,--resolve is being used to quickly emulate what a DNS rebinding attack could achieve, however the same is possible in a browser via a site using DNS rebinding - to demonstrate that this is true:

  1. Use the same project/setup as above
  2. RunDEBUG=express:router ./node_modules/.bin/webpack-dev-server --port 3000
  3. Visithttp://dnsrebinder.net/
  4. Open the web console and watch the XHRs tohttp://<HASH>-bad.dnsrebinder.net:3000/not_found.
  5. When those XHRs change from HTTP 200s to HTTP 404s, it means the DNS for the subdomain has been updated to127.0.0.1.
  6. Check the webpack-dev-server debug output - you'll see theGET /not_found showing the page circumvented CORS and hit the dev server.
  7. Inspect the headers/body of the HTTP 404 response in the browser web console - you'll see they are from the webpack-dev-server Express server - and could just have easily been an HTTP 200 disclosing local file content if the page had requested a more relevant URL.

dnsrebinder.net (source: [8]) is is a proof of concept for the Rails dev server RCE vulnerability mentioned above, hence the port 3000. It doesn't do anything interesting since it's relying on Rails specific behaviour, but it demonstrates the point without me needing to spin up something similar using AWS Route53 (I can if required). Note: A small number of DNS servers filter 127.0.0.1, if you can't repro, use Google DNS (8.8.8.8 / 8.8.4.4).

To fix this issue aHost header check needs to be added to webpack-dev-server, that's ideally enabled by default, with a big warning shown if there is a way to disable it.

In addition I think the nodejs http listen() docs [2] should be updated - but I'll file an issue there myself later.

[1]https://github.com/webpack/webpack-dev-server/blob/v2.4.2/bin/webpack-dev-server.js#L402
[2]https://nodejs.org/api/http.html#http_server_listen_port_hostname_backlog_callback
[3]https://stackoverflow.com/questions/21158686/node-js-express-limit-to-certain-hostname
[4]https://benmmurphy.github.io/blog/2016/07/11/rails-webconsole-dns-rebinding/
[5]https://docs.djangoproject.com/en/1.11/releases/1.10.3/#dns-rebinding-vulnerability-when-debug-true
[6]https://webpack.js.org/configuration/dev-server/#devserver-proxy
[7]https://github.com/chimurai/http-proxy-middleware#http-proxy-options
[8]https://github.com/benmmurphy/rebinder

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp