[tbb-dev] Sandboxing Tor Browser - A New Beginning (?)

Matthew Finkel matthew.finkel at gmail.com
Tue Jul 3 18:03:07 UTC 2018

Hi All,

This is the beginning of a conversation about creating a plan for moving
towards sandboxing Tor Browser on every platform. Over the last few years,
there existed a Sandboxed Tor Browser on only Linux[0] (created and maintained
by Yawning Angel). However, Tor Browser aims at providing a Private Browser on
all supported platforms (Microsoft Windows, Apple Mac OS X, GNU/Linux, and
Android (AOSP))[1][2], this means we must provide a sandboxed run-time environment on
all platforms. Unfortunately, each operating system provides a unique set of
sandboxing techniques and capabilities, so we must work with the facilities we
are given. In some cases, we may need to be creative about how we achieve our

I do not have all the answers, and there are some open questions below.

On Windows, we have the Windows integrity mechanism[3], Windows Containers[4],
SetProcessMitigationPolicy[5], App Container[6], and maybe some others. Some
of this functionality is already used by Firefox.

On Mac OS X, there are two sandboxing techniques available. The first is
Seatbelt[7]. Apple deprecated it in favor of code signing entitlements[8].
Unfortunately, the code signing entitlements are not as fine-grained as
those Seatbelt provides, but we can enable different entitlements per
"target"[9]. I don't know if this will be difficult for us. Therefore, we
should utilize the code-signing restrictions where they are appropriate, but
we should follow Safari[10], Chromium[11], and Firefox[12][13] by applying
restrictive Sealtbelt policies where applicable.

On GNU/Linux, we can use the namespacing and secure computing (Secure
Computing) facilities in the kernel exposed to userspace. Sandboxed Tor Browser
on Linux already shows how these can be combined and form a sandbox. In
particular, we can use bubblewrap[14] as a setuid sandboxing helper (if user
namespace is not enabled), if it is available. In addition, we can reduce the
syscall surface area with Seccomp-BFP. CGroups provide a way for limiting the
resources available within the sandbox. We may also want to manually
proxy/filter other system functionality (X11).

Last, but not least, on Android, we begin with a fairly strict sandbox provided
by its permissioning model[15], distinct per-app users, and SELinux policies.
Because every app is run using a distinct user, and each has its own storage
directories, we get Linux's DAC on the file system for "free". In addition, we
can use some of the same techniques available on GNU/Linux on Android, namely
the seccomp-bpf and namespaces, if they are available. Android provides
privilege and permission isolation within an App by using Services. With some
refactoring, we can isolate some parts of Firefox into isolated permissionless

I'll begin by describing the goals, as I see it, for sandboxing Tor Browser.
Hopefully, this will help us evaluate the different available techniques. These
goals are derived from the Design document[16] and are the means for archieving
Tor Browser's end-goal.

In particular, the sandboxing techniques preserve the Security Requirements of
a private browser when the browser, itself, fails at maintaining those
criteria. By this I mean the sandbox should be designed such that if the
browser process loses any of the Security properties (through a logical bug,
exploited vulnerability, etc), the sandbox provides an additional layer of
those properties and the user is not in immediate danger. The sandbox may, in
some situations, improve the Privacy properties of Tor Browser, for example if
a component/device is emulated instead of providing the browser with raw
access. We should use these mechanisms when they are available.

1) Proxy Obedience
2) State Separation
3) Disk Avoidance
4) Application Data Isolation
5) Secure Updating
6) Usable
7) Cross-Origin Fingerprinting Unlinkability

We'll go through these one-by-one and describe the role of a sandbox and how we
can achieve this on each platform. Note, this design assumes a launcher-based
sandboxed architecture (similar to the Sandboxed Tor Browser on Linux):

                      |    Launcher    |
                 |            |               |
                 |            v               |
                 |     ----------------       |
                 v     |  Sandbox    |        v
    -----------------  | ----------- |    -----------------
    |   Sandbox     |  | | Broker  | |    |   Sandbox     |
    | ------------- |  | ----------- |    | ------------- |
    | |  Firefox  | |  ---------------    | |    Tor    | |
    | ------------- |------/    \_________| ------------- |
    -----------------          Controller -----------------
                         Proxy IPC

Note, the sandboxed broker process (or processes) moves some functionality from
the launcher process into a child process. This process is not as heavily
sandboxed as the Firefox and Tor process, but, for example it would not need
networking. This process would handle sending NEWNYM, provide a circuit display,
change bridge configuration (general controller functions). In addition, it would
handle copying files into and out of the Firefox sandbox, as an example.

