Friday Learning Session, Aug 10, 2018 for comments: hunan131@gmail.com
Buffer overflow is a vulnerability present in programs that perform unsafe buffer manipulation. In this context, unsafe means any logic that doesn't do bounds-checking. It's mostly a threat for C/C++ programs. Let's go through an unrealistic example to see buffer overflow in action and go over some of the context necessary for understanding how this vulnerability can be exploited in the wild and what we can do as engineers (software and hardware) to avoid this nasty problem.
Consider this piece of C code:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char settings[100];
char pass[20];
char *ADMIN_PASS = argv[1];
char *logged_in = &settings[0];
printf("> ");
gets(pass);
if (strcmp(pass, ADMIN_PASS) == 0) {
*logged_in = 1;
}
if (*logged_in) {
printf("Welcome!\n");
} else {
printf("Goodbyte.\n");
}
return 0;
}
Compile with (see Notes at the end for more options):
gcc hello.c -o hello
Run with some admin password:
./hello $(echo '' | md5sum)
Type in a string of 20 or so characters.
- von Neumann architecture of sequential program execution (no distinction between code and data)
- related: executable non-code segments (e.g. stack)
- no built-in support for functions; implemented using System 5 ABI and the stack discipline
- fixed memory layout of a process
- support of dynamically-sized buffers
- no array bounds checking
We have identified an overflowable buffer. This means that we can exploit it to get unintended behavior:
- we can cause the program to crash (if a server, this can lead to traffic loss)
- we can overwrite data used to control program flow
- e.g. the 4_flag program
- we can gain control of the program execution
- we can overwrite the stored
$ebp
to point to wherever we want- if we know the absolute address of a method we want to run, we can write that address over
$ebp
- if we don't know the absolute address, we can jump relative to
$esp
- if we know the absolute address of a method we want to run, we can write that address over
- we can deploy arbitrary programs (constrained only by the buffer size) onto the stack and then jump to it, doing all sorts of evil
- spawning a root shell to hijack control of the program
- recycling the socket descriptor to hijack control of the network channel
- we can overwrite the stored
- avoid buffer overflows in the first place
- can avoid C
- low-level? rust, golang
- higher-level? Java, JavaScript, Python, OCaml
- very high level? Haskell, Racket
- have to use C
- static analysis tools
- fuzzing and testing in general
- can avoid C
- assuming the presencde of buffer overflows, what can we do?
- hardware-level
- non-executable stack
- OS-level
- ASLR
- application-level
- compiler
- stack canaries
- fat pointers
- programmer
- link only libraries you need
- avoid using unsafe functions?
- if using your own IO and memory-manipulation code, perform explicit checking of bounds
- compiler
- OS-level
To get into the same compute environment as me:
- clone
https://github.com/hunan-rostomyan/devplat
- put your C files inside
shared
gcc [code.c] -o [bin]
- add
-fno-stack-protector
to disable stack protection - add
-z execstack
to make the stack executable - add
-g3
to add debugging info to the binary forgdb
- add
To start a new shell with ASLR disabled:
setarch
uname -m-R /bin/bash
- Aleph1 (1996) Smashing The Stack For Fun And Profit
- This is the classic article that popularized buffer overflow exploitation. The concrete code (e.g. pre 64-bit registers) is pretty out of date, but the ideas are still golden. See this for an attempt at updating it.
- Birkholz (2005) Buffer Overflow Attacks. Detect, Exploit, Prevent
- The ethical hacker will appreciate this book. It situates buffer overflows in the landscape of exploits and goes in sufficient amount of detail into the implementation of buffer overflow exploits. Highly recommended.
- Erickson (2008) Hacking: The Art of Exploitation, 2nd Edition.
- This is the book that inspired my own interest in hacking (reversing, viruses) back in the days. If you must read only one book on the topic, read this.
- MIT 6.858 (2014) Computer Systems Security
- The first three lectures constitute a very accessible, high-level introduction to stack overflows, with a focus on remedies (esp. on "baggy bounds" -- since it comes from an MIT paper!).
- Seyfarth (2014) Introduction to 64 Bit Intel Assembly Programming for Linux and OS X
- Good recent book covering x86-64 assembly using both gdb and a GUI debugger/assembler written by the author. One of the nice and surprising features of this book is that it contains lots of low-level numerical code (e.g. implementing efficient dot products and such).