1 15-BufferOverflow


Previous: 14-MaliciousSoftware.html

1.1 Program inputs??

Besides user-input, what should be considered program inputs?

A bio-centric attack:
https://www.technologyreview.com/s/608596/scientists-hack-a-computer-using-dna/
http://dnasec.cs.washington.edu/dnasec.pdf
http://dnasec.cs.washington.edu/

1.2 Extra reading

13b-ReverseEngineering/assembly64.pdf
https://www.hacksplaining.com/exercises/buffer-overflows
https://www.hacksplaining.com/prevention/buffer-overflows

1.3 Screencasts

1.4 Background

https://en.wikipedia.org/wiki/Buffer_overflow

1.4.1 Address space

1.4.2 Virtual memory

Mapping virtual addresses to real addresses
15-BufferOverflow/virt_mem.png

1.4.3 Memory organization

15-BufferOverflow/memory_diagram_stack_heap.png
15-BufferOverflow/stack00.png

15-BufferOverflow/mem.png

1.4.4 Stack

Stack growing downward here
15-BufferOverflow/call_stack.png

1.4.5 Stack and heap growth

Stack grows down, heap grows up
15-BufferOverflow/f4-crop.png

1.4.6 Frame

Each frame on the stack:
15-BufferOverflow/f3-crop.png

1.5 Buffer overflow

1.5.1 Exploits

What is an Exploit?
* An exploit is any input (i.e., a piece of software, an argument string, or sequence of commands) that takes advantage of a bug, glitch or vulnerability in order to cause an attack.
* An attack is an unintended or unanticipated behavior that occurs on computer software, hardware, or something electronic, that brings an advantage to the attacker

1.5.2 Definition

Buffer Overflow Attack
* One of the most common software and OS bugs is a buffer overflow
* The developer fails to include code that checks whether an input fits into its buffer array
* An input to the running process exceeds the length of the buffer
* The input string overwrites a portion of the memory of the process
* Causes the application to behave improperly and unexpectedly
* A very common attack mechanism
* First widely used by the Morris Worm in 1988
* Prevention techniques known
* Still of major concern
* Legacy of buggy code in widely deployed operating systems and applications
* Continued careless programming practices by programmers…
* Having done work in “human factors” and “engineering psychology”, I actually question this notion — bad human factors in the design of the languages themselves is at fault!
* These do not have to occur! Just use a modern low level language like Rust.
* The language should support the human.

1.5.3 History

Buffer overflow attack history
15-BufferOverflow/image4.png
* Still quite common due to legacy code in C/C++/asm !

A buffer overflow, also known as a buffer overrun, is defined in the NIST Glossary of Key Information Security Terms as follows:
* “A condition at an interface under which more input can be placed into a buffer or data holding area than the capacity allocated, overwriting other information. Attackers exploit such a condition to crash a system or to insert specially crafted code that allows them to gain control of the system.”

1.5.4 Buffer Overflow Basics

1.5.5 Example in C

Contiguous memory in C
~~~
unsigned short B = 1979;
char A[8] = ““;
~~~

Lower in stack15-BufferOverflow/over00.pngHigher in stack
Contiguous memory in C

Unsafe:
~~~
strcpy(A, “excessive”);
~~~

Lower in stack15-BufferOverflow/over01.pngHigher in stack

Safer: To prevent the buffer overflow from happening in this example, the call to strcpy could be replaced with strncpy, which takes the maximum capacity of A as an additional parameter and ensures that no more than this amount of data is written to A:
~~~
strncpy(A, “excessive”, sizeof(A));
~~~

Safest: Use a modern fast systems-capable language like Rust.

1.5.6 strcpy() vs. strncpy()

Explicit is better than implicit!

1.5.7 Attacks

Buffer Overflow Attacks

1.5.7.1 Fuzzing

