Skip to content

Instantly share code, notes, and snippets.

@hunan-rostomyan
Created August 10, 2018 16:51
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save hunan-rostomyan/62d47198d4a7171e282de3fc74b29b2f to your computer and use it in GitHub Desktop.

Buffer Overflows

Friday Learning Session, Aug 10, 2018 for comments: hunan131@gmail.com

What is a buffer overflow?

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.

Example

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.

What makes buffer overflows possible?

  • 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

How can buffer overflows be exploited?

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
    • 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

How to mitigate?

  • 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
  • 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

Notes

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 for gdb

To start a new shell with ASLR disabled:

  • setarch uname -m -R /bin/bash

Literature!

  • 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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment