首页
论坛
专栏
课程

[原创]Android security protection overview

2019-10-8 13:20 3974

[原创]Android security protection overview

2019-10-8 13:20
3974


  In recent years, Android phone becomes widely used in the world. At the same time, security becomes more and more important. One of the most important interfaces in security which would expose to outside world is root. In the more and more vehement completion, three kinds of directions in root also becomes stronger. They are mitigation, bypass mitigation mechanism and exploit tricks. Perhaps we should think it over, it is very different from the other techniques which would be out of date. Root security skills can be closed related all the time. In other words, some innovative techniques can revive older skills and will be very convenient to use. Geek also demonstrate brilliant techniques with every-time-period mechanism. I'll elaborate that as well. Therefore I will write it  with four parts. One is android security mitigation, the second is to bypass mitigation, the third one is exploit tricks and last one is detecting exploits. They are the most important features we must know as a security researcher. It is noticeable that I mainly focus on the kernel security and introduce a small amount of knowledge on user mode as we know complete root in android phones cannot live without kernel and user-mode root has a few privileges. I have summarized some latest mitigation in general.


DAC

  We know android is based on linux kernel. So the kernel security is also based on linux kernel security. Briefly, DAC allows the owner of an object (such as a file) to set the security policy for that object—which is why it’s called a discretionary scheme.  As a user, you can, for example, create a new file in your home directory and decide who else may read or write the file.  This policy is implemented as permission bits attached to the file’s inode, which may be set by the owner of the file.  Permissions for accessing the file, such as read and write, may be set separately for the owner, a specific group, and other (i.e. everyone else). This is a relatively simple form of access control lists (ACLs). There is also a superuser—an all-powerful entity which bypasses Unix DAC policy for the purpose of managing the system. Running a program as the superuser provides that program with all rights on the system. That is fatal weakness for the DAC mechnism.

At the same time, accesses to sources are also not coverd such as network packet flows. So here comes POSIX Capabilities, the aim of the feature is to break up the power of the superuser, so that an application requiring some privilege does not get all privileges. It's possible to reduce the number of setuid applicatons on the system by assigning specific capabilities to them, however, some capabilities are very coarse-grained and effectively provide a great deal of privilege.

SELinux

       Security Enhanced Linux (SELinux) is an implementation of fine-grained Mandatory Access Control (MAC) designed to meet a wide range of security requirements, from general purpose use, through to government and military systems which manage classified information.  MAC security differs from DAC in that the security policy is administered centrally, and users do not administer policy for their own resources.  This helps contain attacks which exploit userland software bugs and misconfiguration.

       In SELinux, all objects on the system, such as files and processes, are assigned security labels.  All security-relevant interactions between entities on the system are hooked by LSM and passed to the SELinux module, which consults its security policy to determine whether the operation should continue.  The SELinux security policy is loaded from userland, and may be modified to meet a range of different security goals.  Many previous MAC schemes had fixed policies, which limited their application to general purpose computing. In android 6.0, it even opens Mutil-Level Security option which makes segmentation of a single object more granular. It is important that it even prevents normal user from accessing the device directories.


Seccomp

       Secure computing mode (seccomp) is a mechanism which restricts access to system calls by processes.  The idea is to reduce the attack surface of the kernel by preventing applications from entering system calls they don’t need.  The system call API is a wide gateway to the kernel, and as with all code, there have and are likely to be bugs present somewhere.  Given the privileged nature of the kernel, bugs in system calls are potential avenues of attack.  If an application only needs to use a limited number of system calls, then restricting it to only being able to invoke those calls reduces the overall risk of a successful attack.

       The original seccomp code, also known as “mode 1”, provided access to only four system calls: read, write, exit, and sigreturn.  These are the minimum required for a useful application, and this was intended to be used to run untrusted code on otherwise idle systems.

       A recent update to the code allows for arbitrary specification of which system calls are permitted for a process, and integration with audit logging.  This “mode 2” seccomp was developed for use as part of the Google Chrome OS.

