buffer overflows

Click here to load reader

Post on 22-Feb-2016




0 download

Embed Size (px)


Buffer Overflows. James Walden Northern Kentucky University. Topics. What is a Buffer Overflow? Buffer Overflow Examples Program Stacks Smashing the Stack Shellcode Mitigations. Buffer Overflows. A program accepts too much input and stores it in a fixed length buffer that’s too small. - PowerPoint PPT Presentation



Buffer OverflowsJames WaldenNorthern Kentucky University1CSC 666: Secure Software EngineeringTopicsWhat is a Buffer Overflow?Buffer Overflow ExamplesProgram StacksSmashing the StackShellcodeMitigationsCSC 666: Secure Software EngineeringBuffer OverflowsA program accepts too much input and stores it in a fixed length buffer thats too small.char A[8];short B=3;AAAAAAAABB0000000003AAAAAAAABBoverflows0gets(A);CSC 666: Secure Software EngineeringBuffer Overflow ExamplesMorris WormTook down most of Internet in 1988.Exploited a buffer overflow in fingerd.Subsequent worms used overflow attacks too.CVE-2012-4172: Adobe ShockwaveOverflow in Shockwave Player gcc -o buffer buffer.c> ./buffer70778765CSC 666: Secure Software EngineeringBuffer Overflow Example #2Writing beyond the buffer:int main() { int array[5] = {1, 2, 3, 4, 5}; int i;

