mozilla / geckodriver

WebDriver for Firefox
https://firefox-source-docs.mozilla.org/testing/geckodriver/
Mozilla Public License 2.0
7.21k stars 1.53k forks source link

v0.30.0 broke running geckodriver and webdriver clients on different hosts (e.g. different Docker containers) #1935

Closed blueimp closed 2 years ago

blueimp commented 3 years ago

System

Testcase

geckodriver --host 0.0.0.0 --log trace

Stacktrace

geckodriver: error: invalid --host: 0.0.0.0. Must be a local loopback interface

geckodriver 0.30.0 (d372710b98a6 2021-09-16 10:29 +0300) 

Background

In version v0.30.0, geckodriver received the following two changes:

This prevents use cases like running geckodriver and a webdriver client on different hosts, e.g. in a multi-container docker setup like e.g. https://github.com/blueimp/wdio

It's possible to workaround this by using a reverse proxy (see e.g. https://github.com/blueimp/geckodriver/commit/a3c7a83f224b35a86e3e7bc2d19e7353cb4c3ccf), but this adds unnecessary complexity.

A possible solution would be to re-enable geckodriver to listen on all network interfaces and to accept all host headers, e.g. either by disabling host checks when 0.0.0.0 is set as host IP, or by providing additional command-line parameters.

Chromedriver has faced a similar problem which has been discussed in Issue 3857: Host header or origin header is specified and is not whitelisted or localhost. Their solution is to allow listening on all network interfaces via --whitelisted-ips= (empty parameter) and disabling Host header checks via allowed-origins=* (part of the upcoming release of Chrome v95).

jgraham commented 3 years ago

We didn't consider that people might be running a setup with geckodriver in a different container to the client.

I'm reluctant to add an option that opens you up to CRSF vunerabilities (i.e. blanket allowing anything), but I think adding the possibility to explictly allow certain hostnames/ips is reasonable.

blueimp commented 3 years ago

Thanks for your consideration!

I would still implore you to consider adding an option allowing all client IPs, since in a container context IPs are not known beforehand. Similarly, the host header might not be predetermined either, depending on how the container resolution is set up and depending on which client is accessing the geckodriver server.

blueimp commented 3 years ago

In regards to CSRF protection, I assume the threat model is an evil page under test which sends requests to the webdriver server from a browser context and would therefore be able to control its own automated browser instance (e.g. by sending fetch requests to localhost).

Wouldn't it be enough of a mitigation to continue validating the Origin header (reject if set and not localhost)? This would not impact remote webdriver clients, since they don't send an Origin header.

blueimp commented 3 years ago

To illustrate, the following request should be allowed:

curl -v -H 'Host:geckodriver' -d '{"capabilities":{}}' localhost:4444/session

The following request should be rejected - unless the Origin http://example.org/ is explicitly allowed:

curl -v -H 'Origin:http://example.org/' -H 'Host:geckodriver' -d '{"capabilities":{}}' localhost:4444/session

Being able to provide an allow-list of accepted Origin headers would also support a possible use case of webdriver clients running in a browser context.

gtllbx commented 3 years ago

Hello,

We are also impacted by these new limitations to the --host command line parameter. We have an automated tests setup as follow : tests are run on hostA, while geckodriver is deployed as a remote server on hostB (with geckodriver.exe --host 12.34.56.78 --port 12345) Until v29, this worked fine. With v30, deploying the geckodriver as a remote server fails due to

geckodriver.exe: error: invalid --host: 12.34.56.78. Must be a local loopback interface

regards, G

whimboo commented 3 years ago

There is https://bugzilla.mozilla.org/show_bug.cgi?id=1732622 now, which will be used to handle the mentioned cases. Thanks for reporting!

blueimp commented 3 years ago

To answer my own question from above: James Graham brought up two concerns that are not covered by an Origin-based restriction:

A DNS rebinding attack might allow a website to perform a "same origin" request that actually ends up on a local ip. That could at least allow malicious sites to make GET requests without an Origin header.

Old clients that might not correctly set the Origin header and so leave users vunerable (this is the one that still seems problematic if we allow any ip address).

See also: https://bugzilla.mozilla.org/show_bug.cgi?id=1732622#c13

alexmi256 commented 2 years ago

Super stranger, my tests run at a ~15x slower rate with 0.30.0 vs 0.29.1 which seems to be cause by this issue.

whimboo commented 2 years ago

Super stranger, my tests run at a ~15x slower rate with 0.30.0 vs 0.29.1 which seems to be cause by this issue.

Would you mind filing a new issue with a trace log attached about that? It doesn't sound to be related to this problem given that it wouldn't work at all. Thanks.

whimboo commented 2 years ago

@blueimp we fixed it for the next geckodriver release. Would you have the chance to check the behavior with a Nightly build of geckodriver? If yes, you can find the CI generated builds here. The artifact (geckodriver.tar.gz) you can find in the lower pane. Thanks a lot.

I'm already closing this issue but we will reopen if it's not fully fixed.

ruescar commented 2 years ago

@whimboo I've tried the geckodriver Night build you suggested and I'm still getting a similar error to the one I was getting with version 0.30.0

jgraham commented 2 years ago

@ruescar How are you starting geckodriver (i.e. what's the command line)? You may need to set --allow-host=localhost explicitly if you're not starting on a common local ip address.

ruescar commented 2 years ago

@jgraham @whimboo Still not working using --allow-hosts=localhost Screenshot 2022-02-09 at 13 27 23

whimboo commented 2 years ago

@ruescar but to what resolves localhost? Can you please check that?

ruescar commented 2 years ago

@whimboo 127.0.0.1

whimboo commented 2 years ago

This is strange. @jgraham any idea?

Basically if you start geckodriver on localhost you won't have to specify an entry via --allow-hosts. @ruescar can you please check with a different IP if you are affected by this docker issue?

@blueimp could you maybe check if the Nightly build as referenced in https://github.com/mozilla/geckodriver/issues/1935#issuecomment-1015128435 fixes the issue for you? Thanks.

jgraham commented 2 years ago

Based on the logs, it looks like the port part of the host header isn't matching. Because the port isn't a default HTTP port it's expecting localhost:44799 in the Host header, not just localhost. Which WebDriver / HTTP client is this?

ruescar commented 2 years ago

@jgraham This is happening inside Selenoid Browser images launched in a Selenoid grid. A new random port is used for each session. In the run I shared, we use Selenium Java bindings @vania-pooh Maybe you could give more info about implementation details.

vania-pooh commented 2 years ago

@ruescar currently we just set Host: localhost.

whimboo commented 2 years ago

@vania-pooh could you please try to also set the port and report back if that works as expected? We would appreciate. Thanks.

vania-pooh commented 2 years ago

@whimboo this requires source code modification. https://github.com/aerokube/selenoid/issues/1193