PXN

       PXN is set by changing the bit attribute. PXN bit on every permission template for user-space, as well as UXN/PXN bits for non-executable pages. This makes sure that every user-space page is mapped with PXN bit set, which mitigates ret2usr attack. Ret2usr (return-to-user) attack exploits the truth that the code in kernel mode (high memory) can execute the code in user mode (low memory). PXN is kernel protection against ret2usr attack. If the CPU is running in the kernel mode, executing a code in user space will trigger a page fault. It is just similar to SMEP in linux. Keep in mind that PXN bits are set in user virtual address space, which means they are dynamically allocated, so unlike kernel ones, you will need a good kernel read bug to locate the entry to be manipulated. Usually with both read and write, there is really no need of code execution. So this is not very practicable in real exploit.

PAN

       PAN means it prevents privileged kernel access to user data. There's software-based PAN implementation for armv7 with config CPU_SW_DOMAIN_PAN and arm64 with config CONFIG_ARM64_SW_TTBR0_PAN. It increases kernel security by ensuring that normal kernel accesses are unable to access userspace addresses.  This can help prevent use-after-free bugs becoming an exploitable privilege escalation by ensuring that magic values (such as LIST_POISON) will always fault when dereferenced. It is the part of ARMv8.1 Extensions that adds bit PSR_PAN_BIT to control with the config ARM64_PAN. As we see software-based PAN implementation is common in arm64, so we have detailed description about it.

       Register ttbr0_el1 stores the user page table. In __uaccess_ttbr0_disable, if we disable the ttbr0_el1, then we cannot access the usermod and the right usermod page table base addr is stored in thread_info. On the other hand, uaccess_ttbr0_enable can recover ttbr0_el1 from thread_info, then we can access user page table from kernel state, PAN is disabled. Only open the attribute in copy_from_user and copy_to_user, kernel_entry and kernel_exit. It is sure that ttbr0_el1 is also stored in coprocessor.

Kernel Address Space Layout Randomization (KASLR)

       Android has included support for Address Space Layout Randomization (ASLR) for years. Randomizing memory layout makes code reuse attacks probabilistic and therefore more difficult for an attacker to exploit, especially remotely. Android 8.0 brings this feature to the kernel. While Linux has supported KASLR on x86 since version 3.14, KASLR for ARM64 has only been available upstream since Linux 4.6. Android 8.0 makes KASLR available in Android kernels 4.4 and newer.

       KASLR helps mitigate kernel vulnerabilities by randomizing the location where kernel code is loaded on each boot. On ARM64, for example, it adds 13–25 bits of entropy depending on the memory configuration of the device, which makes code reuse attacks more difficult.

Hardened usercopy

 

       Usercopy functions are used by the kernel to transfer data from user space to kernel space memory and back again. Since 2014, missing or invalid bounds checking has caused about 45% of Android's kernel vulnerabilities. Hardened usercopy adds bounds checking to usercopy functions, which helps developers spot misuse and fix bugs in their code. Also, if obscure driver bugs slip through, hardening these functions prevents the exploitation of such bugs.

Post-init read-only memory

       The final hardening feature extends existing memory protections in the kernel by creating a memory region that's marked read-only after the kernel has been initialized. This makes it possible for developers to improve protection on data that needs to be writable during initialization, but shouldn't be modified after that. Having less writable memory reduces the internal attack surface of the kernel, making exploitation harder.

       Post-init read-only memory was introduced in upstream kernel version 4.6 and we have backported it to Android kernels 3.18 and newer. While we have applied these protections to some data structures in the core kernel, this feature is extremely useful for developers working on kernel drivers. This measure is just a mitigation of dirtycow bug which exploits the android device using the way of vdso.    

Integrity Management

       A simpler approach to integrity management is the dm-verity module.  This is a device mapper target which manages file integrity at the block level.  It’s intended to be used as part of a verified boot process, where an appropriately authorized caller brings a device online, say, a trusted partition containing kernel modules to be loaded later.  The integrity of those modules will be transparently verified block by block as they are read from disk.

