Skip to content

Latest commit

 

History

History
482 lines (333 loc) · 29 KB

README.md

File metadata and controls

482 lines (333 loc) · 29 KB

KASLD logo generated with Stable Diffusion (modified)

Kernel Address Space Layout Derandomization (KASLD)

A collection of various techniques to infer the Linux kernel base virtual address as an unprivileged local user, for the purpose of bypassing Kernel Address Space Layout Randomization (KASLR).

Supports:

  • x86 (i386+, amd64)
  • ARM (armv6, armv7, armv8)
  • MIPS (mipsbe, mipsel, mips64el)
  • PowerPC (ppc, ppc64)
  • RISC-V (riscv32, riscv64)
  • LoongArch (loongarch64)

Usage

sudo apt install libc-dev make gcc binutils git
git clone https://github.com/bcoles/kasld
cd kasld
./kasld

KASLD is written in C and structured for easy re-use. Each file in the ./src directory uses a different technique to retrieve or infer kernel addresses and can be compiled individually.

./kasld is a lazy shell script wrapper which simply builds and executes each of these files, offering a quick and easy method to check for address leaks on a target system. This script requires make.

Refer to output.md for example output from various distros.

Building

A compiler which supports the _GNU_SOURCE macro is required due to use of non-portable code (MAP_ANONYMOUS, getline(), popen(), ...).

KASLD components can be cross-compiled with make by specfying the approriate compiler (CC) with LDFLAGS=-static. For example:

make CC=aarch64-linux-musl-gcc LDFLAGS=-static

Configuration

Common default kernel config options are defined in kasld.h. The default values should work on most systems, but may need to be tweaked for the target system - especially old kernels, embedded devices (ie, armv7), or systems with a non-default memory layout.

Leaked addresses may need to be bit masked off appropriately for the target kernel, depending on kernel alignment. Once bitmasked, the address may need to be adjusted based on text offset, although on x86_64 and arm64 (since 2020-04-15) the text offset is zero.

The configuration options should be fairly self-explanatory. Refer to the comment headers in kasld.h:

// - KERNEL_VAS_START: Expected virtual address for start of the kernel
// virtual address space (VAS).
// (eg. 0xc0000000 for 32-bit systems with 3GB vmsplit)
//
// - KERNEL_VAS_END: Expected end of kernel virtual address space.
// (including modules, I/O, guard regions, ...)
//
// - KERNEL_BASE_MIN: Expected minimum possible kernel base virtual address.
//
// - KERNEL_BASE_MAX: Expected maximum possible kernel base virtual address.
//
// - MODULES_START: Expected start virtual address for kernel modules.
//
// - MODULES_END: Expected end virtual address for kernel modules.
//
// - KERNEL_ALIGN: Expected kernel address alignment.
// (usually 2MiB on modern systems)
//
// - KERNEL_TEXT_DEFAULT: Default kernel base virtual address when KASLR is
// disabled (including text offset). This value is
// calculated automatically based on above values.

Function Offsets

As the entire kernel code text is mapped with only the base address randomized, a single kernel pointer leak can be used to infer the location of the kernel virtual address space and offset of the kernel base address.

Offsets to useful kernel functions (commit_creds, prepare_kernel_cred, native_write_cr4, etc) from the base address can be pre-calculated on other systems with the same kernel - an easy task for publicly available kernels (ie, distro kernels).

Offsets may also be retrieved from various file system locations (/proc/kallsyms, vmlinux, System.map, etc) depending on file system permissions. jonoberheide/ksymhunter automates this process.

Function Granular KASLR (FG-KASLR)

Function Granular KASLR (aka "finer grained KASLR") patches for the 5.5.0-rc7 kernel were proposed in February 2020 (but have not been merged as of 2024-01-01).

This optional non-mainline mitigation "rearranges your kernel code at load time on a per-function level granularity" and can be enabled with the CONFIG_FG_KASLR flag.

FG-KASLR ensures the location of kernel and module functions are independently randomized and no longer located at a constant offset from the kernel .text base.

On systems which support FG-KASLR patches (x86_64 from 2020, arm64 from 2023), this makes calculating offsets to useful functions more difficult and renders kernel pointer leaks significantly less useful.

However, some regions of the kernel are not randomized (such as symbols before __startup_secondary_64 on x86_64) and offsets remain consistent across reboots. Additionally, FG-KASLR randomizes only kernel functions, leaving other useful kernel data (such as modprobe_path and core_pattern usermode helpers) unchanged at a static offset.

Addendum

KASLD serves as a non-exhaustive collection and reference for techniques useful in KASLR bypass; however, it is far from complete. There are many additional noteworthy techniques not included for various reasons.

System Logs

Kernel and system logs (dmesg / syslog) offer a wealth of information, including kernel pointers and the layout of virtual and physical memory.

Several KASLD components search the kernel message ring buffer for kernel addresses. The following KASLD components read from dmesg and /var/log/dmesg:

Historically, raw kernel pointers were frequently printed to the system log without using the %pK printk format.

Bugs which trigger a kernel oops can be used to leak kernel pointers by reading the associated backtrace from system logs (on systems with kernel.panic_on_oops = 0).

There are countless examples. A few simple examples are available in the extra directory:

Most modern distros ship with kernel.dmesg_restrict enabled by default to prevent unprivileged users from accessing the kernel debug log. Similarly, grsecurity hardened kernels support kernel.grsecurity.dmesg to prevent unprivileged access.

