mumble-voip / mumble

Mumble is an open-source, low-latency, high quality voice chat software.
https://www.mumble.info
Other
6.38k stars 1.12k forks source link

Document need for CAP_SYS_PTRACE under certain circumstances #4506

Open davidebeatrici opened 4 years ago

davidebeatrici commented 4 years ago

The capability can be applied like this:

sudo setcap cap_sys_ptrace=eip mumble

It's required:

For detailed info: https://www.kernel.org/doc/html/latest/admin-guide/LSM/Yama.html

Please note that CAP_SYS_PTRACE allows the program to access any process, regardless of the user they're running as!

Krzmbrzl commented 4 years ago

I assume mumble has to be running before executing this command?

davidebeatrici commented 4 years ago

No, the capability is set to the executable.

Krzmbrzl commented 3 years ago

@davidebeatrici where do you think this should be documented? And what are the symptoms that a user will experience in order to know that they have to apply this?

davidebeatrici commented 3 years ago

Unfortunately there is no clear indication, the plugin simply doesn't "link".

We could check whether the capability is set and show a warning dialog in case it isn't. Perhaps with a link to a detailed documentation page in the repository.

cbs228 commented 3 years ago

@davidebeatrici I've been looking at this issue too. After some study, I find that setting CAP_SYS_PTRACE is a significant security risk.

This capability allows the possessing process to trace any process on the system… and not just processes which belong to the same effective user. Try setting this capability on gdb, and then try to attach something like

gdb -p `pidof systemd-journald` # or some other root-owned process

as an unprivileged user. This works on Ubuntu 20.04. (You will probably want to remove CAP_SYS_PTRACE after that.) This is exploitable.

Mumble will gladly load plugins from the user's home directory. It would not be difficult to write a plugin that abuses this functionality to gain a root shell for a user that shouldn't have it. It could also be a very nasty boost for remote code execution exploits, should any ever exist. A remote code execution vulnerability will become a privileged remote code execution vulnerability.

A more secure way would be to create the parent process requirement that Yama wants. We could probably do this by adding a "launcher" option which can fork() off other arbitrary programs (i.e., steam). Then, Mumble will be the parent process, and the ptrace limitations will be satisfied.

In some ways, it's almost safer to turn off Yama. With Yama off, only user processes can be traced… and programs which specifically request "please don't trace me" will still have that limitation in effect.

davidebeatrici commented 3 years ago

Thank you for investigating.

I wasn't aware of that, I thought CAP_SYS_PTRACE only allowed to access processes running under the same user.

Yama is turned off by default on Debian, but processes that are running through firejail cannot be accessed without CAP_SYS_PTRACE.

Ideally we should find a way to allow Mumble to only access processes that belong to the same user, also the ones that are managed by firejail.

More specifically, we need access to /proc/<id>/exe, /proc/<id>/maps and the process' memory through process_vm_readv().

cbs228 commented 3 years ago

Yeah, my man 7 capabilities only says:

transfer data to or from the memory of arbitrary processes

I don't find this language particularly clear. "Arbitrary" could mean "any," but I think they should call that out.

The least-privileged way I can think of would be to move the tracing into its own wrapper process. The wrapper process would start the game, making it the parent process. In your case, you would run it inside the firejail. The wrapper would report its results to mumble via a UNIX socket or named pipe. The wrapper could also handle injection of the mumble overlay.

There might be other alternatives out there, but this would work with both Yama and firejail and doesn't require any capabilities.

davidebeatrici commented 3 years ago

Your idea would also prevent Mumble from crashing in case a plugin is faulty, but the game would crash instead.

As an alternative method to CAP_SYS_PTRACE it's definitely excellent, much less invasive.

For reference: https://github.com/TheDiveO/lxkns/blob/e3c99039998a74c895dfd03975c5a1f6b655a473/docs/notes.md https://github.com/glennklockwood/procmon/blob/c6e67d63e7c9c24f85a46b6d8965b8c615097edc/README.secured

cbs228 commented 3 years ago

There might be a way to write a seccomp filter to allow ptrace for firejail processes. firejail may actually be blocking it by default:

I'm not particularly familiar with kernel namespaces or firejail, but this merits investigation.

