First of all, we need to have a strong understanding of how a program allocates memory during its execution. See Memoria, Memoria virtuale and other notes about Nomi e Scope, Gestione della memoria. The thing you have to remember is that
- Every new function call allocates a new block, with his local variables.
- How the calling parameters are stored in the stack
- How the heap is allocated (common heap algos are in Gestione della memoria)
- How the stack grows (and how it can overflow it, and overwriting important data).
Common attack vectors
We use C, as it is the easiest way to show how this could be attacked.
The threat model
Attacker’s goal:
- Inject malicious code into a program and execute it (Return Object Programming)
- Gain all privileges and capabilities of the target program (e.g. setuid)
System’s goal:
- prevent code injection
- Integrity – program should execute faithfully, as programmer intended
- Crashes should be handled gracefully
Attacker’s capability:
- submit arbitrary input to the program
- Environment variables
- Command line parameters
- Contents of files
- Network data The thing is that it is highly variable.
Stack smash example
Some functions don't have boundary controls, for example `strcpy` or `gets` and are vulnerable to stack overflows.Common defenses
Compiler Hardening
These are just hardening attempts, which means it makes the attack more difficult, but still not impossible to execute.
Stack canaries
Just a random string that is checked before returning. This allows you to check if there has been a stack overflow. Usually this can be bypassed if you can leak the value of the canary before-hand.
Non executable stacks
So you can’t execute the shell-code you have just wrote in the stack! :).
Os hardening
Some hardening at the OS level to prevent common exploits.
Address-Space Layout Randomization (ASLR)
The location of the data and code are always randomized when the program is loaded. This makes it more difficult to have exploits jumping around the code! Example ROP attacks are more difficult. (ROP = Return-oriented-programming, method that allows you to control where the program jumps by overwriting return addresses.)
Some rules
Use memory safe languages
Example: C is not memory safe, see Teoria dei Tipi. using safe languages allow you to have provable guarantees that the type is always respected and stuff like this!
Data vs Code
You need to differentiate the data with the code. They are two very different things! Many different exploits use data to be interpreted as code, and thus have this bug.
Patch!
- Patch as soon as you can. most of the vulnerabilities are discovered but then left to be, without been patched for a long time. (e.g. exploit kits for these vulnerabilities)
Automatic patches are the best.