motioneye-project / motioneye

A web frontend for the motion daemon.
GNU General Public License v3.0
3.99k stars 655 forks source link

Python3 (Dev): User Authentication not working #2813

Open EpicLPer opened 1 year ago

EpicLPer commented 1 year ago

Heya!

Just installed the dev version (python3) on my Raspberry Pi 3 B+ and tried to configure it the same as my old python2 MotionEyeOS install, however I noticed that the user authentication doesn't work.

Whenever I enable "Basic" or "Digest" authentication and try to enter my credentials (either in Browser, VLC or Blue Iris) it always asks me again or throws an "Unauthenticated" error. I tried changing passwords multiple times but nothing seemed to work. One thing I haven't tried yet is renaming the user.

Is this a known issue? How can I debug this to provide more info here? Thanks!

chri-kai-in commented 1 year ago

I can confirm this behavior for basic authentication with my latest installation:

motionEye version : 0.43.0 Motion version : 4.5.1 Operating system version : Linux 6.1.21-v8+, dietpi distribution Python Version: 3.11.2

Access with camera app shows error message "Invalid username/password" with identical credentials ensured. Access to stream in browser with these credentials does not open the stream, but restarts login process with re-openened login window.

Access to stream with no authentication works.

cinnamonsweets commented 8 months ago

This should be relabeled as a bug. I found a way around it but it is inconvenient. When you save a Surveillance Username and Password, it is written into /etc/motioneye/camera-*.conf > stream_authentication user:password. What I found is the password is being stored as hexadecimal and if I copy paste that hexadecimal password as is, it authenticates and the stream starts. If I replace that hexadecimal with my own password and save it to conf using nano, it would authenticate properly but if I hit apply from the web interface, it will replace my password with hexadecimal again and I have to go back and fix it again.

zagrim commented 8 months ago

Thanks @cinnamonsweets for the hint. I think it's about time to try to fix this issue, I'll look into it today and see if I manage to find the root cause...

zagrim commented 8 months ago

This broke in https://github.com/motioneye-project/motioneye/commit/14156d22b49f6bb6fdf3b46435e4e8926288cd5b I guess, because nobody thought of the streaming port authentication, which is done by Motion, and which can't understand hashed password :disappointed: The security-wise "best" option Motion supports would be MD5 digest auth which doesn't really work for interactive use via browser and is not that great anyway (see docs). It seems the only available solution would be to keep streaming_authentication not hashed as it originally was. Having normal user password hashed in motion.conf doesn't make much sense if the same password is available in plaintext in camera-*.conf, but I'll see if that could be done anyway...

zagrim commented 8 months ago

It seems there's nothing really to be done here except reverting the commit I mentioned (and thus have normal user password unprotected in both motion.conf and camera-*.conf files. There has been a proposal in Motion project to use hashed passwords in Motion for basic auth but that didn't fly: https://github.com/Motion-Project/motion/issues/536

MichaIng commented 8 months ago

Many thanks for identifying the issue. This bugged me as well already, but I never found the time to debug.

Why can MD5 digest not work interactively? motionEye can do the conversion of inputs for its own authentication and motion should do anyway?

And does the same apply for the admin user? There is would be of course more critical do leave it in plain text.

What we could generally do is assuring 600 or 640 mode, so that the files are not world-readable.

zagrim commented 8 months ago

MD5 digest auth cannot work for streaming URL, since that is just between browser and Motion, unless I'm mistaken, and there basic auth is the only option for the user. All the rest (which go through ME) work even now just fine (UI, snapshot URL, embed URL although I didn't specifically test this). Admin isn't really relevant for streaming URL so that's not an issue. Of course, if we'd implement a sort of a authenticating proxy for streaming URL within ME, then we could keep on hashing normal user password and e.g. use MD5 digest auth under the covers with Motion.

The point on config file modes is good and probably worth pursuing.

MichaIng commented 8 months ago

TL;DR: Let's just revert the commit for now like your PR does, to restore functionality. We can think about enhancing security when we find time.

Since this MD5 digest is supported by motion directly, I guess also the login prompt and conversion of input into MD5 digest is handled by motion directly? Of course, in case that is true, and we can store passwords like that (in the motionEye config), also motionEye would need to process this correctly for its own authentication.

Is authentication at the streaming URL not possible as admin user? I mean even if it was, i.e. motionEye sets up both users+credentails in motion/camera configs for that, it is not advised to do that, sharing motionEye admin credentials with every motion instance. But if that was currently possible regardless, we might either need to assure that both works, or simply disable the possibility to authenticate at motion with the motionEye admin user. A surveillance user would then be required in any case for motionEye to authenticate at motion (if I am not mistaken) to process and show streams through motionEye interface.

... thinking further about it, also motionEye needs to pass the credentials in plain text to motion to access the streams, as you cannot authenticate with a hash (MD5), is it? Probably it was hence always meant like that: Have the motionEye admin password hashed, as motionEye processes authentication, but have the surveillance password in plain text stored at least in motionEye config, so motionEye can authenticate with (only) this user against motion for access the streams. It could still be stored in MD5 digest in the motion camera configs, but must be accessible in plain text by motionEye. In this case it does not make much sense to hash it for motion, when it is readable just in anther config file. I then wonder whether the surveillance user even works, currently, when you assign a password. I remember I had trouble even logging in with it at the motionEye UI, but did not find the time to investigate. Probably this was caused by the same faulty commit.

zagrim commented 8 months ago

Since this MD5 digest is supported by motion directly, I guess also the login prompt and conversion of input into MD5 digest is handled by motion directly? Of course, in case that is true, and we can store passwords like that (in the motionEye config), also motionEye would need to process this correctly for its own authentication.

Oh, I misthought what the MD5 digest auth was about (haven't been using that ever). Sure it works just as fine interactively with a browser, and it keeps the password out of plain sight in web traffic, but what it doesn't change is that the password needs to be in clear-text in the config file, which was not working here. The digest auth worked just fine now that I actually tested it, but really it doesn't change the core issue here as it only changes the transport format of the credentials, not the storage.

Is authentication at the streaming URL not possible as admin user?

Currently ME only ever puts main_config['@normal_username'] + ':' + main_config['@normal_password'] into stream_authentication config param, so admin credentials have not been possible to use there.

I then wonder whether the surveillance user even works, currently, when you assign a password. I remember I had trouble even logging in with it at the motionEye UI, but did not find the time to investigate. Probably this was caused by the same faulty commit.

For me login as surveillance user works just fine, but I think there's a possibility of a goof-up when changing the password: What the password field contains after saving is literally just "****", so it you try to edit your password without wiping the field empty first, you do not get the password you thought you would.

MichaIng commented 8 months ago

So my assumption then seems to be right: motion correctly handles authentication when credentials are stored as MD5 digest im its configs, but of course authentication needs to be done with plain text password. All fine when users enter it manually, but also motionEye requires it in plain text somewhere, as it needs to authenticate at motion as well. And since hence there is no way around a plain text password in a config file (unless we implement some encryption and obfuscation of the decryption key and method, not really effectively possible in open source software and non-binary Python scripts), there is no point to hash it in motion configs either.

Good and reasonable then, that only the surveillance user is used for this, so it is not that critical. But of course the camera streams are still a privacy concern and hence those config files should only be readable by the motion user.

Funny that the *** is used as password if not changed. That may indeed be the issue I was facing. We should then treat input as empty/skip saving it, if it consists of stars only, or set a flag if the input equals the pre-filled content. Are there no native password input forms in HTML which do only internally hide/replace content visually, and prevent copying it, but not replace the effective input when sending the form?

MichaIng commented 8 months ago

I think this is worth pushing another beta, but I actually would like to test and merge #2903 first. I just didn't find the time yet, and also the next days I am very busy.