Discussion:
[tor-dev] Call For Testing: Capsicum Integration With Tor
Shawn Webb
2017-10-17 17:01:33 UTC
Permalink
Tor Capsicum Call For Testing (CFT)
===================================

Capsicum is a capabilities framework for FreeBSD and its derivatives.
It's commonly used to implement sandboxing. Tor currently supports
sandboxing only on Linux, via seccomp-filter. This CFT presents initial
Capsicum support for Tor on FreeBSD and HardenedBSD. The work
performed is sponsored by HardenedBSD.

The source for the Capsicum work can be found at
https://github.com/lattera/tor. The branch to use is the
hardening/capsicum branch. We hope that this implementation, or a
future revision of it, will be merged upstream by the Tor Project.

Design and Architecture
-----------------------

When capabilities mode (capmode) is entered (ie, the sandbox is
enabled), the kernel will prevent Tor from accessing the global
namespace. This means that once the sandbox is enabled, Tor will not
be able to open files, create sockets, connect outbound, etc.

Naturally, applications like Tor needs to be able to create sockets
on-demand and at-will. In these situations, it is common to fork a
child process which will perform these "privileged" operations. Only
the parent process will enter capmode. Communication between the
parent and the child is performed via a socketpair descriptor.

Wrappers in the parent process call into the child process to perform
these privileged operations. Thus, open(2) becomes sandbox_open(),
rename(2) becomes sandbox_rename(), and so on. A full list of wrapped
operations will be provided further on.

When the parent process wants to open a file, it will call
sandbox_open. The parent process will tell the child via the
socketpair to open the file and limit its capabilities. On success,
the child will return the limited file descriptor back to the parent.

We prevent race conditions surrounding the limitation of file
descriptors by calling cap_rights_limit(2) on the descriptor in the
child before passing the descriptor back to the parent. By the time the
parent can make use of the descriptor, the descriptor is fully limited
to a minimal set of capabilities.

Tor's existing sandbox abstraction API relies on a filtering-based
approach. We've utilized parts of that API to provide a basic
whitelist. Once capmode is entered, the whitelist turns read-only and
cannot be modified.

Efforts to apply Capsicum in the form of wrappers, such as has been
done in this work and others, require ASLR and W^X to be effective.
Without ASLR, an attacker could simply craft an exploit to return into
the respecive wrapper and bypass any guarantees Capsicum provides.
Additionally, Control Flow Integrity (CFI) from clang/llvm will
provide forward-edge guarantees. SafeStack from clang/llvm will
provide backward-edge guarantees.

Known Issues
------------

Enabling the sandbox while having Tor configured in transparent proxy
mode is currently broken. We are researching what causes the breakage.
Chances are that either Tor is trying to access the global namespace in
transparent proxy mode or one or more file descriptors simply need to
be granted one or more extra capabilities.

Future Work
-----------

We plan to research and fix, if possible, the known regression
regarding transparent proxying.

The read-only nature of the whitelist is only enforced via a logic
operation. We plan to relocate the whitelist into a memory mapping
that will turn read-only upon entering capmode.

The current implementation should be further abstracted in order for
Tor to be able to pick at runtime the appropriate sandbox
implementation. This would be similar to how Tor chooses which ed25519
implementation to use, donna or ref10.

Testing and Reporting Back
--------------------------

1. Install required development tools:

# pkg install libevent autoconf automake autotools libtool gmake \
git-lite

2. Clone the git repo:

# git clone https://github.com/lattera/tor.git

3. Check out the hardening/capsicum branch:

# cd tor
# git checkout -b hardening/capsicum origin/hardening/capsicum

4. Regenerate autoconf magic:

# ./autogen.sh

5. Run the configure script:

# ./configure [custom arguments to configure as you'd prefer]

6. Build and install:

# gmake -j$(sysctl -n hw.ncpu) && gmake install

7. Enable the sandbox in the torrc:

# echo "Sandbox 1" >> [path to torrc]

8. Run Tor:

# tor

9. Report results:

Email ***@hardenedbsd.org, report back any issues you may have.
If your testing succeeds, I'd like to hear about it, too. Please do
not open any tickets regarding this work on the Tor Project's Trac
instance. Contact me directly.

A sample report back would include a sanitized torrc along with a
pass/fail result. A successful result would mean that all features you
rely on work as desired. A failed result would mean that enabling a
feature results in Tor crashing, erroring out, or exhibiting bugs. If
Tor crashes for you, please include a backtrace if possible.

New Sandbox Wrappers
--------------------

These APIs will need to be used regardless of operating system. On
operating systems outside of FreeBSD and HardenedBSD, they are simply
macros that forward to their respective native API call.

* int sandbox_close(int fd): close(2) wrapper
* int sandbox_rename(const char *from, const char *to): rename(2) wrapper
* int sandbox_stat(const char *path, struct stat *sb): stat(2) wrapper
* int sandbox_mkdir(const char *path, mode_t mode): mkdir(2) wrapper
* int sandbox_connect(int sockfd, const struct sockaddr *name, socklen_t namelen): connect(2) wrapper
* int sandbox_socket(int domain, int type, int protocol, cap_rights_t *rights): socket(2) wrapper
* int sandbox_unlink(const char *path): unlink(2) wrapper
* int sandbox_open(const char *path, int flags, mode_t mode, cap_rights_t *rights): open(2) wrapper
--
Shawn Webb
Cofounder and Security Engineer
HardenedBSD

GPG Key ID: 0x6A84658F52456EEE
GPG Key Fingerprint: 2ABA B6BD EF6A F486 BE89 3D9E 6A84 658F 5245 6EEE
Shawn Webb
2017-10-18 17:31:41 UTC
Permalink
Hey All,

This is a brief update.
Post by Shawn Webb
Known Issues
------------
Enabling the sandbox while having Tor configured in transparent proxy
mode is currently broken. We are researching what causes the breakage.
Chances are that either Tor is trying to access the global namespace in
transparent proxy mode or one or more file descriptors simply need to
be granted one or more extra capabilities.
In discussions with a FreeBSD developer, the whitelist methodology for
filesystem access that Tor uses and that I adopted isn't as strong as it
could be. An attacker could potentially get around the whitelist scheme
as currently implemented.

Instead, the code will be rewritten to pre-open expected directories
when Tor starts up, and utilize openat(2) to open file descriptors. We
can utilize the existing whitelisting API to perform that work, since
the whitelisting API is called prior to entering capmode.

We will keep the sandbox_open abstraction, since that will do the work
of matching up with directory descriptor matches the requested path.
Post by Shawn Webb
Future Work
-----------
The read-only nature of the whitelist is only enforced via a logic
operation. We plan to relocate the whitelist into a memory mapping
that will turn read-only upon entering capmode.
This is nullified by the statement above.
Post by Shawn Webb
The current implementation should be further abstracted in order for
Tor to be able to pick at runtime the appropriate sandbox
implementation. This would be similar to how Tor chooses which ed25519
implementation to use, donna or ref10.
This is mostly done. The FreeBSD/Capsicum side is done. However, the
Linux/seccomp-filter side needs to be integrated.

Thanks,
--
Shawn Webb
Cofounder and Security Engineer
HardenedBSD

GPG Key ID: 0x6A84658F52456EEE
GPG Key Fingerprint: 2ABA B6BD EF6A F486 BE89 3D9E 6A84 658F 5245 6EEE
Loading...