Open davidebeatrici opened 4 years ago
I assume mumble has to be running before executing this command?
No, the capability is set to the executable.
@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?
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.
@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.
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()
.
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.
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
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?
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)
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
@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.
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
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:
Adding a GUI and CLI process launcher to mumble. This would make mumble the parent process of the game (or Steam)
Add a separate mumble-link
process to perform the tracing. This would work regardless of firejail support. It provides a bit more separation between mumble, the plugins, and the game. It also limits access: If you launch "steam" via mumble, then mumble could ptrace all of steam. New RPC calls would probably be required.
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.
Thank you very much!
I added a warning about the potential security issue in the first message.
The capability can be applied like this:
It's required:
firejail
environment.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!