[guardian-dev] CopperheadOS

Hans-Christoph Steiner hans at guardianproject.info
Mon Jan 4 14:02:23 EST 2016


Sounds like quite a project, that's some serious probing in the guts :-)
 I wonder if they would be interested in implementing our old idea of
using SQLCipher as the default SQLite implementation, and tying in the
per-app keys to the lockscreen.

.hc

Nathan of Guardian:
> 
> Thoughts? At first glance, it looks like a good mix of hardening and
> sensible defaults. It isn't quite fully locked down as MIA, but I can
> imagine using this as a starting point for something. I've also been
> chatting with them on Twitter about including Orfox and Orbot.
> 
> https://copperhead.co/docs/technical_overview
> 
> ****
> 
> Technical overview of CopperheadOS
> 
> This is a technical overview of the currently implemented features in
> CopperheadOS. For a list of planned features, see the issues tagged as
> enhancements on the tracker. The scope will be expanded as more features
> are implemented.
> 
> Exec-based spawning model
> 
> CopperheadOS spawns applications from the Zygote service in the
> traditional Unix way with fork and exec rather than Android’s standard
> model using only fork. This results in the address space layout and
> stack/setjmp canaries being randomized for each spawned application
> rather than having the same layout and canary values reused for all
> applications until reboot. In addition to hardening applications from
> exploitation, this also hardens the base system as the large, near root
> equivalent system_server service is spawned from the Zygote.
> 
> This required some workarounds due to code depending on the Zygote
> spawning model.
> 
> Bionic libc improvements
> 
> Hardened allocator
> 
> CopperheadOS replaces the system allocator with a port of OpenBSD’s
> malloc implementation.
> 
> Fine-grained randomization is performed for small allocations by
> choosing a random pool to satisfy requests and then choosing a random
> free slot within a page provided by that pool. Freed small allocations
> are quarantined before being put back into circulation via a randomized
> delayed allocation pool. This raises the difficulty of exploiting
> vulnerabilities by making the internal heap layout and allocator
> behavior unpredictable.
> 
> Unlike jemalloc, Android’s standard allocator, OpenBSD uses page-aligned
> regions instead of 2MiB aligned regions so it doesn’t lose any of the
> mmap randomization entropy. The standard allocator loses 9 bits of mmap
> entropy on systems with 4096 byte pages.
> 
> Small allocations are filled with junk data upon being released, as is
> the initial portion of large allocations. This eliminates many
> information leaks caused by lack of initialization and can make the
> exploitation of use-after-free and double free vulnerabilities more
> difficult. Full junk filling on free is available via a user-facing
> setting. Unlike OpenBSD, filling new allocations with junk data rather
> than either zeroes or the junk on free pattern is split out into a
> separate option (not exposed to users) as it’s much more of an
> auditing/debugging feature than a security one.
> 
> A user-facing setting is exposed for placing guard pages at the end of
> large allocations to prevent and detect overflows at the cost of higher
> memory usage and reduced performance. It may be enabled by default on
> 64-bit in the future. CopperheadOS also extends the allocator with
> support for canaries at the end of small allocations, mitigating small
> overflows and catching corruption upon free (this could potentially be
> upstreamed). This is disabled by default for now and exposed via a
> setting due to the memory usage cost.
> 
> A user-facing setting is exposed for enabling page cache memory
> protection to trigger aborts for use-after-free bugs. For small
> allocations, a whole page needs to be cleared out for it to happen, so
> CopperheadOS includes an extension providing enhanced use-after-free
> detection for all small allocations. It simply checks if the junk
> pattern used on free is still present when allocations are moved out of
> the delayed free array. This is also exposed via a user-facing setting.
> It may be extended further in the future.
> 
> The page span cache is also randomized. This avoids the introduction of
> determinism, but the value will be limited until a form of fine-grained
> randomization is added below the malloc layer like the mmap
> randomization on OpenBSD.
> 
> The allocator doesn’t use any inline metadata, so traditional allocator
> exploitation techniques are not possible. The configuration is made
> read-only at runtime and the rest of the global state is protected to
> some extent via randomization and canaries. CopperheadOS has some small
> extensions to improve the randomization and may do more in the future.
> 
> Extended _FORTIFY_SOURCE implementation
> 
> The _FORTIFY_SOURCE feature provides buffer overflow checking for
> standard C library functions in cases where the compiler can determine
> the buffer size at compile-time. In CopperheadOS, it also provides
> system calls with dynamic heap overflow checks by querying the allocator
> for allocation sizes. The dynamic checks will be extended in the future.
> 
> Copperhead has added fortified implementations of the following
> functions:
> 
> fread - upstreamed
> fwrite - upstreamed
> getcwd - upstreamed
> memchr - upstreamed
> memrchr - upstreamed
> pread - upstreamed
> pread64 - upstreamed
> pwrite - upstreamed
> pwrite64 - upstreamed
> readlink - upstreamed
> readlinkat - upstreamed
> realpath - upstreamed
> send - submitted upstream
> sendto - submitted upstream
> write - upstreamed
> Additionally, the dlmalloc API has been annotated with alloc_size
> attributes to provide buffer overflow checking for the remaining code
> using the extended API.
> 
> Some false positives in jemalloc were fixed in order to land support for
> write fortification in AOSP.
> 
> Function pointer protection
> 
> Writable function pointers in libc have been eliminated, removing
> low-hanging fruit for hijacking control flow with memory corruption
> vulnerabilities.
> 
> The at_quick_exit and pthread_atfork callback registration functions
> have been extended with the same memory protection offered by the atexit
> implementation inherited from OpenBSD.
> 
> The vDSO function pointer table is made read-only after initialization,
> as is the pointer to the function pointer table used to implement
> Android’s malloc debugging features. This has been upstreamed.
> 
> Mangling of the setjmp registers was implemented upstream based on input
> from Copperhead.
> 
> Miscellaneous improvements
> 
> Allocations larger than PTRDIFF_MAX are prevented, preventing a class of
> overflows. This has been upstreamed for mmap and mremap.
> 
> A dedicated memory region is created for mapping libraries, to isolate
> them from the rest of the mmap heap. It is currently 128M on 32-bit and
> 1024M on 64-bit. A randomly sized protected region of up to the same
> size is placed before it to provide a random base within the mmap heap.
> The address space is reused via a simple address-ordered best-fit
> allocator to keep fragmentation at a minimum for dynamically
> loaded/unloaded libraries (plugin systems, etc.).
> 
> Secondary stacks are randomized by inserting a random span of protected
> memory above the stack and choosing a random base within it. This has
> been submitted upstream.
> 
> Secondary stacks are guaranteed to have at least one guard page above
> the stack, catching sequential overflows past the stack mapping. The
> pthread_internal_t structure is placed in a separate mapping rather than
> being placed within the stack mapping directly above the stack. It
> contains thread-local storage and the value compared against stack
> canaries is stored there on some architectures.
> 
> Signal stacks were given guard pages to catch stack overflows. This was
> upstreamed.
> 
> Assorted small improvements:
> 
> have getauxval(…) set errno to ENOENT for missing values, per glibc 2.19
> - upstreamed
> name the atexit handler pages - upstreamed
> name the arc4random structure mappings - upstreamed
> fix the mremap signature - upstreamed
> implementations of explicit_memset and secure_getenv for use elsewhere
> replaced the broken implementations of issetugid and explicit_bzero
> larger default stack size on 64-bit (1MiB -> 8MiB)
> and more…
> PaX kernel
> 
> CopperheadOS has ports of the PaX kernel hardening patch to the
> supported devices. It may use a larger subset of grsecurity in the
> future, but most of the additional features over PaX are not usable on
> Android or are already provided in other ways. It would make more sense
> to extract only the useful features (PROC_MEMMAP, KSTACKOVERFLOW,
> HIDESYM, RANDSTRUCT, DEVICE_SIDECHANNEL, RWXMAP_LOG and maybe a few
> more) rather than maintaining a full port.
> 
> Userspace features
> 
> PaX’s userspace hardening features are all enabled. The RANDMMAP feature
> provides significantly stronger Address Space Layout Randomization
> (ASLR) than the vanilla kernel and eliminates the mmap address hint
> footgun. PAGEEXEC turns no-execute violations into fatal errors rather
> than recoverable ones. MPROTECT prevents runtime code
> modification/injection.
> 
> There are a few MPROTECT exceptions (mediaserver, mm-qcamera-app,
> mm-qcamera-daemon) for the base system to work around proprietary
> libraries that are not easily fixable. CopperheadOS contains a custom
> exception system for dealing with Android applications via group-based
> permissions and has package manager integration to set the permissions
> automatically. The package manager scans for calls to the WebView
> widget’s setJavaScriptEnabled method in an Android package’s bytecode
> and automatically adds MPROTECT exceptions as necessary. The remaining
> issues are dealt with using a hard-wired exception table in the package
> manager mapping application names like com.chrome.beta to a list of
> necessary exceptions. Very few of these manually made exceptions are
> required and more issues could be auto-detected in the future.
> 
> A toggle for soft mode is exposed in Settings -> Developer options along
> with a status entry in Settings -> About device displaying whether a PaX
> kernel is in use and the soft mode setting.
> 
> Kernel self-protection
> 
> Some kernel self-protection features are enabled (MEMORY_SANITIZE,
> REFCOUNT, USERCOPY) along with the baseline improvements without
> configuration options. KERNEXEC and UDEREF will be available for devices
> using the 3.10 kernel. The features implemented via compiler plugins
> have been tested and are work well, but the necessary changes to support
> them are unfinished and aren’t yet published.
> 
> Compiler hardening
> 
> Lightweight bounds checking for statically sized arrays via
> -fsanitize=bounds -fsanitize-trap=bounds.
> For some sub-projects, lightweight object size bounds checking is
> performed (including extended checks for arrays) via
> -fsanitize=object-size -fsanitize-trap=object-size. This has a lot of
> overlap with the bounds sanitizer, but the redundant checks are
> optimized out when both are set to trap on error. It would be nice to
> enable this globally, but there’s too much code relying on undefined
> out-of-bounds accesses.
> For some sub-projects, both unsigned and signed integer overflow
> checking via -fsanitize=integer -fsanitize-trap=integer (mostly
> backported from AOSP master).
> Stack overflow checking for supported architectures via -fstack-check
> (not on ARM yet due to a severe bug) - submitted upstream for the NDK
> Signed integer overflow is made well-defined via -fwrapv to avoid having
> incorrectly written overflow checks optimized out.
> Expanded stack overflow canaries to all relevant functions via
> -fstack-protector-strong for both the NDK and base system. It has also
> been upstreamed for both the NDK and base system.
> Added -Wsuggest-attribute=format warning to audit for missing format
> attributes - dozens of cases have been found and fixed, providing more
> coverage for warnings about exploitable format string bugs.
> _FORTIFY_SOURCE=2 is enabled for local usage of the NDK, since
> portability isn’t a concern.
> Enhanced SELinux policies
> 
> eliminated code injection holes
> removed gpu_device execute access
> removed ashmem execute access
> removed tmpfs execute access
> the remaining hole in full (not just in-memory) w^x is app_data_file
> execution, and the intention is to address this with a whitelisting
> model in the package manager similar to the handling of PaX exceptions
> removed mediaserver’s write access to sysfs
> Encryption
> 
> Full disk encryption is enabled by default on all supported devices, not
> just those shipping that way with the stock operating system.
> 
> Support for a separate encryption password
> 
> In vanilla Android, the encryption password is tied to the lockscreen
> password. That’s the default in CopperheadOS, but there’s full support
> for setting a separate encryption password. This allows for a convenient
> pattern, pin or password to be used for unlocking the screen while using
> a very strong encryption passphrase. If desired, the separate encryption
> password can be removed in favor of coupling it to the lockscreen
> password again.
> 
> When a separate encryption password is set, the lockscreen will force a
> reboot after 5 failed unlocking attempts to force the entry of the
> encryption passphrase. This makes it possible to use a convenient
> unlocking method without brute force being feasible. It offers similar
> benefits as wiping after a given number of failures or using a
> fingerprint scanner without the associated drawbacks.
> 
> Better defaults
> 
> The default settings have been altered to emphasize privacy/security
> over small conveniences.
> 
> Location tagging is disabled by default in the Camera app, and there is
> no longer a prompt about choosing whether to enable it on the first
> launch. It can still be enabled using the Camera’s settings menu.
> 
> passwords are hidden by default
> sensitive notifications are hidden on the lockscreen by default
> NFC and NDEF Push are disabled by default
> Browser:
> 
> DuckDuckGo as the default browser home page and search engine instead of
> Google
> link preloading in the browser is disabled by default
> search result preloading in the browser is disabled by default
> plugins are disabled by default (although there aren’t any around by
> default)
> Miscellaneous features
> 
> SQLite’s SECURE_DELETE feature is enabled, resulting in deleted content
> being overwritten with zeros. This prevents sensitive data from
> lingering around in databases after it’s deleted. SQLite is widely used
> by Android’s base system is the standard storage mechanism for
> applications, so this results in lots of coverage.
> 
> The hidepid=2 option is enabled for procfs, hiding processes owned by
> other UIDs. Since non-system apps each have a unique UID, this prevents
> apps from obtaining sensitive information about each other via /proc.
> There are exceptions for a few of the core services via the gid mount
> option (lmkd, servicemanager, keystore, debuggerd, logd, system_server)
> but not for apps. A subset of this was provided by SELinux, but it isn’t
> fine-grained enough. This enhancement was adopted upstream based on the
> implementation in CopperheadOS (it had been planned, but they were
> unaware of the gid mount option).
> 
> Some misuses of memset for sanitizing data were replaced with
> explicit_memset, to stop the compiler from optimizing them out.
> 
> Interfaces are given a random MAC address whenever they are brought up.
> This can be disabled via a toggle in the network settings.
> 
> The kernel TCP/IP settings are adjusted to prioritize security. A
> minimal firewall is provided with some options that are always sane.
> Support for IP sets is enabled in the kernel and the ipset utility is
> provided, but not yet integrated in an automated way. Android has
> group-based control over networking so basic controls over networking
> are in the realm of PrivacyGuard, but more advanced firewall features
> might be provided down the road.
> 
> Many global function pointers in Android’s codebase have been made
> read-only. This is ongoing work and will need to be complemented with
> Control Flow Integrity (CFI) as many are compiler-generated. Some of
> this work has been upstreamed: 1, 2.
> 

-- 
PGP fingerprint: EE66 20C7 136B 0D2C 456C  0A4D E9E2 8DEA 00AA 5556
https://pgp.mit.edu/pks/lookup?op=vindex&search=0xE9E28DEA00AA5556


More information about the guardian-dev mailing list