Unfortunately, there is not an existing cross-platform solution for this design.
We can take bits-and-pieces from other solutions, creating this will require
engineering effort.

1) Proxy Obedience

The last line of defense against a proxy-bypass is a mechanism for dropping all
outgoing IP packets from the browser that are:
  - not TCP
  - or TCP but not destined for the Tor proxy port (SOCKS or HTTP)
  - or all packets (including TCP) if the proxy listener is not a TCP port
    (Unix domain socket, named pipe, etc)

We should also consider guarding the creation of all non-Unix domain sockets
and non-named pipes with a pref. I believe sandboxing should be optional, but
enabled by default (at least with first few versions), so excluding that code
at compile-time is not an option.  However, a pref-guard only stops unintended
proxy-bypass through normal control flow. This only slightly increases the
difficulty of some exploit methods.

Per-platform sandboxing techniques:
  a) Microsoft Windows
    i) Windows 8+
      If the user can elevate for administrator permissions, then the launcher
        - install a network filter using the Windows Filter Platform[17]. This
          can deny any connection from any process (based on the process's
          fully-qualified file name)[18]. This adds some risk because if the
          launcher process exits unexpected for whatever reason, the firewall
          rule may remain in place.
    ii) Windows 10
      We can create a new network namespace[19] using the (undocumented) HNSCall
      procedure[20]. This is very appealing.
    iii) Windows 7+
      If the platform is Windows 8+ and the user cannot elevate to
      Administrator or if the platform is Windows 7:
        - TODO: can/should we use DLL injection of WinSocks and manually
          filter all proxy-bypass network connections? Is there something we
          can use for mitigating ROP gadgets within the sandbox?

  b) Mac OS X
    i) We can restrict network access using the
       com.apple.security.network.client and com.apple.security.network.server
    ii) We can further restrict which types of connections the browser is
       allowed. Previously, there was a seatbelt profile for Tor Browser[22],
       but it is not usable with newer versions of the browser. We can
       continue using it for only allowing access requests for Unix domain
       sockets, and denying all other network connections.

  c) GNU/Linux
    i) On Linux, significant progress was already made in terms of sandboxing
       Tor Browser. There are two methods we can use:
         - Isolated network namespace via bubblewrap[14]
         - Seccomp-BPF on socket syscalls
    ii) If bubblewrap is not available, we can fallback on using unshare if it
        is available and user namespace is enabled
    iii) If user namespaces are not avialable, we ask the user for elevated
         privileges and manually fork into the new network namespace

  d) Android
    i) We can use the same (or similar) Seccomp-BPF filter that we use on Linux
    ii) We can move the Gecko service into an isolated process without any
        permissions (including Networking).
    iii) If all networking goes through Necko, and Neck is in the isolated
         process, then the remaining code, outside the isolated process, should
         be proxy-safe or it is the tor process.

2) State Separation

Per-platform sandboxing techniques:
  a) Microsoft Windows
    i) I'm not sure if there is more we can do here.

  b) Mac OS X
    i) The Seatbelt profile[22] can restrict access to all other Firefox
    ii) The Seatbelt profile can only allow access for bundled libraries
    iii) We may exclude entitlements for most system services

  c) GNU/Linux
    i) We can create new IPC, mount, and uts namespaces
    ii) We can provide a clean environment
    iii) The new mount namespace contains only the required bundled libraries
         required for running
    iv) D-Bus/I-Bus access would be nice, if we can do it safely.

  d) Android
    i) All apps are isolated by default, so there should never be shared state.
    ii) Ensure we have the smallest set of intent filters we need
    iii) Ensure we have the smallest set of exported components we need
    iv) Ensure we have the smallest set of broadcast receivers we need
    v) Ensure we only use Broadcast intents where it is necessary
    vi) Is there something else we should investigate here?

3) Disk Avoidance
In general, I'd like #7449 mitigated.

Per-platform sandboxing techniques:
  a) Microsoft Windows
    i) Windows 10+
      - On very recent versions of Windows, we can create temporary filesystem
        Layers[23][24]. I'm not sure if these are memory-backed or
      - We can create a read-only layer over the installation directory
        - #18367 may be useful (side-by-side user/app data on Windows)
      - Can we can isolate the container from system services?

  b) Mac OS X
    i) We can use entitlements[25]
    ii) The Seatbelt profile[22] provided additional access restrictions.
    iii) Is there a filesystem layering mechanism available in OS X (like tmpfs in Linux)?
      - Specifically, if we can use this for ~/Library/Caches/TemporaryItems and ~/Downloads

  c) GNU/Linux
    i) We can create new IPC, mount, and uts namespaces
    ii) #18369 may be useful (side-by-side user/app data on Linux)

  d) Android
    i) The app is self-contained by default
    ii) Need #26574
    iii) Additional auditing required

