-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Possible security vulnerability to connect to notebook from another tab in the browser or another browser and execute arbitrary code #1830
Comments
Hi there, Thanks for the report. For information we prefer security vulnerability report to be disclosed on security(at)ipython.org in order to investigate without potential malicious listener to use the hypothetic vulnerability. We'll have a look. |
Oh, sorry about that. Do you think it is too late to just delete this issue report or do you think too many people have been notified about it? |
No problem, now that's it's here there are little advantage of removing it. |
Didn't know ipython.org was still around. I should have looked for that at least for a bit first instead of only digging around on jupyter.org |
So a couple of information, regardless of whether you run a localhost server or a remote one we always strongly suggest setting up https/SSL and password. This is in our docs and we are enforcing that a little more each time we make a new major release. We also provide a tool to automaticlly secure notebooks. As far as I can tell, once a notebook server is secured over https + password the server should be immune to the attach describe. If they are over http, then notebook are anyway susceptible to another wide range of attack. Maybe not remote with DNS poisoning, but they give all users and program of the current machine shell access as the user who run the notebook servers/kernels. Unfortunately it is relatively hard to automatically generate a trusted-self-signed certificate for a machine it is (still) something we cannot enforce without manual user intervention. I'm going to refer to @rgbkrk, @minrk and @yuvipanda to be sure, and likely push a bit more user to set-up ssl.
Oh, we are the same developers and IPython is still actively developed. We use the same security mailing list. |
That is good to hear. That does sound like it probably mitigates it (I am not an expert, though) I guess I fell a bit behind the news in the last couple years with the split. |
Sorry about that. The problem was people asking :
So the part of IPython which was not purely python became Jupyter. Does that make some sens ? |
That makes sense. The split was rather nice (i have used the julia and octave kernels some) |
What we did in the Sage notebook (I think implemented by @robertwb) was to by default generate a long random key when the server starts up, and we start the browser with that key in the URL. In Jupyter's case, it's a bit more complicated, but perhaps we could always authenticate the user (either using a random key at startup, or the existing password mechanism) to set an authentication cookie. |
@jasongrout we should be doing that, and once we do, we can require setting a token on the local notebook server. |
I might be misunderstanding something, but since the kernel can execute arbitrary code, one wouldn't need the DNS trick (the kernel could e.g. email the private data)? If so, shouldn't this be a rather severe vulnerability, where instead of running a DNS, one could execute an exploit using even a static webpage? |
Normally the cross-origin protection should mean that only pages loaded from the Jupyter server can talk to the server REST API and open websockets to kernels. I'm not a security expert though, so if you think there's another way round that, please try it and let us know. |
The link http://bouk.co/blog/hacking-developers/ mentioned that cross-origin protection doesn't prevent |
Running code on a kernel requires a websocket connection, but you could do enough to be concerning just by POST-ing. We also do origin checks on the server side, which should prevent this by checking the headers before taking the action. But we skip the check if either the @rgbkrk I'd appreciate your assistance once you're up and about :-) |
With an AJAX request, and it looks like Origin and Host are both forbidden names which cannot be set from Javascript. Now I'll try with forms, as shown in the blog post. |
With a form submission, it appears that you can perform any operation which doesn't require a JSON body. The ones I can find are:
Here's how to replicate it: <form enctype="text/plain" method="POST" action="http://localhost:8888/api/kernels">
<input type="submit" value="Submit" />
</form> With a running notebook server, serve this ( A simple mitigation for the first two cases would be for |
In discussion on jupytergh-1830, I found that HTML forms in Firefox do not send an Origin header. You can therefore submit a POST request with an empty body to trigger certain actions, such as starting a kernel, avoiding the origin check we do. This mitigates that for creating files and starting kernels, by requiring a JSON body, even if there's no data. I cannot currently find a way to create a JSON body in a request sent from a form. The other cases I've found are interrupting and restarting kernels. This does not affect those cases, but they are only possible if you have a kernel ID.
From my limited reading (and a much earlier investigation) the websockets are extremely strict about the origin and header from the browser matching expectations. The usual REST requests are certainly subject to this type of attack though. |
So how serious is this after all? Is it still true that *hubs are secure? What about notebooks, is it worthy to backport a security patch for the versions that are still supported? |
@akhmerov an authenticated server is protected from the DNS issue, so Hubs are not affected. The general fix is to enable a version of authentication that is acceptable to use by default (i.e. not a password that people have to remember). 4.3 is the backport of the security fix to 4.x. Backporting farther would probably not be appropriate. |
I saw that Guile just fixed a method that a browser could connect to it even if it only listened on localhost and possibly run arbitrary code (https://lists.gnu.org/archive/html/guile-user/2016-10/msg00007.html). It seems like Jupyter notebooks would be vulnerable to the same sort of attack.
The attack, which is described at http://bouk.co/blog/hacking-developers/ (cited in the guile bug report), is basically malicious a cross protocol scripting attack combined with DNS rebinding to change the attacking code's DNS record to localhost as the article puts it.
Given that Jupyter notebooks listen to a TCP port on localhost using http, it would seem that Jupyter notebooks might be even more vulnerable to the same sort of attack. I do hope I am wrong on this, though, and jupyter notebooks are immune.
The mitigation that Guile suggests, using a unix socket, would obviously not work for Jupyter notebooks. The whole point is to use them in the browser. Only thing I can think of, if it is an issue, would be to have the jupyter notebook, when it is run, generate some sort of random authentication information and print it out to the terminal and wait a bit before starting everything so that the user can copy it or make a pop-up window in a GUI environment that shows it.
The text was updated successfully, but these errors were encountered: