170 likes | 174 Views
Bride of Buffer Overflow. Chapter 7. Chapter Synopsis. Integers Wrap around errors Truncation and sign extension Conversions between unsigned and signed Methods to detect and prevent problems Runtime Protection Safe Programming Lanuages Safer C Dialects
E N D
Bride of Buffer Overflow Chapter 7
Chapter Synopsis • Integers • Wrap around errors • Truncation and sign extension • Conversions between unsigned and signed • Methods to detect and prevent problems • Runtime Protection • Safe Programming Lanuages • Safer C Dialects • Dynamic Buffer Overflow protections
The Problem • Numbers in computers are not integers but only an approximation. They are bounded, have a sign, representation, etc. • Many arithmetic operations, many conversions have a risk of returning non-sense values due to machine limitations. • When this non-sense value is used for memory allocation, bound a string operation or index into a buffer, we have a buffer overflow.
An example • An Integer Overflow causing a Buffer overflow: u_int nresp; nresp = packet_get_int(); if ( nresp > 0 ) { response = xmalloc(nresp*sizeof(char *)); for (i = 0; i < nresp; i++) response[i] = packet_get_string(NULL); } • Value of nresp = 1073741824 causes problems.
Other Problems • Subtracting from 0 can also cause problems. • (example, page 238) (next slide)
Bad subtract from 0 unsigned int readamt; readamt =getstringsize(...); if ( readamt > 1024 ) return -1; readamt--; // don't allocate space for '\n' buf = malloc(readamt)
Truncation and sign extension • When integers get truncated, the most significant part is lost; when they get expanded, the most significant bit is extended, sometimes with unexpected results. • Examples: • -1 truncated to 4 bits is 15; • 4 bit 7 expanded is still 7, but • 4 bit 15 (unsigned) can become -1!
Conversion between signed and unsigned • The problem is the high-order bit: the semantics are different, the meaning is different. Bad example: char *a; short len = ????; if (len < 1024 ) a = malloc((int)len); . .
What to do? • Use Unsigned types (watch out, though) • Expect bad assumptions • Restrict numeric User input: use santy checks • Sanity check values used to allocate and access memory • Respect compiler warnings. • Use best practices for your compiler • Understand Integer Conversion rules • Verify overflow of operators
Use Best Practices for CL from MSDN • Compile with highest possible warning level: /W4 • Watch out for integer related compiler warnings • Investigate all #pragma disabling overflows • Enable runtime integer error checks for conversion overflows with /RTCc (for debugging only)
Use Best Practices for gcc • Compile with -wconversion -wsign-compare • Check all #pragma disabling diagnostics. • Enable runtime error checks with -ftrapv (not for production runs)
Understand Integer Conversion rules • Plethora of rules but most important ones: • Less precision is usually upcast to higher precision but • An unsigned type can be implicitly cast to a signed type even if not all values can be represented.
Use Special Libraries • SafeInt • IntSafe
Safer Programming Languages/Dialects • Safe Programming Languages like: • Java • C# • Python • Ruby • Safe dialects of C/C++ like: • Ccured • Cyclone
Dynamic Buffer Overflow Protections • Not a fix: • Non-executable memory segments • Compile-Time Instrumentation (“canaries”) • Virtual Execution Environments • Hardened System Libraries