https://en.wikipedia.org/wiki/Fuzzing
* This is like randomized unit testing, but barrages the binary with far more randomized inputs.
* Fuzzing or fuzz testing is an automated software testing technique that involves providing invalid, unexpected, or random data as inputs to a computer program.
* The program is then monitored for exceptions such as crashes, failing built-in code assertions, or potential memory leaks.
* Typically, fuzzers are used to test programs that take structured inputs.
* This structure is specified, e.g., in a file format or protocol and distinguishes valid from invalid input.
* An effective fuzzer generates semi-valid inputs that are “valid enough” in that they are not directly rejected by the parser, but do create unexpected behaviors deeper in the program and are “invalid enough” to expose corner cases that have not been properly dealt with.

1.5.8 Programming language

Memory organization
15-BufferOverflow/memory_diagram_stack_heap.png
15-BufferOverflow/stack00.png

1.6 Stack buffer overflow

1.6.1 Simple example

Stack buffer overflow vulnerability example in C

#include <string.h>

void foo(char *bar)
{
    char  c[12];
    strcpy(c, bar);  // no bounds checking
}

int main(int argc, char **argv)
{
    foo(argv[1]);
    return 0;
}
// g++ source.cpp
// ./a.out arg1tooooloooooongg

+++++++++++++++ Cahoot15-1

Stack buffer overflow vulnerability example in C
* The previous code takes an argument from the command line and copies it to a local stack variable c.
* This works fine for command line arguments smaller than 12 characters (as you can see in figure B below).
* Any arguments larger than 11 characters long will result in corruption of the stack.
* The maximum number of characters that is safe is one less than the size of the buffer here because in the C programming language strings are terminated by a zero byte character.
* A twelve-character input thus requires thirteen bytes to store, the input followed by the sentinel zero byte.
* The zero byte then ends up overwriting a memory location that’s one byte beyond the end of the buffer.

Stack buffer overflow vulnerability example Before data is copied
NOTE: this image series is “upside-down” compared to most stack diagrams
15-BufferOverflow/overflow3.png

Stack buffer overflow vulnerability example Hello is the first command line argument
15-BufferOverflow/overflow1.png

Stack buffer overflow vulnerability example
“AAAAAAAAAAAAAAAAAAAA
is the first command line argument (address of what?)
15-BufferOverflow/overflow2.png

1.6.2 Another example

Buffer overflow attack
15-BufferOverflow/image6.png

Buffer overflow attack
15-BufferOverflow/image7.png

1.6.3 Recall

Password example buffer_overflow.cpp uploaded during the last section.

1.7 Shellcode injection

Side note:
* Metasploit Project
* https://www.metasploit.com/
* https://en.wikipedia.org/wiki/Metasploit_Project
* Provides useful information to people who perform penetration, IDS signature development, and exploit research.
* I recommend testing this out on a virtual network, on virtual machines, which are isolated from the internet at large.
* Do NOT let this loose on the campus network, or other real-world environments; doing so would likely be illegal, and irresponsible (or malicious), unless you were paid to do some kind of audit, for example.

1.7.1 Stack Overflow Variants

Target
* A trusted system utility
* Network service daemon
* Commonly used library code

Shellcode functions
* Launch a remote shell when connected to
* Create a reverse shell that connects back to the hacker
* Use local exploits that establish a shell
* Flush firewall rules that currently block other attacks
* Break out of a chroot (restricted execution) environment (like a docker container), giving full access to the system.
* Side note: docker containers are easy to escape…

1.8 Defenses

Two approaches to buffer overflow defense

Compile time
* Aim to harden programs to resist attacks in new programs.

Run time
* Aim to detect and abort attacks in existing programs.

1.8.1 Compile-Time Defenses: Programming Language

Solution
* Use a modern high-level language (python, rust, ruby, lua, go etc).

Advantages
* Not vulnerable to buffer overflow attacks that exploit memory in this way
* Compiler enforces range checks and permissible operations on variables

Disadvantages
* Additional code must be executed at run time to impose checks
* Flexibility and safety comes at a cost in resource use
* Distance from the underlying machine language and architecture means that access to some instructions and hardware resources is lost
* Limits their usefulness in writing code, such as device drivers, that must interact with such resources

1.8.2 Compile-Time Defenses: Safe Coding Techniques

1.8.3 Run-time defenses

1.9 Heap overflow

1.10 Defenses

