netblue30 / firejail

Linux namespaces and seccomp-bpf sandbox
https://firejail.wordpress.com
GNU General Public License v2.0
5.75k stars 563 forks source link

firefox: Yubikey u2f does not work if plugged in after launching (private-dev) #1990

Closed chiraag-nataraj closed 6 years ago

chiraag-nataraj commented 6 years ago

So as documented in a bunch of issues (#1553, #1381), private-dev is broken with U2F. But I worked around that by using a whitelist instead in my Firefox profile, and it works.

However, I ran into a separate issue just now. The Yubikey is put into a different mode if I plug it in after starting the browser. So normally, it should use U2F authentication when requested. However, I think it gets stuck in OTP mode if I plug in the Yubikey after starting Firefox. If I plug it in before starting the browser, everything works as expected. But if I take it out and plug it back in later (say, because I want to authenticate another site), I run into the same issue. I will try removing my whitelist /dev entries to see if that fixes the issue.

chiraag-nataraj commented 6 years ago

Yup, commenting out the whitelist /dev entries fixes the problem. I'm not quite sure what's going on, since I whitelisted the required /dev/hidraw* devices.

chiraag-nataraj commented 6 years ago

Huh, I'm going to try whitelisting /dev/usb/hiddev*

chiraag-nataraj commented 6 years ago

Okay, I see what's happening. When I whitelisted /dev/usb/ and /dev/usb/hiddev0, those devices existed upon startup. However, when I took the Yubikey out and plugged it back in, /dev/usb/hiddev0 failed to reappear. Given that this file is created when the Yubikey is plugged in, this is probably why authentication no longer works when you take out the Yubikey and plug it back in.

@netblue30 Do you have any idea why the whitelisted file is not re-appearing when it is re-created? Or rather, is there any way we can enable this? This would probably need some type of inotify system and a new command-line/profile option (something like --watch=<file or directory>) which would watch for and react to changes. Thoughts?

Vincent43 commented 6 years ago

I think the problem is that firejail drops all privileges and can't modify sandbox after it was created. You have to either plug the token before starting sandbox or add ignore private-dev to local modifications.

chiraag-nataraj commented 6 years ago

Hmmm. I guess the problem is that with either whitelist or private-dev, a new view of the filesystem is created which is effectively static. But if that's the case, why is /dev/usb/hiddev0 disappearing after I disconnect it? Shouldn't the device file remain even if the device itself is disconnected?

Vincent43 commented 6 years ago

I think it's better to say that new view of filesystem is subset of the old view at the time it's created. So if existing device is deleted from host it's also deleted from sandbox but when new device is added to host the sandbox remains unaffected.

chiraag-nataraj commented 6 years ago

Hmm, and this is a feature of mount namespaces I take it?

chiraag-nataraj commented 6 years ago

Looking at the mount_namespaces man page, couldn't we use the MS_SHARED propagation type? That is, use the MS_SHARED propagation type only on those specific files and directories that we whitelist (specifically for private-dev or whitelist on files/directories in /dev)?

netblue30 commented 6 years ago

However, when I took the Yubikey out and plugged it back in, /dev/usb/hiddev0 failed to reappear.

That's the mount namespace, it has its own mount table. When you plug in a USB device it goes into the default mount table and it will not be propagated to all other namespaces.

There is this list of devices: https://github.com/netblue30/firejail/blob/master/src/firejail/fs_dev.c#L51

What if we add /dev/usb/hiddev* to the list by default? It will take care of the case when you already have the Yubikey plugged in. Then we add a --nou2f option similar to --nodvd, --novideo etc.

chiraag-nataraj commented 6 years ago

What if we add /dev/usb/hiddev* to the list by default? It will take care of the case when you already have the Yubikey plugged in. Then we add a --nou2f option similar to --nodvd, --novideo etc.

Hmmm, that would go part-way towards solving this. But unlike with many other things, Yubikeys (and other U2F hardware devices) are things we repeatedly plug in and take out (leaving them in all the time can be a security risk, since it means that if the laptop is stolen, so is the key). As I mentioned above, there seem to be different mount propagation modes, and the behavior you're describing would be the default (slave?) mode iirc. Would it be possible to set up a shared mount for just the specific devices that are whitelisted? Or is that fundamentally impossible?

chiraag-nataraj commented 6 years ago

Also, the key parts seem to actually be the things in /dev/usb (i.e. /dev/usb/hiddev0 in my example above), since /dev/hidraw* seem to stay around even after I take out the Yubikey?

chiraag-nataraj commented 6 years ago

Huh, this is actually really interesting. I tried using unshare to play around with mount namespaces. It seems that if I use unshare to create a private,slave mount namespace (through sudo unshare -m --propagation slave /bin/bash), it still recognizes when the Yubikey is plugged back in (consistent with the manpage, which states that "When a mount point is a slave, mount and unmount events propagate into this mount point from the (master) shared peer group of which it was formerly a member. Mount and unmount events under this mount point do not propagate to any peer."

That is, mount events from the master (in this case, that should be the global namespace, right?) should propagate into the slave namespace, while mount events in the slave shouldn't propagate back. But that seems to not be happening, even though this is a private,slave namespace. Does this have to do with the fact that we're creating mount namespaces for individual files?

netblue30 commented 6 years ago

Try the latest from main. I am bringing in by default /dev/usb in --private-bin:

https://github.com/netblue30/firejail/commit/2b4afcfb0ae77ffd40e665efdada274d804678bc

chiraag-nataraj commented 6 years ago

Nope. I think we need to whitelist /dev/hidraw* as well? I'm going to add it and try and report back.

chiraag-nataraj commented 6 years ago

Latest commit should fix it 78011fbc922e4dc69f41b107cefee8bbd26d11bc

chiraag-nataraj commented 6 years ago

I suppose there's really nothing we can do about the device not re-appearing when we plug it back in, is there?

chiraag-nataraj commented 6 years ago

Also added a --nousb option to the command args and nousb option for the profile.

197bcc86c1a1f4c75d6a42a850e0619b3268db1e

chiraag-nataraj commented 6 years ago

If there's no way to solve the mount propagation issue, I think I can close this.

kubrickfr commented 6 years ago

Would it be possible to add a udev rule to have the /dev/ file permanently in place even if the device is not connected?