EDIT: if that could be made to work, then all we'd need to do would be to add an arbitrary process starter to mumble to launch the game. (Perhaps via CLI arguments too, for people that like .desktop launchers.)

For Yama, we could also LD_PRELOAD a library which uses prctl(2) to make the game ptrace-able by mumble. But that would be yet another binary that would need to be cross-compiled for x86 and x86_64, and it's another thing that can go wrong.

Moving the tracing into its own process would probably be cleaner.

I can really only see one disadvantage with creating a dedicated "mumble-link" wrapper program. A dedicated wrapper program would obsolete MumblePluginQt::config(). The proposed wrapper process wouldn't really need a GUI, but we could give it one if we really wanted to. Without the ability to display windows, we would need an alternative configuration mechanism. This primarily affects the Manual Placement Plugin, which maybe needs to be folded into mumble core. Other plugins might need to read CLI configuration options. This would be API-breaking for plugins.

Should we use the existing RPC/dbus interface to set the position? Can these sockets sustain the signaling rate we would need for game position? dbus might be an issue if you want firejail to block it.

I am not sure how this change would impact Windows or Mac.

Also… is there a a reason why the Ubuntu packages don't seem to contain the plugins? Is this a licensing/distribution issue?

Krzmbrzl commented 3 years ago

This would be API-breaking for plugins.

We're going to introduce a new API for plugins in #3743 anyways

Also… is there a a reason why the Ubuntu packages don't seem to contain the plugins? Is this a licensing/distribution issue?

1.3.x doesn't include Windows-only plugins that could be launched through Wine. Therefore the list of plugins that are built there is significantly smaller than the list in 1.4.x (aka current master)

davidebeatrici commented 3 years ago

As a long term solution, we may want to propose a new capability; something like CAP_SYS_PTRACE_STRICT or CAP_SYS_PTRACE_USER.

Implementing it seems to be very easy, the check is performed here: https://github.com/torvalds/linux/blob/0adc313c4f20639f7e235b8d6719d96a2024cf91/security/yama/yama_lsm.c#L347-L392

cbs228 commented 3 years ago

@davidebeatrici testing suggests that you can ptrace even through firejail, but it requires loosening the sandbox restrictions.

First, ensure Yama isn't messing with you. (Change will not persist across reboots.)

sudo sysctl kernel.yama.ptrace_scope=0

Then try

firejail --noprofile top

in one window and

gdb -p `pidof top`

in another. The ptrace system call is allowed. If, however, you run

firejail --noprofile --noroot top

then you are not allowed to attach gdb.

With --noroot given on either the command line or in the profile, firejail creates a new user namespace.

Normally, whenever you create a user namespace, every process in the parent namespace with the same euid has full capabilities. That is, all of your user's processes outside the sandbox would have CAP_SYS_PTRACE and all other capabilities inside the sandbox. Firejail appears to create this user namespace with an euid of zero—and not your uid. I believe this would make the namespace owned by root. No capabilities for you. firejail then performs some mappings to ensure that everything runs correctly with the calling user's permissions.

If you remove the noroot flag from your profile, you should be able to trace. With that said, you have loosened your sandbox a little bit. A process which gains root inside the sandbox could have write access to places it probably shouldn't. We should maybe look at why this option exists and what, precisely, it protects us from.

davidebeatrici commented 3 years ago

I confirm the behavior you're describing.

Related: netblue30/firejail#3012 https://github.com/netblue30/firejail/blob/65911742d70fbe287fc9d0e6f2c9a92e2b6657de/src/firejail/main.c#L2744-L2754 https://github.com/netblue30/firejail/blob/52fb58567fa7360cdd0f6631f658f74c7920d0b6/src/firejail/usage.c#L157

cbs228 commented 3 years ago

Perhaps we should see if proper support for this could be included in firejail. Opened netblue30/firejail/issues/3727.

If support for external debuggers is a safe/sane thing for firejail to do, then all we need to worry about is Yama. For that, my two proposals were either:

Is it worth mentioning up top in the issue description that CAP_SYS_PTRACE exposes the system to privilege escalation attacks? People looking for a quick fix might not read this entire thread.

davidebeatrici commented 3 years ago

Thank you very much!

I added a warning about the potential security issue in the first message.