CONFIG_DEBUG_RODATA

       Linux kernel has utilized many features to harden the kernel. One of them is protecting critical memory zones like kernel text and non-volatile data. Recent Linux mainline kernel has this feature implemented through CONFIG_DEBUG_RODATA. It invokes mark_rodata_ro function to allocate a section page ahead of kernel text Kernel text starts relatively at a fixed location for most of the devices, so we can predict the beginning of this critical kernel data structure.

KNOX Active Protection

       TrustZone is an extension to ARM cores, which creates two “worlds”.  Although few restrictions are there that how vendor can utilize Trustzone, usually the feature-rich OS, aka Android, in our case, is going to run in the normal world. The secure world will be hosting trustlets on a light-weight OS.

       As a secure world running in parallel with the normal world, compromising the kernel in normal world shall not affect the secure world if the implementation was properly done, as their communication is handled by the privileged monitor mode code usually loaded by low-level bootrom. However, there are cases seen that secure world can also be compromised due to its own bug or bugs in monitor mode.

       Samsung has implemented TIMA(Trust Zone based Integrity Measurement Architecture) which can provide complete protection in real time. Even though an attack can compromise kernel and gain arbitrary read/write, he/she can still not load any kernel module for convenient kernel code execution.

        It also introduces TIMA protected page table and read-only kernel text/data into the kernel in Galaxy S5. In Galaxy S6/S6 Edge since 5.1.1, Samsung did not only protect the page table, but also put crucial kernel objects like credentials into consideration such as kmem_cache. If it is readable, this helps mitigating conventional DKOM exploit.

        Real-time kernel protection (RKP) is implemented in Trust Zone or hypervisor, depends on device model with the config CONFIG_TIMA_RKP CONFIG_RKP_DKP. It completely prevents kernel data running unauthorized privileged code and prevents kernel data from being directly accessed by user processes and monitors some critical kernel data structures to verify that they are not exploited by attacks.

       Its main function is rkp_call() which is called by many critical kernel functions than manages slab allocation and de-allocation, page table operations and copy/override/commit creds. It provides kernel data protection based on read only pages. Important data can be set read only after initialized. In previous version s6, just call rkp_override_creds() to override current process's credentials. This is not working in s7 and adds more checking.

       In knox 2.6, it adds verifying in rkp_override_creds() such as part of data flow integrity  and uid chek. Uid_checking is unprivileged process(uid>1000) cannot override the credential with high privilege (uid 0~1000). DFI(data flow integrity) with config CONFIG_RKP_DKP will check whether credential and task_struct is of own. We cannot manipulate credentials and security object in kernel mode, point current credential to init_cred and call rkp_override_creds function to ask secure world to help overide credential with uid(0~1000). It also has enhanced selinux. The init process and u:rinit:s0 is still limited by selinux and almost do nothing. It disables CONFIG_SECURITY_SELINUX_DEVELOP thus cannot disable selinux by override selinux_enforcing. Selnux is statically enforcing with removing the flag AVD_FLAGS_PERMISSIVE all the time. Init process cannot reload seliux poliy after system initialized and permissive domain is not allowed.

       In knox 2.8, there is more security than knox 2.6. The load_elf_binary function checks if uid<1000 and the bin file is not from / and /system directory, the kernel will panic. For the reason, we cannot invoke __orderly_poweroff function to start a kernel thread.

       Besides these “high-end” mitigations, Samsung also customized some syscalls to restrict post-exploit activities. Taking fork/execve as an example. These two are basically the underlying syscalls behind “system”, a very common routine an exploit will utilize after privilege escalation. So Samsung added some additional check in execve (fs/exec.c).

       For any root process, sec_restrict_fork() will check if it is originated from /data. In general, this directory is the only place that an user application can start in. Samsung is hoping that this can stop rooting applications from spawning new process, in most cases a daemon running as root. But since they failed to protect some critical data structures being used inside sec_restrict_fork(), bypassing this check if far easiler than bypassing a tz/hyp assisted protection.