System log files (ie, /var/log/syslog) are readable only by privileged users on modern distros. On Debian/Ubuntu systems, users in the adm group also have read permissions on various system log files in /var/log/:

$ ls -la /var/log/syslog /var/log/kern.log /var/log/dmesg
-rw-r----- 1 root   adm 147726 Jan  8 01:43 /var/log/dmesg
-rw-r----- 1 syslog adm    230 Jan 15 00:00 /var/log/kern.log
-rw-r----- 1 syslog adm   8322 Jan 15 04:26 /var/log/syslog

Typically the first user created during installation of an Ubuntu system is a member of the adm group and will have read access to these files.

Additionally, an initscript bug present from 2017-2019 caused the /var/log/dmesg log file to be generated with world-readable permissions (644) and may still be world-readable on some systems.

DebugFS

Various areas of DebugFS (/sys/kernel/debug/*) may disclose kernel pointers.

DebugFS is no longer readable by unprivileged users by default since kernel version v3.7-rc1~174^2~57 on 2012-08-27.

This change pre-dates Linux KASLR by 2 years. However, DebugFS may still be readable in some non-default configurations.

Hardware Bugs

There are a plethora of viable hardware-related attacks which can be used to break KASLR, in particular timing side-channels and transient execution attacks.

KASLD includes the following hardware-related KASLR breaks:

The extra/check-hardware-vulnerabilities script performs rudimentary checks for several known hardware vulnerabilities, but does not implement these techniques.

Refer to the Hardware Side-Channels section for more information.

Weak Entropy

The kernel is loaded at an aligned memory address, usually between PAGE_SIZE (4096 KiB) and 2MiB on modern systems (see KERNEL_ALIGN definitions in kasld.h. This limits the number of possible kernel locations. For example, on x86_64 with RANDOMIZE_BASE_MAX_OFFSET of 1GiB and 2MiB alignment, this limited the kernel load address to 0x4000_0000 / 0x20_0000 = 512 possible locations.

Weaknesses in randomisation can decrease entropy, further limiting the possible kernel locations in memory and making the kernel easier to locate.

KASLR may be disabled if insufficient randomness is generated during boot (for example, if get_kaslr_seed() fails on ARM64).

Refer to the Weak Entropy section for more information.

Additional References

Linux KASLR History and Implementation

Linux KASLR Configuration

Linux Memory Management

Hardware Side-Channels

Practical Timing Side Channel Attacks Against Kernel Space ASLR (Ralf Hund, Carsten Willems, Thorsten Holz, 2013)

google/safeside

Micro architecture attacks on KASLR (Anders Fogh, 2016)

PLATYPUS: Software-based Power Side-Channel Attacks on x86 (Moritz Lipp, Andreas Kogler, David Oswald†, Michael Schwarz, Catherine Easdon, Claudio Canella, and Daniel Gruss, 2020)

LVI: Hijacking Transient Execution through Microarchitectural Load Value Injection (Jo Van Bulck, Daniel Moghimi, Michael Schwarz, Moritz Lipp, Marina Minkin, Daniel Genkin, Yuval Yarom, Berk Sunar, Daniel Gruss, and Frank Piessens, 2020)

Exploiting Microarchitectural Optimizations from Software (Moritz Lipp. 2021)

Hardening the Kernel Against Unprivileged Attacks (Claudio Canella, 2022)

ThermalBleed: A Practical Thermal Side-Channel Attack (Taehun Kim, Youngjoo Shin. 2022)

AMD prefetch and power-based side channel attacks (CVE-2021-26318):

Microarchitectural Data Sampling (MDS) side-channel attacks:

EchoLoad:

Data Bounce:

Prefetch side-channel attacks:

Straight-line Speculation (SLS):

Transactional Synchronization eXtensions (TSX) side-channel timing attacks:

Branch Target Buffer (BTB) based side-channel attacks:

Transient Execution / Speculative Execution:

Speculative Data Gathering / Gather Data Sampling:

TagBleed: Tagged Translation Lookaside Buffer (TLB) side-channel attacks:

RAMBleed side-channel attack (CVE-2019-0174):

Memory deduplication timing side-channel attacks:

Kernel Info Leaks

Patched kernel info leak bugs:

Patched kernel info leak bugs caught by KernelMemorySanitizer (KMSAN):

Netfilter info leak (CVE-2022-1972):

Remote uninitialized stack variables leaked via Bluetooth:

Remote kernel pointer leak via IP packet headers (CVE-2019-10639):

floppy block driver show_floppy kernel function pointer leak (CVE-2018-7273) (requires floppy driver and access to dmesg).

kernel_waitid leak (CVE-2017-14954) (affects kernels 4.13-rc1 to 4.13.4):

snd_timer_user_read uninitialized kernel heap memory disclosure (CVE-2017-1000380):

PPTP sockets pptp_bind() / pptp_connect() kernel stack leak (CVE-2015-8569):

Exploiting uninitialized stack variables:

Kernel Bugs

Leaking kernel addresses using msg_msg struct for arbitrary read (for KMALLOC_CGROUP objects):

Leaking kernel addresses using privileged arbitrary read (or write) in kernel space:

Weak Entropy

Another look at two Linux KASLR patches (Kryptos Logic, 2020)

arm64: efi: kaslr: Fix occasional random alloc (and boot) failure

License

KASLD is MIT licensed but borrows heavily from modified third-party code snippets and proof of concept code.

Various code snippets were taken from third-parties and may have different license restrictions. Refer to the reference URLs in the comment headers available in each file for credits and more information.