Thursday, May 10, 2018

Linux sandboxing improvements in Firefox 60

Continuing our past work, Firefox 60 brings further important improvements to security sandboxing on Linux, making it harder for attackers that find security bugs in the browser to escalate those into attacks against the rest of the system.

The most important change is that content processes — which render Web pages and execute JavaScript — are no longer allowed to directly connect to the Internet, or connect to most local services accessed with Unix-domain sockets (for example, PulseAudio).

This means that content processes have to follow any network access restrictions Firefox imposes — for example, if the browser has been set up to use a proxy server, connecting directly to the internet is no longer possible. But more important are the restrictions on connections to local services: they often assume that anything connecting to them has the full authority of the user running it, and either allow it to ask for arbitrary code to run, or aren't careful about preventing that. Normally that's not a security problem because the client could just run that code itself, but if it's a sandboxed Firefox process, that could have meant a sandbox escape.

In case you encounter problems that turn out to be associated with this feature, the `security.sandbox.content.level` setting described previously can be used for troubleshooting; the network/socket isolation is controlled by level 4. Obviously we'd love to hear from you on Bugzilla too.

Additionally, System V IPC is now blocked. This is a relatively old way of communicating between processes on Unix systems, which modern software mostly avoids. It's not needed in content processes, and it can grant access to resources they shouldn't have, so we now block it. (There are exceptions: ATI's legacy `fglrx` graphics drivers and VirtualGL require it, so if either of those is in use, we grant an exception. This does not affect newer AMD drivers, who can run with these restrictions in place.)

These changes also allow something else useful: because content processes no longer need any direct access to the network or filesystem (they can still ask the main process for some whitelisted subset they are allowed to read), we can ask the kernel to take it away.

Specifically, we use Linux namespaces and chroot. This is similar to how containers like Docker work, and complements the existing sandbox: in addition to blocking specific system calls like `open` and `connect`, we can prevent filesystem/network access no matter how it is requested. This is part of our defense in depth: if a clever attacker manages to bypass one layer of protection, that still won't be enough to compromise the system.

The kernel feature we use for this is called “unprivileged user namespaces”. Although it has been in Linux for a while, some distributions don't support it because they rely on older kernels, or they disable it because of security concerns. Although we don't want to take a position on the latter, obviously if the feature is available, Firefox might as well make use of it to make itself more secure. The Sandbox section of about:support will tell you whether it is supported on your distribution or not. If it isn't, you are still secure, just missing one of the extra hardening layers.

The one exception to the network policy, for now, is the X11 protocol which is used to display graphics and receive keyboard/mouse input. Content processes don't need most of its functionality, but they still have some dependencies on it. Hardening work on X11 is ongoing and will be addressed in future releases.

Developer information about Unprivileged User Namespaces:


User namespaces allow a process to behave as if it were root in a restricted subset of the system by granting it extra capabilities. Firefox uses the thus gained CAP_SYS_CHROOT capability to chroot() the content processes into an empty directory, thereby blocking their view of the real filesystem. Using user namespaces avoids the need to install a setuid root binary to achieve this.

Unprivileged user namespaces had some security bugs in their initial Linux implementation, and some Linux distribution maintainers are still wary of keeping them enabled. The problem is that although the process behaves as if it were root in its own namespace, at many levels in the kernel checks must be done to ensure it cannot do things that it couldn't do in its original namespace, where it is not root. There have been some calls to rework the feature to reduce the possibility of errors in this regard.

In this context, we'd like to remark that an application like Firefox only needs CAP_SYS_ADMIN, CAP_SYS_CHROOT, CAP_SET(UG)ID inside the namespace to achieve most effect, and specifically does not require the CAP_NET_ADMIN permission that has been proven rather bug prone in the past.



15 comments:

  1. Wouldn't it be worth to provide a setuid shim for downstreams that don't allow user namespaces but build their own Firefox? (like, totally randomly chosen, Debian)

    ReplyDelete
    Replies
    1. Actually... I checked the kernel configuration and CONFIG_USER_NS *is* set to `y`. Yet, Firefox doesn't use user namespaces. I wonder what's up with that.

      Delete
    2. I've been pointed to: https://sources.debian.org/src/linux/4.16.5-1/debian/patches/debian/add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch/
      so it's enabled in the kernel, but disabled via /proc/sys/kernel/unprivileged_userns_clone

      Delete
    3. It would be nice to have, but installing a suid root binary in order to give more defense in depth is right now not terribly appealing work compared to other things we need to do.

      Of the more popular Linux distros, only Arch Linux ships with user namespaces entirely disabled. As you found out, Debian has them behind a sysctl.

      Delete
    4. > Of the more popular Linux distros, only Arch Linux ships with user namespaces entirely disabled

      We've been shipping them enabled with that very same sysctl patch for a while now.

      Delete
  2. reduce the margin for error
    --->
    increase the margin for harmless error
    or
    reduce the possibility of errors
    ?

    ReplyDelete
  3. Would Wayland builds take avoid the X11 protocol concerns you reference, or do they just come with their own new sandboxing issues? I've been trying out wayland firefox builds from some patched versions of firefox, and they seem to be working well. I can't wait for a supported wayland build.

    ReplyDelete
    Replies
    1. My understanding is that just running a Wayland server sidesteps many of the issues because it doesn't allow applications to indiscriminately muck around with others' windows.

      It's exactly this security limitation that caused some backwards compatibility issues and caused Ubuntu to revert to X in 18.04.

      But yes, Wayland improves things here a lot.

      Delete
  4. "In this context, we'd like to remark that an application like Firefox only needs CAP_SYS_ADMIN, CAP_SYS_CHROOT, CAP_SET(UG)ID to achieve most effect"

    Is this a joke? If so, it's not funny :(

    https://lwn.net/Articles/486306/
    https://forums.grsecurity.net/viewtopic.php?f=7&t=2522

    and Solar Designer (Openwall.com)

    http://www.openwall.com/lists/oss-security/2010/11/08/3

    Do you still claim that it improves security?

    ReplyDelete
    Replies
    1. I think there's some misunderstanding here. We talk about the capabilities in the context of a user namespace. They're not applied to the Firefox process itself (in the original namespace).

      Once the content process has used the capabilities inside its own namespace, it can drop them again.

      Thus, the security considerations you link to are largely not relevant here. Most of the recent controversy of user namespaces has been due to kernel bugs that allow capabilities to leak to the original namespace, but that's not what those threads talk about.

      Delete
    2. OK I understand. You wrote:

      "Firefox uses the CAP_SYS_CHROOT capability to chroot() the content processes into an empty directory, thereby blocking their view of the real filesystem. Using user namespaces avoids the need to install a setuid root binary to achieve this. "

      And then:

      "In this context, we'd like to remark that an application like Firefox only needs CAP_SYS_ADMIN, CAP_SYS_CHROOT, CAP_SET(UG)ID to achieve most effect"

      One can understand that the main process has all these capabilities. So the correct statement is that firefox uses only CAP_SYS_CHROOT in the main namespace, and then only CAP_SYS_ADMIN, CAP_SET(UG)ID in unprivileged user namespaces.

      Delete
    3. No, we don't use any capabilities in the original namespace. Once it creates a new namespace, the process holds *all* capabilities in the new namespace regardless of what it had outside. Of these, we only require a few, which we drop after the chroot.

      Some additional security layers (see the comment below), as well as much discussion around user namespaces, talks about restricting the set of capabilities the process would get in a new namespace (so it doesn't get everything, which in *theory* is harmless, but in practice has pointed out kernel bugs). I pointed out what we require to give some guidance to kernel developers and the people making security profiles what could be sensible to allow for a "normal" application like Firefox that wants to sandbox itself.

      I'll try to reword the text a bit to address the nuance.

      Delete
  5. It seem like CAP_SYS_PTRACE is also needed now. Those changes to the sandboxing impacted the Apparmor profile as shipped by Ubuntu (disabled by default): https://bugs.launchpad.net/ubuntu/+source/firefox/+bug/1770600

    ReplyDelete
    Replies
    1. Thanks, this is probably required by the crash reporting tool.

      Delete