200 - 200th Episode! Integer Bugs & Synthetic Memory Protections
A high performance, but apparently low security library for some industrial software, root cause is the use of a signed comparison of a value that is then used as an unsigned size value in a memcpy. End result being a much too large copy, overflowing the destination buffer.
An exploit chain that targets Samsung’s TEEgris OS running in the ARM TrustZone secure world. TEEgris consists of a secure kernel and trustlets that run on the userspace side, which Android in the non-secure world can communicate with via Secure Monitor Calls (SMCs). The first vuln they found was in the Key Master (KEYMST) trustlet.
Stack overflow in KEYMST RSA Exponent Import As a key manager, the KEYMST trustlet allows non-secure world to import keys including RSA. When importing the exponent and reading the untrusted size, that size isn’t validated properly before copying in the exponent. They check that the size is less than 512 bytes, but when added to the exponent offset in the stack buffer for storing key info, it can go out-of-bounds.
They then did a classic return address overwrite and ROP chain, using qiling to emulate for testing their exploit.
Format string bug in Secure Kernel Logging Driver
The secure kernel also contains secure drivers, one of which is the logging driver. The KEYMST trustlet has access to this driver, and can reach one of the logging-related ioctls implemented by
log_msg(). The problem is, a user-provided argument is passed directly for the format string to
printf(). The other arguments passed aren’t controlled directly by the attacker, but by exploiting the format string multiple times to increment arbitrary bytes, they could achieve arbitrary read/write.
Looks like OpenBSD is/has introduced some new exploit mitigations that work to hinder ROP-based exploited chains. There are four new mitigations
Immutable mappings (permissions) - Mappings can be marked as immutable so the mappings rwx permissions cannot be modified after that point, nor can the page be unmapped and remapped with different permissions. So you can’t use a ROP chain to make some page you can get data in executable.
Xonly - eXecute Only memory - Memory that can be mapped as executable but not readable. Mainly this tries to prevent attacks from being able to find ROP gadgets in the first place, if they can’t read the executable code they can’t find gadgets. Of course if you have access to the original binaries then you can get the executable data from there, but it prevents Blind ROP style attacks.
I was surprised to see they had an amd64 implementation using the RPKU register (only on newer CPUs). I can’t comment much on the implementation since I’m unfamiliar with how that aspect works, but it did surprise me.
There is also a kernel enforced XOM, I’m not sure how effective it will be though. It seems like it just basically validates addresses on
copyin calls. So pure-userland/CPU reads wouldn’t trip this check, though I’m sure there are some cases it’ll stop.
Stack Protection - This one is a meant to prevent stack pivots, which is where you use a ROP gadget to move the stack to a completely new region of memory, usually off the stack somewhere the attacker has more control. To do this pages mapped for the stack get marked, and when there is a syscall the kernel verifies the stack pointer still points to a stack page otherwise it kills the program.
Execute Syscall Protection - Restricts where syscalls can originate from, on syscall the instruction pointer/program counter must point to a region where syscalls are permitted. This prevents chains that create an executable section to dump shellcode into and execute that. Forcing chains to use an existing syscall gadget.
Honestly, an interesting set of mitigations. Nothing that is game changing, but as they say, they are all steps that make exploitation most costly and difficult.
- Kagi Summarizer - - - - -
The PDF document discusses various methods of attack on computer systems, including stack smashing, heap payloads, and return-oriented programming (ROP). The author explains that while there have been attempts to mitigate these attacks, there is no complete solution to block ROP. The document then goes on to describe the development of synthetic memory protections, including execute-only permissions and stack and syscall protection. These protections aim to push attackers towards more challenging schemes and disrupt their success rates. The author concludes by stating that the real-world impact of these mitigations will be judged in the coming years. Overall, the document highlights the ongoing battle between attackers and defenders in the realm of computer security.
- ROP (Return Oriented Programming) is a sophisticated attack method that combines pre-existing code chunks to gain control.
- There is no simple complete solution to block ROP.
- Synthetic Memory Protections are a new generation of mitigations that aim to block ROP by identifying system behaviors that only ROP code requires and blocking them.
- There have been 25 years of stack smashing mitigations, with four generations of mitigations.
- The MMU (Memory Management Unit) is a hardware component that remaps physical memory into virtual ranges and contains permission bits that include R (Read), W (Write), and X (Execute).
- Synthetic Permissions are a new type of permission that includes Immutable Mappings, Execute-Only Permission, and Stack Permission on mappings.
- Xonly is a new type of protection mechanism that enforces Execute-Only permission and blocks reading code areas.
- Stack Protection and Syscall Protection are new protection mechanisms that detect easier exploit patterns and push the ROP programmer to explore more challenging schemes.
- Immutable mappings may help with other inexpensive checks.
- All these mitigations aim to push attackers towards methods that require more intense labor, features that are disrupted, and worse success rates.