Defeat Exploit Mitigations¶
General¶
In order to defeat mitigations explained in Exploit Mitigations, an attacker can use various kind of techniques.
Recap all exploit mitigations
- Stack canary: detects/blocks overflows
- enabled per default
- per program (3rd party programs?)
-fstack-protector
(default),-fstack-protector-all
(ALL functions),-fstack-protector-strong
(better)
- DEP: makes it impossible to execute uploaded code (stack only)
- enabled per default
- system level + per-program
- disable it with
gcc -z noexecstack
- ASLR & PIE: makes it impossible to locate data
- ASLR is enabled per default
- PIE (is not) enabled per default (
-pie -fPIE
) \(\rightarrow\) Ubuntu 18.04 makes it default - system-level
- ASCII Armor: makes it impossible to insert certain data
Arbitrary Write (Stack Canary)¶
Arbitrary write is a technique, where the attacker jumps over the stack canary and writes data behind the canary. This will not break the canary and therefore make it useless. Arbitrary write can be prevented when brute-force is not feasible and there is no information disclosure.
Local Variables (Stack Canary)¶
Function-Local variables are stored below the stack canary and therefore can be tampered without the Stack Canary taking notice of it.
Heap Overflow (Stack Canary)¶
The Stack Canary does protect from overflowing the stack. But what about the heap?! The heap can still be overflown or abused by an attacker leveraging one of:
- Use after free
- Type confusion
- Inter-Chunk heap overflow / Relative write
- Inter-Chunk heap overflow / Corruption
Brute Force (Stack Canary)¶
A Stack Canary normally consists of 4 bytes. This gives a total of \(2^{32} > 4\ billion\) possibilities. But what if we can bruteforce the Stack Canary byte after byte? A byte only has \(2^8 = 256\) possible values. The Stack Canary consists of four bytes. This gives a total of \(4 * 256 = 1024\) possibilities. Because of the birthday problem this will lead to \(512\) required tries on average. Bruteforcing the Stack Canary is therefore feasible. For 64-Bit Stack Canaries this is equally true because then it would be \(8 * 256 = 2048\). This would lead to \(1024\) tries on average, which is still feasible.
Example:
- need to break SBP first
- easy if the vulnerable program is a network server (e.g.
fork
to brute-force)
Information Disclosure (ASLR)¶
To defeat ASLR, an attacker can gather information about the specific memory layout by reading out the addresses of uninitialized memory, structs with pointers or by over-reading (heartbleed) from an address \(\rightarrow\) memory leak!
Partial RIP Overwrite (ASLR)¶
This technique takes advantage of the fact that only part of a memory address is randomized by ASLR, allowing an attacker to control enough bits of the address to jump to a desired location in memory.
NOP Slide (ASLR)¶
This method helps ensure that an exploit lands correctly on the intended payload, even if the exact address is not known.
Ret 2 PLT (DEP/ASLR)¶
Return 2 Procedure Linkage Table (Ret2PLT) is a technique where the attacker uses the fact that the shared libraries are leveraged using a table which holds static addresses for the shared functionality. The idea of Ret2PLT is therefore to abuse the shared library and return to the library code from the executable.
Ret 2 PLT is fixed and prevented by PIE
ROP (DEP)¶
Return Oriented Programming (ROP) can break DEP. The idea behind ROP is to use sequences of instructions (called gadgets) to build a working attack. Therefore gadgets represent the basic building blocks of a program (Read, Write, Conditions, Loops, etc.). These gadgets can be found in shared libraries like libc
. An attacker then chains those gadgets in a way, which reach the goals of the attacker. This will allow the attacker to eventually execute shellcode and hijack the victims system. The attacker does not need the permissions (X
-flag) introduced with DEP to execute the code, because the executed gadgets are placed in a location which must be executable by its nature. The approach is nicely described in the article of Hovav Shacham: The geometry of innocent flesh on the bone: return-into-libc without function calls (on the x86) (ACM, CCS: Computer and Communications Security, Conference, 2007).
Where to take gadgets from?
- The program code
- static location in memory (if no PIE)
- needs to be of some size to have enough gadgets
- Shared library code (LIBC etc.)
- "Universal gadget library", because its very big
- Sadly, non-guessable base location (ASLR'd even without PIE)
- Requires an information-leak into LIBC (e.g. memory leak PLT/GOT)
Conclusion
- Can execute arbitrary code by re-using code from program or shared libraries
- Can defeat often ASLR+DEP
- Can defeat ASLR+DEP+PIE with information dislosure
Information disclosure can eliminate ASLR protection which enables ROP to eliminate DEP