[LINUX] Kernel Self-Protection (2/2)

Originally, it is a part of the Linux Kernel source code, so it will be treated as GPLv2 (recognition that it should be).

https://www.kernel.org/doc/html/latest/index.html

Licensing documentation

The following describes the license of the Linux kernel source code (GPLv2), how to properly mark the license of individual files in the source tree, as well as links to the full license text.

https://www.kernel.org/doc/html/latest/process/license-rules.html#kernel-licensing

https://www.kernel.org/doc/html/latest/security/self-protection.html

Kernel Self-Protection (continued)

Probabilistic defenses

While many protections can be considered deterministic (e.g. read-only memory cannot be written to), some protections provide only statistical defense, in that an attack must gather enough information about a running system to overcome the defense.

Many protections are decisive (for example, they cannot be written to read only memory), but some protections are statistical protections. This attempts the attacker to get enough information from the running system to surrender the defense.

While not perfect, these do provide meaningful defenses.

This isn't perfect, but it's a valuable defense.

Canaries, blinding, and other secrets

It should be noted that things like the stack canary discussed earlier are technically statistical defenses, since they rely on a secret value, and such values may become discoverable through an information exposure flaw.

Something like stack canary that we have discussed so far is a statistical defense technique. It is associated with a hidden value and can be discovered by a flaw in an information leak.

.

Blinding literal values for things like JITs, where the executable contents may be partially under the control of userspace, need a similar secret value.

Hidden values are also needed to make literal values invisible, such as JIT, where executable content may exist due to user space control.

.

It is critical that the secret values used must be separate (e.g. different canary per stack) and high entropy (e.g. is the RNG actually working?) in order to maximize their success.

It is important that the hidden values must be separated (eg, different canaries for stack things) or have high entropy (actually run RNG). To maximize this outcome.

Kernel Address Space Layout Randomization (KASLR)

Since the location of kernel memory is almost always instrumental in mounting a successful attack, making the location non-deterministic raises the difficulty of an exploit.

The location of kernel memory is often a means to a successful attack. By making the location non-specific, you can increase the difficulty of the attack.

(Note that this in turn makes the value of information exposures higher, since they may be used to discover desired memory locations.)

(Note that this increases the chances of an information breach. Information breaches are also used to find the memory city you need).

Text and module base

By relocating the physical and virtual base address of the kernel at boot-time (CONFIG_RANDOMIZE_BASE), attacks needing kernel code will be frustrated.

Redefining physical and virtual for the kernel at boot time will frustrate attacks on kernel code (CONFIG_RANDOMIZE_BASE). ,

Additionally, offsetting the module loading base address means that even systems that load the same set of modules in the same order every boot will not share a common base address with the rest of the kernel text.

Furthermore, by offsetting the base address that loads the module, even if the same module set is loaded in the same order at boot time, it will not share a common base address with the text area of the kernel.

Stack base

If the base address of the kernel stack is not the same between processes, or even not the same between syscalls, targets on or beyond the stack become more difficult to locate.

If the base address of the kernel stack does not match between processes, it will be even more difficult to find targets on or across the stack, even if they are similar or different in the same syscalls building.

Dynamic memory base

Much of the kernel’s dynamic memory (e.g. kmalloc, vmalloc, etc) ends up being relatively deterministic in layout due to the order of early-boot initializations.

Much of the kernel's dynamically allocated memory has a relatively deterministic layout (kmalloc, vmalloc, etc.) depending on the initial desired order.

If the base address of these areas is not the same between boots, targeting them is frustrated, requiring an information exposure specific to the region.

If the base addresses of these areas do not match at startup, it will be difficult to target them and information will be needed for the areas.

Structure layout

By performing a per-build randomization of the layout of sensitive structures, attacks must either be tuned to known kernel builds or expose enough kernel memory to determine structure layouts before manipulating them.

Randomizing the layout of the sensitive information structure from build to build requires sufficient kernel memory exposure to tailor the attack to a known kernel build or to determine the structure before manipulating it.

Preventing Information Exposures

Since the locations of sensitive structures are the primary target for attacks, it is important to defend against exposure of both kernel memory addresses and kernel memory contents

It is important to prevent the exposure of both kernel memory addresses and kernel memory contents, as the location of sensitive information structures is the main target for attacks.

(since they may contain kernel addresses or other sensitive things like canary values).

(May contain other sensitive information such as kernel address and canary values)

Kernel addresses

Printing kernel addresses to userspace leaks sensitive information about the kernel memory layout.

Displaying the kernel address to the user space leaks sensitive information about the kernel's memory layout.

Care should be exercised when using any printk specifier that prints the raw address, currently %px, %p[ad], (and %p[sSb] in certain circumstances [*]).

Great care should be taken when using printk descriptors that print raw addresses (currently% px,% p [ad],% p [sSb] in certain situations [*]. reference).

Any file written to using one of these specifiers should be readable only by privileged processes.

Files written using these descriptors should only be readable by privileged processes. .

Kernels 4.14 and older printed the raw address using %p.

In kernels 4.14 and earlier,% p was used to output the raw address display.

As of 4.15-rc1 addresses printed with the specifier %p are hashed before printing.

In 4.15-rc1 and later, the% p descriptor is mask-hashed before the address is displayed.

.

[*] If KALLSYMS is enabled and symbol lookup fails, the raw address is printed.

If KALLSYMS is enabled and symbol lookup fails, the raw address will be displayed.

If KALLSYMS is not enabled the raw address is printed.

If KALLSMYS is not enabled, the raw address will be displayed.

.

Unique identifiers

Kernel memory addresses must never be used as identifiers exposed to userspace.

Do not use the kernel memory address as an identifier exposed to user space.

Instead, use an atomic counter, an idr, or similar unique identifier.

Instead, use atomic counter, idr, or similar unique identifier.

Memory initialization

Memory copied to userspace must always be fully initialized.

The memory copied to user space must always be fully initialized.

If not explicitly memset(), this will require changes to the compiler to make sure structure holes are cleared.

If you don't explicitly memset (), the compiler must modify it to prevent holes in the structure.

Memory poisoning

When releasing memory, it is best to poison the contents, to avoid reuse attacks that rely on the old contents of memory.

Contaminating content is the best way to prevent attacks that reuse old memory content when you free it.

E.g., clear stack on a syscall return (CONFIG_GCC_PLUGIN_STACKLEAK), wipe heap memory on a free.

For example, you can wipe the released heap memory by clearing the stack when returning from syscall (CONFIG_GCC_PLUGIN_STACKLEAK).

This frustrates many uninitialized variable attacks, stack content exposures, heap content exposures, and use-after-free attacks.

This can prevent many uninitialized variable attacks, stack context exposures, heap content exposures, and unopened memory attacks.

Destination tracking

To help kill classes of bugs that result in kernel addresses being written to userspace, the destination of writes needs to be tracked.

In order to stop the class that causes the kernel address to be written to user space, it is necessary to track the write destination.

If the buffer is destined for userspace (e.g. seq_file backed /proc files), it should automatically censor sensitive values.

If the buffer outputs userspace (for example, seq_file with / proc files in the background), sensitive values are automatically censored.

Recommended Posts

Kernel Self-Protection (1/2)
Kernel Self-Protection (2/2)
k-means and kernel k-means
Kernel mode NEON
Kernel SVM (make_circles)