Prevent pipe read and write

       YunOS, a customized Android ROM from Alibaba, one of the generic route we take for rooting is by modifying the addr_limit of current task’s thread_info structure. This allows the kernel to take the whole virtual address space (or sometimes just enough virtual address space) as “USER_DS” so read/write operation in the address range won’t be restricted for certain syscalls, like pipe_read and pipe_write. In the kernel of YunOS, YunOS added one additional ext_security_pre_check before actually heading into the syscall. The first basic block extracts addr_limit from current context and check against the standard USER_DS value, 0x8000000000 (1 << 39). If it is not the desired value, it will enforce a SIGKILL to the calling process. Since SIGKILL can’t be masked, the calling process will be forcibly killed (which may lead to a panic if in the middle of exploit).

CFI

       Google's Pixel 3 will be the first Android device to ship with LLVM's forward-edge Control Flow Integrity (CFI) enforcement in the kernel, and they have made CFI support available in Android kernel versions 4.9 and 4.14.

       A huge number of overwriting a function pointer to complete their exploit exists in mobile devices.CFI attempts to mitigate these attacks by adding additional checks to confirm that the kernel's control flow stays within a precomputed graph which just makes exploiting such a bug more difficult in practice.

       LLVM's CFI implementation adds a check before each indirect branch to confirm that the target address points to a valid function with a correct signature. This prevents an indirect branch from jumping to an arbitrary code location and even limits the functions that can be called

       In order to support loadable modules, they have implemented LLVM's cross-DSO CFI support in the kernel, including a CFI shadow that speeds up cross-module look-ups. When compiled with cross-DSO support, each kernel module contains information about valid local branch targets, and the kernel looks up information from the correct module based on the target address and the modules' memory layout.


       The following kernel configuration options are needed to enable kernel CFI:

       CONFIG_LTO_CLANG=y

       CONFIG_CFI_CLANG=y

       Using CONFIG_CFI_PERMISSIVE=y may also prove helpful when debugging a CFI violation or during device bring-up. This option turns a violation into a warning instead of a kernel panic. However, it hasn't adopted measures to protect function return addresses.

    In some devices like samsung, huawei, they just implemented simple KCFI. In every function end, they put a fixed value. When jumping to another function, firstly it jumps a fixed code and check whether the last code is at the start of a function. If yes, then jump into the right function in case that attacks abuse function pointer to exploit the device.


Reference:

https://www.linux.com/tutorials/overview-linux-kernel-security-features/

https://keenlab.tencent.com/en/2016/06/01/Emerging-Defense-in-Android-Kernel/

https://blog.quarkslab.com/attacking-the-arms-trustzone.html

http://c0reteam.org/2018/09/17/kcfi

https://events.linuxfoundation.jp/wp-content/uploads/2017/11/LSS2018.pdf

https://android-developers.googleblog.com/2018/06/compiler-based-security-mitigations-in.html

http://ne2der.com/2017/Hardening-the-Kernel-in-Android-Oreo/

https://connortumbleson.com/slides/2019-01-19-SecurityAndPieDevFest.pdf

https://react-juejin.foreversnsd.cn/post/5c753609f265da2d8b634dd2?pos=comment

https://struct.github.io/cross_dso_cfi.html

https://www.phoronix.com/scan.php?page=news_item&px=Clang-Kernel-2018

https://taesoo.kim/pubs/2016/song:kenali.pdf

https://android-developers.googleblog.com/2017/08/hardening-kernel-in-android-oreo.html

https://lwn.net/Articles/695991/

      

      

      

      

      



2020安全开发者峰会(2020 SDC)议题征集 中国.北京 7月!

最后于 2019-10-8 13:30 被LowRebSwrd编辑 ,原因:
最新回复 (2)
Editor 2019-10-8 13:42
2
0
全英文
挤蹭菌衣 2020-2-22 15:54
3
0
学习了  有点困难
游客
登录 | 注册 方可回帖
返回