commit 445da4c004246320597e36c3227bab1c7aad581b
parent b14194d4ffa6887941a9a3d075844734b61ff7da
Author: Alex Balgavy <a.balgavy@gmail.com>
Date: Thu, 24 Sep 2020 22:27:23 +0200
Updated CNS lecture notes
Diffstat:
3 files changed, 200 insertions(+), 5 deletions(-)
diff --git a/content/computer-network-security/Lecture 7_ exploitation techniques.md b/content/computer-network-security/Lecture 7_ exploitation techniques.md
@@ -1,9 +1,9 @@
+++
-title="Lecture 7: exploitation techniques"
+title = "Lecture 7: exploitation techniques"
+++
# Lecture 7: exploitation techniques
-Buffer overflows:
+## Buffer overflows:
- common mistake
- can exploit locally and remotely
- can modify both data and control flow
@@ -17,7 +17,7 @@ Buffer overflows:
- `scanf()` etc. length depends on input string - put bound on `%s` formats
- own input functions might be sloppy, always check assumptions
-Array overflow example (provides arbitrary write):
+## Array overflow (provides arbitrary write)
```c
#include <stdio.h>
@@ -30,4 +30,160 @@ int main(int argc, char **argv) {
return 0;
}
```
-You can load shellcode into environment, then write to this array to overwrite the return address.-
\ No newline at end of file
+You can load shellcode into environment, then write to this array to overwrite the return address.
+
+
+## Off-by-one errors
+- e.g. wrong comparison operator, forget about string terminator
+- similar to regular overflows, but can overwrite only one element above array size
+- this can be exploited to overflow adjacent buffers
+- note: every pointer contains 2 null bytes (at end in 64-bit, integers are stored little endian)
+
+## Data/BSS overflows
+Data and BSS store global variables
+No return address reachable for contiguous overflows.
+What can you do?
+- overwriting function pointer
+- overwrite saved frame pointer (attacker can set up fake stack, later return from this stack)
+- overwrite C++ object pointer (can hijack virtual function calls)
+- overwriting variables often breaks security, like changing strings/integers
+- changing pointers
+
+## Heap overflows
+explicit allocation functions return memory on heap, which survives function return but needs explicit deallocation.
+harder to exploit: no return addresses, relative locations depend on order and malloc implementation
+instead you target e.g. metadata
+
+heap organisation:
+- heap grows towards higher memory address
+- memory managed through in-band control structures (metadata is between buffers)
+- control structures can be manipulated through heap overflows for arbitrary code execution
+- depends on architecture and OS (especially libc)
+- heap is divided in chunks, adjacent free blocks are merged
+
+dlmalloc (used in glibc) implementation:
+1. find free chunk from free list
+ - if not found, allocate more memory from OS and add to free list
+2. if chunk too large, split in two and add new chunk to free list
+3. Remove chunk from free list
+4. Mark chunk as used in metadata
+5. Return pointer to data area in chunk
+
+dlmalloc's free:
+1. Locate chunk with data pointer
+2. Mark chunk as free in metadata
+3. If next chunk also free, merge with next chnk
+4. If previous chunk also free, merge with previous chunk
+5. Add chunk to free list
+
+Metadata at start of every chunk:
+
+```c
+struct malloc_chunk {
+ size_t prev_size;
+ size_t size;
+ struct malloc_chunk* fd; // used only if free, otherwise data pointer starts here
+ struct malloc_chunk* bk;
+};
+```
+
+Chunk size:
+- 8 bytes overhead per allocated block (only size field always used)
+- size always multiple of 16 (data size+overhead rounded up, four low-order bits always 0)
+- low-order bits of size field used for status
+
+Free list:
+- used to find free block to allocate
+- doubly linked list using `fd` and `bk` fields
+- insertion in free list: free(), splitting large block in malloc
+- removal from free list: malloc(), merging free blocks in free()
+
+Exploiting dlmalloc:
+- assume we find heap buffer overflow
+- overwrite `fd` and `bk` (requires free block)
+- make program call unlink (e.g. to merge block when block before is freed)
+- unlink writes chosen data (`fd`) at chosen location (`bk`)
+
+In stack buffer overflows, return address is at fixed offset (so it's easy to reach)
+Heap overflow/format string write to an absolute address
+Alternative target is Global Offset Table
+- used to lazily load library functions
+- address is looked up and stored on first call
+- has a fixed location
+- can use printf
+
+
+## Integer overflow
+Integers have a fixed size, each integer type has limited range.
+If result does not fit in range of integer, CPU still computes result but discards bits that don't fit
+Classification:
+- truncation: integer is cast to a smaller type, discarding extra bits
+- arithmetic overflow: computation result out of range for type, wrapping around
+- signedness: negative integer cast to unsigned type, incorrectly interpreting sign bit
+
+## Format strings
+printf and related take format string and parameters
+careless programmers might let user specify format string
+
+parameter passing is just like for other functions (registers, then stack)
+missing parameters filled with whatever happened to be there -- information leaks, or position to reach all of stack
+`%n` - writes to memory, stores number of output characters so far to pointer passed as parameter. so controlling format strings implies arbitrary write.
+
+```c
+int main(int argc, char **argv) {
+ char buf[256];
+ int y = 1;
+ snprintf(buf, sizeof(buf), argv[1]); // missing parameter! so format string is attacker-controlled
+ printf("buffer (%d): %s\n", strlen(buf), buf);
+ printf("y is %d/0x%x (@ %p)\n", y, y, &y);
+ return 0;
+}
+```
+
+## Temporal errors
+Spatial errors let attacker access outside space allocated for buffer.
+Temporal errors let attacker access buffer before/after intended time frame
+Main types;
+- use after free
+- uninitialized variables
+
+Use after free:
+- sometimes program retains pointer to freed memory location
+ - malloc buffer that was freed
+ - local variable/alloca buffer after function return
+- future allocation/function call can re-use memory
+- dereferencing dangling pointer results in undefined behavior
+- attacker can craft input to overwrite memory with own data
+ 1. program allocates X
+ 2. program uses X to store some data
+ 3. program frees X
+ 4. program allocates Y overlapping with X
+ 5. data written to Y also overwrites relevant part of X
+ 6. program uses X, causing incorrect result
+
+Uninitialized variables
+- local variables and malloc buffers not automatically zeroed
+- instead contain whatever happened to be there
+- compilers try to warn, but e.g. arrays, struct/union members, malloc buffers not checked
+- attacker can initialize variable in way that programmer didn't expect:
+ 1. program allocates X
+ 2. program uses X to store data under attacker control
+ 3. program frees X
+ 4. program allocates Y overlapping X
+ 5. program doesn't initialize some/all of Y, causing attacker-provided data from X to stay there
+ 6. program uses Y, causing incorrect result
+
+## Type confusion
+C++ provides classes (basically structs tying data to functions)
+Instance of class is object, can be on stack or on heap
+Classes can inherit from one or more classes, can call all functions available from parent.
+Object pointer can be cast from child to parent.
+
+C++ typecasts:
+- reinterpret_cast: no checks (fast), assumes programmer knows their shit (unsafe)
+- static_cast: compile-time check (fast at runtime), allows any possibly valid cast including parent-to-child (still unsafe)
+- dynamic_cast: run-time check (slow), ensures runtime type is consistent with compile-time type (safe)
+
+static_cast is common but unsafe:
+- object may be cast to wrong type
+- incorrect cast causes mismatch between runtime type and compile-time type, members read/written according to wrong type+
\ No newline at end of file
diff --git a/content/computer-network-security/Lecture 8_ Defenses.md b/content/computer-network-security/Lecture 8_ Defenses.md
@@ -0,0 +1,38 @@
++++
+title = "Lecture 8: Defenses"
++++
+
+# Lecture 8: Defenses
+Some techniques available to make attacks harder.
+Modern compilers and OSes implement several of them, some by default.
+
+Stack canaries:
+- value between local vars and return address, compiler adds initialization in function prologue
+- check whether value is same before function returns, compiler adds check in function epilogue
+- corrupting return address also corrupts canary
+- attacker can:
+ - jump over canary
+ - overwrite canary with correct value after leaking it first
+
+Data execution prevention
+- OS marks data pages as non-executable (requires CPU feature no-execute bit, supported on all modern Intel/AMD CPUs)
+- attempt to execute those pages causes segfault
+
+W⊕X: write xor execute
+- ensure no memory is both writable and executable
+- prevents attacker from injecting code and executing it
+- attacker can instead reuse existing code:
+ - shared library functions (return to libc)
+ - for example, write address of system(), ensure %rdi has pointer to shell command
+ - easier in 32-bit as parameters are on stack
+ - chain together parts of code into new program (Return Oriented Programming chains, where stack has addresses)
+
+ASLR: address space layout randomization
+- randomizes memory addresses of code, data, heap, stack
+- prevents attacker from finding code pointer to overwrite, or knowing what to overwrite it with
+- attacker can:
+ - leak addresses
+ - leak code and data to recover addresses
+ - use side channels to recover complete address space layout
+- only few bits are truly random, so try to brute force
+
diff --git a/content/computer-network-security/_index.md b/content/computer-network-security/_index.md
@@ -11,3 +11,4 @@ title = "Computer and Network Security"
- [Lecture 5: application security - simple attacks](lecture-5-application-security-simple-attacks)
- [Lecture 6: assembly, shellcode exploits](lecture-6-assembly-shellcode-exploits)
- [Lecture 7: exploitation techniques](lecture-7-exploitation-techniques)
+- [Lecture 8: Defenses](lecture-8-defenses)