-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
How to securely integrate noVNC inside an authetication system ? #522
Comments
You can use websockify's authentication and token plugin mechanisms to make this work. You can look at the included plugins (see https://github.com/kanaka/websockify/blob/master/websockify/auth_plugins.py and https://github.com/kanaka/websockify/blob/master/websockify/token_plugins.py for examples). You'll have to launch websockify with the appropriate parameters (e.g.
Hmm... at the moment, you'd have to modify noVNC to send that information in a header, and then use an auth plugin. I'm going to play around a bit and see if I can get HTTP basic auth working (but it will required a bit of changing websockfiy).
You should be able to use
Can you try either with a recently release of websockify (launch websockify manually like noVNC v0.5.1 bundles an older version of websockify that may have issues. There should be a new release of noVNC coming out somewhat soon. |
Ok, first thank you a lot. In the meanwhile I found out that the option "--target-config" works. Here the URL must be added the "?path=" in the URL like https://testserver:6080/vnc_auto.html?path=?token=abcd. So the URL is parsed fine. Can somebody explain what function has the path argument (normally it is defined as path=websockify) and should it be set or not or doesn't it matter? So the 0.51 version works fine. Also with the newest branch I got hangups of the VNC canvas, that means after some seconds the connection breakes down. Because of that I went back to a previous version where this problem doesn't appear. I will have a deeper look to the token plugin now. When I try the command "./run --token-plugin /websockify/token_plugins.py 6080 192.111.111.111:5900" I get the following error: Traceback (most recent call last): Where do I get the token plugin an also the auth plugin? Is there somewhere an example how to do that? At the moment I can't figure out completly the differences between simpler websockify commands like "./utils/websockify --verbose --cert ./self.pem --web ./ 6080 --target-config ./token.list" and more advanced commands like " ./run --token-plugin mymodule.MyTokenPlugin --token-source some_arg ... ). Here a tutorial or a manual would help. At the moment I create token files with a long token (bigger than 32 digits length) and start the websockyfy with "--target-config". The calling URL to the websockify webserver is done over an https:// connection. Do you think this is yet a secure solution? Because I thought that the token is like a username and with the use of a password there should be a strong security protection, am I right? What I don't exactly know is when you sent the URL let's say "https://testserver:6080/vnc_auto.html?path=?token=abcd" can than somebody grab (man-in-the middle) the token or is the URL also encrypted when it is send and calling the URL? Can someone tell if this is secure? This question also concerns the password "&password=" argument. I'm not sure if this is also encrypted when you call that URL (it seems to me to be like a php get-submit function and this could be unencrpted and visible to sniffers). Because of the password security I could also hardcode the password in the .js script and instead use a long token so that the security depands only on the length of the token (like a very long keyfile >100 digits). Is this a right way or must I use the token and auth plugin (which I don't understand at the moment how to use and configure it ). Also I'm aware that the URL is saved in the browser history and I heard that a sniffer can read out the browser history with javascript. So how to solve that problem (perhaps token and auth plugin prevent that but how to get it configured)? In my scenario I'm using an autentication system and inside that there is an embedded iframe with the URL defined in the "--target-config" and a very long token. Is that a secure solution yet? |
The
Can you please provide which browser version this occurs on? I recently merged a major PR that changed quite a few things, so I'm trying to make sure that there weren't any major repercussions due to browser quirks.
Sorry, this is a bit of a new feature. You have to pass a class name, not a file path -- if you're using one of the built-in plugins, you can just pass it's class name, like
The built-in token support shouldn't be considered a username/password scheme -- they're easy to fish out of a URL, and are persistent. You could write a plugin that fetches tokens from a database of some sort (a SQL database, memcached, redis, etc), and makes them single-use -- this would be a bit better.
The basic VNC auth isn't very secure (among other things, it's limited to a very short number of characters) -- you shouldn't count on it for security. That being said, you don't have to put |
This commit reworks auth plugins slightly to enable support for HTTP authentication. By raising an AuthenticationError, auth plugins can now return HTTP responses to the upgrade request (such as 401). Related to novnc/noVNC#522
The PR referenced above should make it slightly easier to use HTTP authentication. Included is an example of HTTP basic auth, although it will require either modifying noVNC so that it internally adds a username and password into the connection URL (which the browser will then convert into HTTP auth) or putting the username and password in the host query parameter (which would not be secure). |
This commit reworks auth plugins slightly to enable support for HTTP authentication. By raising an AuthenticationError, auth plugins can now return HTTP responses to the upgrade request (such as 401). Related to novnc/noVNC#522
I checked it once with newest version Also I've tried now Also to your last contribution Lastly please give me your opinion to the following scenario concerning security aspects: |
Can you indicate which versions of those browsers? That's important. Also, can you set the log level to debug and show the contents of the browser javascript console (in the developer tools for Chrome, Firefox, or newer versions of IE). Finally, if you feel comfortable (if I can't identify anything immediately wrong from the logs or browser version), a recording of the broken session would be useful so I can debug from my end (you can do this by running websockify with
The VNC password auth isn't very secure. Additionally, people might want to do authentication of the connection based on things like the HTTP headers, instead of through the VNC protocol. The auth plugins allow you to reject connections based on the header values.
The PR that I created above reworks the way the auth plugins are used internally to noVNC. The upshot of this is that the auth plugins get called before the WebSocket handshake happens, so that they can return different error codes to instruct the browser to attempt to use various forms of HTTP auth, such as HTTP basic auth, SPNEGO, etc. Additionally, you could use something like a cookie to ensure that a user was logged in. You can look at the example plugins to see the structure (they're in auth_plugins.py), but they're basically just classes which have an |
Hi, here are the versions: I've created a recording. I would give you an account where you can download it. Please send me your email. In the browser I can't find the JavaScript console where is it? |
Great. Those browsers should work fine, so this is definitely an issue. The email on my GitHub account page is fine (http://github.com/directxman12) to send to. Thanks! |
In Firefox and Chrome, press F12 and select "Console", (or Firefox Menu->Developer->Web Console, Chrome Menu->Developer Tools, select "Console") Also, which VNC server are you using? |
@comsyspro thanks for helping out with the debug of this. Regarding your security questions, my suggestion would be to use a short lived token that only lasts for a minute or two, and just redirect the browser to a path that includes the token in the URL. This is similar to how openstack (and other systems) integrate noVNC/websockify. Also, I wouldn't necessarily use an iframe. The iframe can cause user interaction issues with noVNC keyboard/mouse and I don't think it adds much to the security if you have short lived tokens. A simple way of easily accomplishing the above without writing a new plugin would be to use the TokenFile plugin. One thing that may not be immediately obvious from the *TokenFile plugins is that rather than storing all your token mappings in a single file, you can store them one token per file in a configuration directory. And if you use TokenFile (rather than ReadOnlyTokenFile) then every time a connection is made, all the config files are re-read. This means that you can easily add and remove tokens just by creating or deleting a config file. You can then have a timer that automatically removes the token after 60 seconds (established connections are unaffected), or a process that sweeps token files older than 60 seconds, or both. That allows you to keep you web framework for your main app and auth separate from the websockify process and use the file-system to communicate the auth information. And it should be reasonably efficient as long as you don't expect to have thousands of simultaneous users. Of course, another option would be to create auth tokens on demand in a DB (rather than a file-systems) and write an auth token that reads from the DB (e.g. and your select could ignore anything older than 60 seconds). As long as your tokens are secure (long and using a good random generator), then that part of your system should be reasonably secure. Of course, if your web framework, it's authentication and the systems it is running on are weak, then all bets are off of course. Also, websockify itself has not been security audited that I'm aware of, so the general model should be okay in theory, but the implementation might have issues. Scratch that ... it definitely has holes. Whether it is worse than your average piece of software is the question. |
For performance reasons, the `handle_tight` function skips the use of the receive queue API and uses the raw receive queue directly. Because of the way that typed array receive queue gets reused, this introduced the potential for buffer over-reads. To address this, a new function, `rQwhole`, was introduced. `rQwhole` simply returns a new view into the receive queue that starts at 0 and ends at the current recorded end of the queue. `handle_tight` now makes use of this function. Fixes #522
@comsyspro I think I found the bug in noVNC. To make a long story short, it looks like it was a buffer over-read issue. Can you try the PR above (#524) and see if it fixes your issue? I probably wouldn't have noticed that without your recording. Thanks a bunch! |
@DirectXMan12 In the output of the console there are no error messages visible but you can see that the canvas stopped here very fast on entering (only few buckets) and sometimes it stops after some seconds. @kanaka |
@comsyspro is that with or without the patch above? |
The above comment was the error case without any changes. @DirectXMan12 |
If you have a redis setup, you could set the TTL when you create the token to 60s, and then the plugin should work something like this (something similar would work with memcached): class SingleUseToken(websockify.token_plugins.BasePlugin):
def __init__(self, src=None):
import redis
self.client = redis.Redis(host=src)
def lookup(self, token):
p = self.client.pipeline()
pair, _ = p.get(token).delete(token).execute()
return pair.split(':') |
😮 I'll have to look into that. Can you possibly send me a recording of that as well (I tried with my own VNC server, and I'm not seeing what you're seeing, I suspect due to TigerVNC having some newer features)?. Testing performance against lots of different VNC servers is quite useful. |
I did a second test with both versions v0.51 and master and now I see no differences in streaming quality - seems to be equal now. |
Authentication is quite specific to the application/system into which websockify/noVNC is being integrated. We've tried to make websockify fairly extensible and pluggable to make this easy, but also generic. There really isn't one right way to do it for all situations. |
Feel free to reopen this if you have further questions on how to use the plugin system. In the mean time, I'm going to close this thread. |
Does someone already have a basic auth example for noVNC and websockify? |
auth plugins work very similarly to token plugins (https://github.com/novnc/websockify/wiki/Token-based-target-selection), so you'll need to use the basic auth plugin in websockify. I don't believe we have a concrete example, but I recall being able to throw one together. There's a trick to get basic auth properly forwarded on the websocket upgrade connection, but I don't recall what I did when testing things out. |
Hi,
1.)
I have an authentication site (let's say "https://www.abcd.com/login.php") where a user puts in his login credentials and logs in to his account website. Now I want to put there in his account a link or an iframe which lets him auto connect to his VNC server. At the moment the only way I know is to point to the URL "https://www.abcd.com:6080/vnc_auto.html?password=1234". But here I would like to have a solution where the URL should be only reacheable inside / embedded in the authentication system that means that the URL should be something like "https://localhost/vnc_auto.html?password=1234" so that the URL is only accessible for the user which logged in his account site and not for others users from outside which could guess an URL and port with a password. Can you please give some advice how to do that? Is it also sensful to put the "?password=1234" in the URL in terms of security or is there another possibility to set the password for an auto connection?
2.)
Besides my apache server is configured for ssl with listen port 443. Is it also possible to "mix" or "redirect" the websockify webserver with the apache server on the same port 443?
3.)
I have problems using the option "--target-config".
Here is the command:
root@testserver:~/noVNC# ./utils/websockify --verbose --cert ./self.pem --web ./ 6080 --target-config ./token.list
The file "token.list" contains the line:
abcd: 192.168.124.123:5900
The URL is:
http://testserver:6080/vnc_auto.html?token=abcd
And here is the error message:
Traceback (most recent call last):
File "/root/noVNC/utils/websocket.py", line 874, in top_new_client
client = self.do_handshake(startsock, address)
File "/root/noVNC/utils/websocket.py", line 809, in do_handshake
self.RequestHandlerClass(retsock, address, self)
File "/root/noVNC/utils/websocket.py", line 112, in init
SimpleHTTPRequestHandler.init(self, req, addr, server)
File "/usr/lib/python2.7/SocketServer.py", line 655, in init
self.handle()
File "/root/noVNC/utils/websocket.py", line 540, in handle
SimpleHTTPRequestHandler.handle(self)
File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
self.handle_one_request()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
method()
File "/root/noVNC/utils/websocket.py", line 506, in do_GET
if not self.handle_websocket():
File "/root/noVNC/utils/websocket.py", line 494, in handle_websocket
self.new_websocket_client()
File "./utils/websockify", line 48, in new_websocket_client
(self.server.target_host, self.server.target_port) = self.get_target(self.server.target_cfg, self.path)
File "./utils/websockify", line 94, in get_target
raise self.EClose("Token not present")
AttributeError: ProxyRequestHandler instance has no attribute 'EClose'
Reaing zombies, active child count is 6
Ignoring interrupted syscall
What happens here?
Thanks.
I'm using this release:
https://github.com/kanaka/noVNC/releases/tag/v0.5.1
The text was updated successfully, but these errors were encountered: