Software Vulnerabilities -- stack overflow
Code based security Code based security discusses typical vulnerabilities made by programmers that can be exploited by miscreants Implementing safe software in C/C++ is almost impossible However, a huge amount of unsafe codes exist worldwide On the other hand, native codes are still appealing due to performance issues Steps have been taken both by hardware and software vendors: High-level languages: Java (J2EE),.NET framework (C#) ASLR: Address Space Layout Randomization Using safe libraries Input validator Antivirus, IDS NX/XN bit: CPU support for non-executable memory ranges 2
Code based security/buffer overflow Occurs when the boundary of a buffer is exceeded by data thus overwriting adjecent memory locations Typically causing the program to halt with exception Segmentation fault (Linux) Access violation at 0x11223344 (Windows) Can be exploited by overwriting interesting variables, memory locations (return address, pointers, file names,etc) Forcing the program to change its control flow by injecting malicious code Most preferred targets: Setuid/setgid programs Network servers: remote access 3
Code based security/buffer overflow Morris worm (1988): overflow in fingerd 6000 machines are infected (10% of Internet) CodeRed (2001): overflow in Microsoft IIS 300 000 machines are infected in 14 hours SQL Slammer (2003): overflow in MS-SQL server 75 000 machines are infected in 10 minutes Stack Overflow in FreeBSD kernel (2010) In 2003, 75% of vulnerabilities were buffer overflow related according to CERT Today web based vulnerabilities are more common, however, in case of servers it is still essential 4
Code based security/stack overflow Stack has already been introduced Stack overflow can occur when a procedure copies usercontrolled data to a local buffer on the stack without verifying its size. Dangerous functions: strcpy, sprintf, strcat, gets, fgets, Local data overwrites other values on the stack up to return address When the procedure returns EIP is set to the address residing at the location of the return address. control flow can be changed Insert code to that modified address will be executed. 5
Stack Stack is built up from several stack frames belonging to functions. Each stack frame comprises: Function parameters Return address Saved Frame Pointer (Frame pointer of the preceding frame) Local variables Previous frame Higher memory addresses Function parameters Return address Saved EBP (SFP) Local variables Free memory EBP 6
The stack in calling and returning from function addnum LIFO principles Grows towards lower memory addresses ESP: stack pointer, points to the top of the stack 7
mov dword ptr [b],3 ; Moving 3 to the address pointed by variable b mov eax,dword ptr [b]; Storing that value in register eax push eax ; Pushing b to stack and decreasing ESP its widthness 3 (b) int main(void){ int a, b, c; a=7; b=3; c = addnum(a,b); printf("result is: %d", a+b); 8
mov dword ptr [a],7 ; Moving 7 to the address pointed by variable a mov ecx,dword ptr [a]; Storing that value in register ecx push ecx ; Pushing a to stack and decreasing ESP by its widthness 3 (b) 7 (a) int main(void){ int a, b, c; a=7; b=3; c = addnum(a,b); printf("result is: %d", a+b); 9
call addnum ; pushing the address of the next instruction (return addr.) ; (0x00411459) to the stack and calling function addnum & ; decreasing esp 3 (b) 7 (a) 0x00411459 (ret addr.) int main(void){ int a, b, c; a=7; b=3; c = addnum(a,b); printf("result is: %d", a+b); 10
Every function starts with function prologue: push ebp ; Saves the previous frame pointer (EBP also called Saved FP) mov ebp,esp ; Currently the EBP points to SFP sub esp, 0x10 ; Saving space for the local variables of the function 3 (b) 7 (a) 0x00411459 (ret addr.) Saved EBP (SFP) int addnum(int a, int b){ int c = 4; c = a + b; return c; 11
Every function starts with function prologue: push ebp ; Saves the previous frame pointer (EBP also called Saved FP) mov ebp,esp ; Currently the EBP points to SFP sub esp, 0x10 ; Saving space for the local variables of the function 3 (b) 7 (a) 0x00411459 (ret addr.) Saved EBP (SFP),EBP int addnum(int a, int b){ int c = 4; c = a + b; return c; 12
Every function starts with function prologue: push ebp ; Saves the previous frame pointer (EBP also called Saved FP) mov ebp,esp ; Currently the EBP points to SFP sub esp, 0x10 ; Saving space for the local variables of the function 3 (b) 7 (a) 0x00411459 (ret addr.) Saved EBP (SFP) Space for local variables EBP int addnum(int a, int b){ int c = 4; c = a + b; return c; 13
Every function ends with function epilogue. mov esp,ebp ; restoring the stack pointer to SFP, unallocating space for locals pop ebp ; restoring the value of EBP thus point into SFP of preceding frame ret ; popping return address and returning to that, increasing ESP 3 (b) 7 (a) 0x00411459 (ret addr.) Saved EBP (SFP) EBP, ESP int addnum(int a, int b){ int c = 4; c = a + b; return c; 14
Every function ends with function epilogue. mov esp,ebp ; restoring the stack pointer to SFP, unallocating space for locals pop ebp ; restoring the value of EBP thus point into SFP of preceding frame ret ; popping return address and returning to that, increasing ESP 3 (b) 7 (a) 0x00411459 (ret addr.) int addnum(int a, int b){ int c = 4; c = a + b; return c; 15
Every function ends with function epilogue. mov esp,ebp ; restoring the stack pointer to SFP, unallocating space for locals pop ebp ; restoring the value of EBP thus point into SFP of preceding frame ret ; popping return address and returning to that, increasing ESP 3 (b) 7 (a) int addnum(int a, int b){ int c = 4; c = a + b; return c; 16
add esp,8 ; decreasing the stack after the RET instruction of addnum 3 (b) 7 (a) int main(void){ int a, b, c; a=7; b=3; c = addnum(a,b); printf("result is: %d", a+b); 17
Code based security/stack overflow int main(int argc, char* argv[] ) { dangereous(argv[1]); printf( Is everything all right? ); void dangerous(char * buf){ char buffer[100]; strcpy(buffer, buf); Previous frame Higher memory addresses Previous frame Function parameters Function parameters Return address buffer address Saved EBP (frame pointer) EBP SHELLCODE buffer[100] Free memory 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 Free 0x90 memory 0x90 0x90 NOP sled 18
Code based security/stack overflow NOP sled: Put in front of the shellcode and jump into that area. Instructions should always reach the beginig of the shellcode. The simplest version is a sequence of 0x90 (no operations - nop) Reason to apply: Bigger chance to find our shellcode On local systems the position of return address can be calculated (no ASLR) Remote addresses are unknown Where to put the shellcode? Into the local buffer with a preceeding nop sled Remote attacks possible, but the memory page the buffer residing at must be executable. The location of the buffer must be known. Into Environment variables Easy to implement. Good for tiny buffers, however, only for local attacks. Stack must be executable. Address of a function inide the program Remote attacks possible with no executable stack. More frames to put on stack. 19
Memory segmentation (ELF binaries) 0xFFFFFFFF Kernel Environment variables Stack Data segment (heap) Data segment (.bss) Data segment (.data) Code segment (.text) Stack segment includes Local variables Values required for procedure call Data segment heap: dynamically allocated memory. bss: Uninitialized global & static variables.data: Initialized global & static vairbales Code Segment: Executable instructions Typically read-only Shared libraries 20
Code based security/software ASLR There are many workarounds for protecting against stack and heap overflow. One of the most effective ones is ASLR: Address Space Layout (Load) Randomization Randomizes the base address of stack and heap. Stack Heap RND RND void alt_main(int argc, char* argv[]){... void spamstack(int i, int ac, char* av[] ){ if (! i) alt_main(ac, av); spamstack(--i); int main(int argc, char* argv[]){ srand ( time(null) ); malloc(rand() % 123456 + 1); // rnd heap spamstack(rand() % 123456 + 1, argc, argv); 21