for( i=0; i gcc -o bufferw bufferw.c> ./bufferwSegmentation fault (core dumped)6CSC 666: Secure Software EngineeringWhat happened to our program?The buffer overflow:Overwrote memory beyond buffer with 41.Memory page was not writable by program.OS terminated prog with segmentation fault.Do overflows always produce a crash?Most of the time, yes.Careful attacker can access valid memory.7CSC 666: Secure Software EngineeringWhy do we keep making the same mistake?C/C++ inherently unsafe.No bounds checking.Unsafe library functions: strcpy(), sprintf(), gets(), scanf(), etc.D, Java, Python, Ruby largely immune.C/C++ gains performance by not checking.8CSC 666: Secure Software Engineering Process Memory Layoutargv, envstackheapbssdatatexthigh mem

low memArgv/Env: CLI args and environmentStack: generally grows downwardsHeap: generally grows upwardsBSS: unitialized global dataData: initialized global dataText: read-only program code9Memory segments have access protections: r, w, x.Text is usually read-only and may be shared between processes.CSC 666: Secure Software EngineeringMemory Layout Example/* data segment: initialized global data */int a[] = { 1, 2, 3, 4, 5 };/* bss segment: uninitialized global data */int b;

/* text segment: contains program code */int main(int argc, char **argv) /* ptr to argv */{ /* stack: local variables */ int *c; /* heap: dynamic allocation by new or malloc */ c = (int *)malloc(5 * sizeof(int));}CSC 666: Secure Software EngineeringProgram Stack Layoutb() {}a() { b();}main() { a();}UnallocatedStack Frame for b()Stack Frame for a()Stack Frame for main()High MemoryLow MemoryCSC 666: Secure Software EngineeringStack FramesA function call produces a stack frame.Return address of the caller.Actual arguments used in function call.Local variables.Register EBP points to current frame.Stack frame is deallocated on return.CSC 666: Secure Software EngineeringC Calling ConventionPush params on stack in reverse order.Parameter #NParameter #1Issue a call instruction.Pushes address of next instruction (the return address) onto stack.Modifies EIP to point to start of function.CSC 666: Secure Software EngineeringStack before Function Executes Frame Pointer

Stack Pointerold stack frameparameter #Nparameter #1return address14FP points at top of old frame.call statement places old PC onto stackCSC 666: Secure Software EngineeringFunction InitializationFunction pushes FP (%ebp) onto stack.pushl %ebpSets FP to current SP.Allows function to access params as fixed indexes from frame pointer.movl %esp, %ebpReserves stack space for local vars.subl $12, %espCSC 666: Secure Software EngineeringStack at Function Start Frame Pointer

Stack Pointerold stack frameparameter #Nparameter #1return addressold FPlocal vars16FP still points at new frame.SP points at current top of stack, moving with local var allocation/deallocation.CSC 666: Secure Software EngineeringFunction ReturnStores return value in %eax.movl $1, %eaxRestores stack and frame pointers.movl %esp, %ebppopl %ebpPops return address off stack and transfers control to that address. retCSC 666: Secure Software EngineeringControlling ExecutionLets make the program an infinite loop by changing the return value to start of main().

(gdb) disassemble mainDump of assembler code for main:0x080483c1 : push %ebp0x080483c2 : mov %esp,%ebp0x080483c4 : call 0x804839c 0x080483c9 : leave0x080483ca : retCSC 666: Secure Software EngineeringSending a non-ASCII Valuevoid main() { char addr[44]; int i; for( i=0; i gcc ggdb static o shell shellcode.c> ./shellsh-3.00$ exitCSC 666: Secure Software EngineeringFrom C to Machine Languagechar shellcode[] ="\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b""\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd""\x80\xe8\xdc\xff\xff\xff/bin/sh";

void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode;}

> gcc -o testsc2 testsc2.c> ./testsc2sh-3.00$ exitCSC 666: Secure Software EngineeringWriting an ExploitConstruct shellcode to inject.Find exploitable buffer in a program.Estimate address of buffer.Run program with an input that:Injects shellcode into stack memory.Overwrites return address with address of your shellcode.CSC 666: Secure Software EngineeringImproving the OddsDetermining the correct address of your shellcode is difficult.What if you could use multiple addrs?Pad buffer with NOP instructions preceding the shellcode.If function returns anywhere in NOP pad, it will continue executing until it executes the shellcode.CSC 666: Secure Software EngineeringOverflow Exploits w/o the StackOverflows can exist in other segments.Only the stack has return addresses.Must rewrite other addressesFunction pointersLongjmp buffersOr alter security critical variables.CSC 666: Secure Software EngineeringBuffer Overflow MitigationsUse language with bounds checking.Do your own bounds checking.Avoid unsafe functions.Use safe functions securely.Operating system defenses.Compiler-based defenses.29CSC 666: Secure Software EngineeringLanguages with Bounds CheckingHigh-level languages do bounds checksJavaJavaScriptOCamlPythonRubySchemeSmalltalkC variantsCCuredCycloneD

30Image from http://www.research.att.com/viewProject.cfm?prjID=67CSC 666: Secure Software EngineeringBounds CheckingCheck input length before copying into buffer.

int myfunction(const char *str) { char buf[1024];/* strlen() doesnt count NULL */ if (strlen(str) >= sizeof(buf)) { /* str too long */ exit(1); }}31If strlen(str) returns 1024, str is actually 1025 bytes long because of the NULL terminator, and thus the string is too large to be copied into buf, which has only 1024 bytes of space.CSC 666: Secure Software EngineeringUnsafe Functions: Inputgets(char *s)Always an overflow. Cannot be checked.Use fgets(char *s, int size, FILE *stream);scanf(const char *fmt, )Similar: _tscanf, wscanf, sscanf, fscanf, Use of %s format allows overflow.Use %Ns to limit length of input.CSC 666: Secure Software EngineeringUnsafe Functions: strcatstrcpy(char *dst, char *src)Similar: wscpy, wcscpy, mbscpyOverflow if dst smaller than src.strncpy(char *dst, const char *src, size_t n)Similar: _tcsncpy, wcscpyn, _mbsncpy, No NULL termination if src >= dst.

CSC 666: Secure Software EngineeringBounded Function PitfallsDestination buffer overflows because bound depends on size of source data, not destination buffer.Destination buffer left without null terminator, often as result of off-by-one error.Destination buffer overflows because its bound is specified as the total size of the buffer, rather than space remaining.Programs writes to arbitrary location in memory as destination buffer is not null-terminated and function begins writing at location of first null in destination buffer.CSC 666: Secure Software EngineeringSafe String LibrariesUNIX LibrariesCBstrlibMT-SafeSafeStrstrlcpy(), strlcat()VstrC++std::string (STL)Windows LibrariesCSafe CRTstrlcpy(), strlcat()StrSafeC++CString (MFC)Safe C++std::string (STL)35C++ can be used with C-style strings in dangerous ways (see example in a few slides.)CSC 666: Secure Software Engineeringstrlcpy() and strlcat()size_t strlcpy (char *dst, const char *src, size_t size); size_t strlcat (char *dst, const char *src, size_t size);

Size is max size of dest buffer (not maximum number of chars to copy), including NULL.Destination buffer always NULL terminatedReturn how much space would be required in destination buffer to perform operation.BSD-style open source license.36strlcat() and strlcpy() exist.CSC 666: Secure Software EngineeringCharacter SetsChars represented using encoding forms that map code points to printable chars.Fixed WidthISO-8859-1UTF-32Variable WidthUTF-8UTF-16 (Java, .NET)CharacterEncodingCode PointsISO-8859-1UTF-87373ISO-8859-1UTF-8FFC3 BFCSC 666: Secure Software EngineeringWide CharactersC/C++char contains 1-byte characterswchar_t is 2-byte, 4-byte on some platformsJava and .NET stringsUTF-16Buffer Overflow issuesMixing up different character-set string types.Are sizes measured in bytes or characters?CSC 666: Secure Software EngineeringC++ String DangersUsing C-style strings with cinchar username[16];cin >> username;The [] operator does no bounds checking.Converting from C++ to C-style strings:string::data() output is not NULL terminated.string::c_str() output is NULL terminated.CSC 666: Secure Software EngineeringDealing with Overly Long InputsPrevent operation with an error message.Possibly exit program too.Truncate input to allowed length.Can lead to null-termination errors.Can cause input to be misinterpreted later.Resize the buffer to accomodate input.Limit resizing to avoid memory DoS.CSC 666: Secure Software EngineeringDynamic vs. Static AllocationStaticSimpleEasy to track buffer size for bounds checks.Inflexible.Limited options if size is too small.Waste memory if size is too large.DynamicComplexManually tracking buffer sizes can lead to overflows due to stale size data.FlexibleCan lead to memory exhaustion if no limits.Possibility of use after free and double free errors.CSC 666: Secure Software EngineeringNon-executable Stack Memory protection prevents exploit code from being executed.Some applications execute code on the stack/heap.x86 arch doesnt have exec bit in page tables.Segment limits can divide memory into two parts: executable and non-executable.Keep program code in low memory.Keep data and stack in high memory.Coarse-grained.NX TechnologyExec bit for page tables.Added in AMD64 and newer Intel P4 processors.Only works in PAE 64-bit page table format.

CSC 666: Secure Software EngineeringReturn-Oriented ProgrammingROP transfers control to code that already exists in memory.Put function arguments on stack.Change return address to that function.libc has functions to start a shell.Allows exploit even if stack non-executable.Sophisticated ROP attacks create multiple stack frames to run multiple functions that are in memory.CSC 666: Secure Software EngineeringAddress RandomizationRandomize layout of memory spaceStack location.Shared library locations.Heap location.PIE: Position Independent ExecutableDefault format: binary compiled to work at an address selected when program was compiled.Gcc can compile binaries to be freely relocatable throughout address space.gcc flags: -fpie pieProgram loaded at different address for each invocation.CSC 666: Secure Software EngineeringDefence: StackguardCompiler extension for gcccode must be compiled w/ StackguardDetects altered return addressbefore function returnsadds canary word to stackmust overwrite canary to change return addruse random canary words for each function to avoid guessing attacksCSC 666: Secure Software EngineeringStackguard Stack Layout Frame Pointer Stack Pointerold frameparam1param2old PCcanary wordold FPlocal vars46FP still points at new frame.SP points at current top of stack, moving with local var allocation/deallocation.CSC 666: Secure Software EngineeringStackguard EffectivenessCode dependenciesare dynamic libraries stackguarded?CompatibilityRecompiled entire RedHat Linux system.Small performance costcanary insert and check overhead on each callProtects against future stack attacks.Similar tools:gcc -fstack-protector flagVisual Studio 200547Visual Studio 2003 had /gs flag, but 2005 better and on by default.Gcc 4.1 will include Propolice (-fstack-protector) by default, but many Linux distributions include Propolice in their gcc already.CSC 666: Secure Software EngineeringBuffer Overflow: Key PointsBuffer overflow attacks.C/C++ perform no bounds checking.There is no difference btw code and data.Smashing the stack.Mitigating buffer overflows.Use a language with bounds checking.Check your own bounds in C/C++.Use safe functions, string libraries.ReferencesAleph Null, Smashing the Stack for Fun and Profit, Phrack 49, 1996.Brian Chess and Jacob West, Secure Programming with Static Analysis, Addison-Wesley, 2007.Johnathan Bartlett, Programming from the Ground Up, Bartlett Publishing, 2004.Matt Conover & w00w00 Security Team, w00w00 on Heap Overflows, http://www.w00w00.org/files/articles/heaptut.txtMark Graff and Kenneth van Wyk, Secure Coding: Principles & Practices, OReilly, 2003.Horizon, Bypassing Non-executable Stack Protection on Solaris, http://packetstormsecurity.nl/groups/horizon/stack.txtGreg Hoglund and Gary McGraw, Exploiting Software: How to Break Code, Addison-Wesley, 2004.Michael Howard and David LeBlanc, Writing Secure Code, 2nd edition, Microsoft Press, 2003.Koziol, et. al, The Shellcoders Handbook: Discovering and Exploiting Security Holes, Wiley, 2004.Robert C. Seacord, Secure Coding in C and C++, Addison-Wesley, 2006.John Viega and Gary McGraw, Building Secure Software, Addison-Wesley, 2002.David Wheeler, Secure Programming for UNIX and Linux HOWTO, http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/index.html, 2003.