4) Application Data Isolation
I'll claim the per-platform sandboxing techniques are the same as Disk

5) Secure Updating
Nearly the same sandboxing techniques can be used on all platforms. A
launcher-component (maybe not the launcher, but a reduced-privileged process,
not the browser) downloads the update. Next, on download completion, a
launcher-component verifies the download and installs it (I can't justify
verifying the download in an unprivileged, sandboxed process - I'd like to do
it, but I don't see a benefit).

  a) Microsoft Windows
    i) Layer read-only filesystem on top of install dir, prevents presistant

  b) Mac OS X
    i) Seatbelt profile prevents write access of app binaries

  c) GNU/Linux
    i) Mount namespace provides read-only access of install dir
    ii) Mount namespace does not include launcher binaries

  d) Android
    i) If App was installed using a App Store, then that is responsible for
    ii) If the app was installed by the user (side-loaded), then the we can
        isolate downloading into a separate process, and then verification
        can be handled in an isolated process. Finally, the Android Package
        Manager controls installing the update.

6) Usable

Unfortunately, despite the above suggestions, this sandboxing model fails if
users find its unusable. In particular, with temporary file systems, we should
provide a method for safely extracting a file from the temporary location and
copying it to a permanent location using the launcher process. In addition,
exposing operating system functionality which may be fingerprintable and/or
another attack vector should be optional if it unbreaks the web (such as
providing pulseaudio on Linux[26]). As usual. we must be careful about
giving users too many customizable switches.

7) Cross-Origin Fingerprinting Unlinkability

I've less experience here on non-Linux OS (and Sandboxed Tor Browser is
already a good base on Linux). Which other components should we consider
spoofing (if possible) or go out of our way and disallow access (if not
possible using the above means)?

[0] https://trac.torproject.org/projects/tor/wiki/doc/TorBrowser/Sandbox/Linux
[1] https://www.mozilla.org/en-US/firefox/60.0esr/system-requirements/
[2] https://support.mozilla.org/en-US/kb/will-firefox-work-my-mobile-device
[3] https://msdn.microsoft.com/en-us/library/bb625963.aspx
[4] https://github.com/Microsoft/dotnet-computevirtualization/blob/master/src/Microsoft.Windows.ComputeVirtualization/Hcs.cs#L130
[5] https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-setprocessmitigationpolicy
[6] https://docs.microsoft.com/en-us/previous-versions/windows/apps/hh464936(v=win.10)
[7] https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AboutAppSandbox/AboutAppSandbox.html
[8] https://help.apple.com/xcode/mac/current/#/dev88ff319e7
[9] https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW1
[10] https://trac.webkit.org/browser/webkit/releases/Apple/Safari%2011.1.1/WebKit/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in
[11] https://www.chromium.org/developers/design-documents/sandbox/osx-sandboxing-design
[12] https://wiki.mozilla.org/Security/Sandbox#OSX
[13] https://dxr.mozilla.org/mozilla-central/source/security/sandbox/mac/SandboxPolicies.h
[14] https://github.com/projectatomic/bubblewrap
[15] https://developer.android.com/reference/android/Manifest.permission
[15] https://developer.android.com/guide/topics/manifest/service-element#isolated
[16] https://www.torproject.org/projects/torbrowser/design/
[17] https://docs.microsoft.com/en-us/windows/desktop/FWP/windows-filtering-platform-start-page
[18] https://docs.microsoft.com/en-us/windows/desktop/FWP/permitting-and-blocking-applications-and-users
[19] https://docs.microsoft.com/en-us/virtualization/windowscontainers/container-networking/architecture
[20] https://github.com/Microsoft/hcsshim/blob/master/internal/hns/namespace.go#L61
[21] https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW9
[22] https://gitweb.torproject.org/builders/tor-browser-build.git/tree/projects/tor-browser/Bundle-Data/mac-sandbox?h=tbb-7.5.6-build4
[23] https://github.com/Microsoft/hcsshim/blob/master/internal/wclayer/createlayer.go#L10
[24] https://github.com/Microsoft/hcsshim/blob/master/internal/wclayer/createscratchlayer.go
[25] https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24
[26] https://trac.torproject.org/projects/tor/wiki/doc/TorBrowser/Sandbox/Linux#HowdoIgetsoundtowork

More information about the tbb-dev mailing list