Two approaches to buffer overflow defense

Compile time
* Aim to harden programs to resist attacks in new programs

Run time
* Aim to detect and abort attacks in existing programs

1.10.1 Compile time

1.10.1.1 Programming language

Examples
15-BufferOverflow/languages.png

1.10.1.1.1 Classic overflow
void copyData(char *userId)
{
    char smallBuffer[10]; // size of 10
    strcpy(smallBuffer, userId);
}

int main(int argc, char *argv[])
{
    // Payload of 11
    char *userId = "01234567890";
    // this shall cause a buffer overload
    copyData(userId);
    return 0;
}

Unsafe functions
15-BufferOverflow/image14.png

Classic overflow fix?

#include <iostream>
#include <cstring>

int main(void)
{
    char strDest[3]= "hi";
    char strSrc[] = "Welcome";
    char anotherCstring[] = "Hello";
    strncpy(strDest, strSrc, 5);
    std::cout << strDest;
    return 0;
}

strncopy can cause another overflow too (no NULL check)

Unsafe functions
15-BufferOverflow/funcs.png

1.10.1.1.2 Format Strings

Some format parameters:
~~~
%x // hexadecimal (unsigned int)
%s // string ((const) (unsigned) char )
%n // number of bytes written so far, (
int)
%d // decimal (int)
%u // unsigned decimal (unsigned int)
~~~

Example:
printf ("Hello:%s\n", a273150);

Issues:
printf (User_Input); // Vulnerability:
// Attack:
"%s%s%s%s%s%s%s%s%s%s%s%s"
printf("%s", str); //Fix:

For every % in the argument the printf function finds, it assumes that there is an associated value on the stack.
In this way, the function walks the stack downwards, reading the corresponding values from the stack, and printing them to the user.

1.10.1.1.3 Integer overflow
int main(void)
{
    int val;
    val = 0x7fffffff;     /* 2147483647*/
    printf("val=%d(0x%x)\n", val, val);
    /*Overflow the int*/
    printf("val+1=%d(0x%x)\n", val + 1, val + 1);
    return 0;
}

Integer overflow

#include <limits.h>

int safe_add(int a, int b)
{
    if(a > 0 && b > INT_MAX - a)
    {
        /* handle overflow */
    }
    else if(a < 0 && b < INT_MIN - a)
    {
        /* handle underflow */
    }
    return a + b;
}
1.10.1.1.4 Array bounds checking

1.10.1.2 Language Extensions/Safe Libraries

1.10.1.3 Stack protection

1.10.2 Run-time defenses

1.10.2.1 Executable address space protection

Overview
* Many of the buffer overflow attacks, such as the stack overflow examples in this chapter, involve copying machine code into the targeted buffer and then transferring execution to it.
* A defense is to block the execution of code on the stack, on the assumption that executable code should only be found elsewhere in the processes address space.
* Making the stack (and heap) non-executable provides a high degree of protection against many types of buffer overflow attacks for existing programs, hence the inclusion of this practice is standard in a number of recent operating systems releases.

Issues
* One issue is support for programs that do need to place executable code on the stack.

1.10.2.2 Address space randomization

1.10.2.3 Random dynamic memory allocation

1.10.2.4 Random standard library locations

1.10.2.5 Guard pages

1.11 Other attack types

1.11.1 Replacement stack frame

1.11.2 Return to system call

Stack overflow variant replaces return address with standard library function
* Response to non-executable stack defenses
* Transfer to system call, and trick the system call to then execute malicious code

Defenses
* Any stack protection mechanisms to detect modifications to the stack frame or return address by function exit code
* Use non-executable stacks
* Randomization of the stack in memory and of system libraries

1.11.3 Heap overflow

1.11.4 Global data overflow

Can attack buffer located in global data
* May be located above program code
* If has function pointer and vulnerable buffer
* Or adjacent process management tables, e.g., with references to destructor function
* Aim to overwrite function pointer later called

Defenses
* Non executable or random global data region
* Move function pointers
* Guard pages

+++++++++++++++++++++++ Cahoot15-2

Next: 16-Databases.html