Question? Leave a message!




Secure Coding in C and C++

Secure Coding in C and C++ 24
Secure Coding in C and C++ Integral Security Robert C. Seacord FIRST Conference : June 26, 2006 © 2006 Carnegie Mellon Universityƒƒƒ About this Presentation Derived from the AddisonWesley book “Secure Coding in C and C++” Presentation assumes basic C/C++ programming skills but does not assume in depth knowledge of software security Ideas generalize but examples are specific to Microsoft Visual Studio Linux/GCC 32bit Intel Architecture (IA32) © 2006 Carnegie Mellon University 2ƒƒ An Integer Story 1 GNU’s Bourne Again Shell (bash) is a dropin replacement for the Bourne shell (/bin/sh). same syntax as the standard shell but provides additional functionality such as job control, commandline editing, and history. most prevalent use is on Linux. A vulnerability exists in bash versions 1.14.6 and earlier where bash can be tricked into executing arbitrary commands. © 2006 Carnegie Mellon University 3An Integer Story 2 Bash contains an incorrectly declared variable in the yystringget() function responsible for parsing the userprovided command line into separate tokens. The error involves the variable string, which has been declared to be of type char . The string variable is used to traverse the character string containing the command line to be parsed. © 2006 Carnegie Mellon University 4An Integer Story 3 As characters are retrieved from this pointer, they are stored in a variable of type int. For compilers in which the char type defaults to signed char, this value is signextended when assigned to the int variable. For character code 255 decimal (1 in two’s complement form), this sign extension results in the value 1 being assigned to the integer. 1 is used in other parts of the parser to indicate the end of a command. © 2006 Carnegie Mellon University 5ƒ An Integer Story 4 The character code 255 decimal (377 octal) serves as an unintended command separator for commands given to bash via the c option. Example: bash c 'ls\377who' (where \377 represents the single character with value 255 decimal) executes two commands, ls and who. © 2006 Carnegie Mellon University 6ƒƒ Integer Security Integers represent a growing and underestimated source of vulnerabilities in C and C++ programs. Integer range checking has not been systematically applied in the development of most C and C++ software. security flaws involving integers exist a portion of these are likely to be vulnerabilities © 2006 Carnegie Mellon University 7Unexpected Integer Values An unexpected value is a value other than the one you would expect to get using a pencil and paper Unexpected value are a common source of software vulnerabilities (even when this behavior is correct). © 2006 Carnegie Mellon University 8Integer Agenda Integers Vulnerabilities Mitigation Strategies Notable Vulnerabilities Summary © 2006 Carnegie Mellon University 9Integer Section Agenda Representation Types Conversions Error conditions Operations © 2006 Carnegie Mellon University 10Integer Representation Signed magnitude One’s complement Two’s complement These integer representations vary in how they represent negative numbers. © 2006 Carnegie Mellon University 11ƒƒƒ SignedMagnitude Representation Uses the highorder bit to indicate the sign 0 for positive 1 for negative remaining loworder bits indicate the magnitude of the value 001 0 1001 101 0 1001 32 + 8 + 1 32 + 8 + 1 41 + 41 Signedmagnitude representation of +41 and 41 © 2006 Carnegie Mellon University 12One’s Complement One’s complement replaced signed magnitude because the circuitry was too complicated. Negative numbers are represented in one’s complement form by complementing each bit 0 0 1 0 1 0 0 1 each 1 is even the replaced sign bit is with a 0 1 1 0 1 0 1 1 0 reversed each 0 is replaced with a 1 © 2006 Carnegie Mellon University 13Two’s Complement The two’s complement form of a negative integer is created by adding one to the one’s complement representation. 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 1 1 0 1 0 1 1 0 + 1 = 1 1 0 1 0 1 1 1 Two’s complement representation has a single (positive) value for zero. The sign is represented by the most significant bit. The notation for positive integers is identical to their signed magnitude representations. © 2006 Carnegie Mellon University 14Integer Section Agenda Representation Types Conversions Error conditions Operations © 2006 Carnegie Mellon University 15Signed and Unsigned Types Integers in C and C++ are either signed or unsigned. For each signed type there is an equivalent unsigned type. © 2006 Carnegie Mellon University 16Signed Integers Signed integers are used to represent positive and negative values. On a computer using two’s complement n1 arithmetic, a signed integer ranges from 2 n1 through 2 1. © 2006 Carnegie Mellon University 17Signed Integer Representation © 2006 Carnegie Mellon University 18Unsigned Integers Unsigned integer values range from zero to a maximum that depends on the size of the type This maximum value can be calculated as n 2 1, where n is the number of bits used to represent the unsigned type. © 2006 Carnegie Mellon University 19Unsigned Integer Representation two’s complement © 2006 Carnegie Mellon University 20ƒƒƒƒƒ Standard Integer Types Standard integers include the following types, in nondecreasing length order: signed char short int int long int long long int © 2006 Carnegie Mellon University 21ƒƒƒ Other C99 Integer Types The following types are used for special purposes ptrdifft is the signed integer type of the result of subtracting two pointer sizet is the unsigned result of the sizeof operator wchart is an integer type whose range of values can represent distinct codes for all members of the largest extended character set specified among the supported locales. © 2006 Carnegie Mellon University 22ƒƒƒƒƒƒƒƒƒƒ PlatformSpecific Integer Types Vendors often define platformspecific integer types. The Microsoft Windows API defines a large number of integer types: int8, int16, int32, int64 ATOM BOOLEAN, BOOL BYTE CHAR DWORD, DWORDLONG, DWORD32, DWORD64 WORD INT, INT32, INT64 LONG, LONGLONG, LONG32, LONG64 Etc. © 2006 Carnegie Mellon University 23ƒƒƒ Integer Ranges Minimum and maximum values for an integer type depend on the type’s representation signedness the number of allocated bits The C99 standard sets minimum requirements for these ranges. © 2006 Carnegie Mellon University 24Example Integer Ranges signed char signed char 1 1 12 2 28 8 8 127 127 127 0 0 0 unsigne unsigned cha d char r 255 255 255 0 0 0 short short 3 3 32768 2768 2768 32767 32767 32767 0 0 0 unsigne unsigned sho d shor rt t 65535 65535 65535 0 0 0 © 2006 Carnegie Mellon University 25Integer Section Agenda Representation Types Conversions Error conditions Operations © 2006 Carnegie Mellon University 26ƒƒƒ Integer Conversions Type conversions occur explicitly in C and C++ as the result of a cast or implicitly as required by an operation. Conversions can lead to lost or misinterpreted data. Implicit conversions are a consequence of the C language ability to perform operations on mixed types. C99 rules define how C compilers handle conversions: integer promotions integer conversion rank usual arithmetic conversions © 2006 Carnegie Mellon University 27ƒƒ Integer Promotions Integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int the value of the smaller type is converted to int otherwise, it is converted to unsigned int Integer promotions are applied as part of the usual arithmetic conversions. © 2006 Carnegie Mellon University 28Integer Promotion Example Integer promotions require the promotion of each variable (c1 and c2) to int size. char c1, c2; c1 = c1 + c2; The two ints are added and the sum truncated to fit into the char type. Integer promotions avoid arithmetic errors from the overflow of intermediate values. © 2006 Carnegie Mellon University 29Implicit Conversions 1. char cresult, c1, c2, c3; The sum of c1 and c2 exceeds the 2. c1 = 100; maximum size of signed char. 3. c2 = 90; However, c1, c2, and c3 are each converted to integers and the overall 4. c3 = 120; expression is successfully evaluated. 5. cresult = c1 + c2 + c3; The value of c1 is added The sum is truncated and to the value of c2. stored in cresult without a loss of data. © 2006 Carnegie Mellon University 30Integer Conversion Rank Every integer type has an integer conversion rank that determines how conversions are performed. © 2006 Carnegie Mellon University 31Integer Conversion Rank Rules No two signed integer types have the same rank, even if they have the same representation. The rank of a signed integer type is the rank of any signed integer type with less precision. The rank of long long int is the rank of long int, which is the rank of int, which is the rank of short int, which is the rank of signed char. The rank of any unsigned integer type is equal to the rank of the corresponding signed integer type. © 2006 Carnegie Mellon University 32Usual Arithmetic Conversions If both operands have the same type, no conversion is needed. If both operands are of the same integer type (signed or unsigned), the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank. If the operand that has unsigned integer type has rank = the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type. If the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type is converted to the type of the operand with signed integer type. Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type. © 2006 Carnegie Mellon University 33ƒƒƒƒ Unsigned Integer Conversions 1 Conversions of smaller unsigned integer types to larger unsigned integer types is always safe typically accomplished by zeroextending the value When a larger unsigned integer is converted to a smaller unsigned integer type, the larger value is truncated loworder bits are preserved © 2006 Carnegie Mellon University 34ƒƒ Unsigned Integer Conversions 2 When unsigned integer types are converted to the corresponding signed integer type the bit pattern is preserved so no data is lost the highorder bit becomes the sign bit If the sign bit is set, both the sign and magnitude of the value change. © 2006 Carnegie Mellon University 35From To Method unsigned char char Preserve bit pattern; highorder bit becomes sign bit char short Zeroextend char long Zeroextend char unsigned Zeroextend short char unsigned long Zeroextend short char Preserve loworder byte short short Preserve bit pattern; highorder bit becomes sign bit short long Zeroextend short unsigned char Preserve loworder byte long char Preserve loworder byte long short Preserve loworder word long long Preserve bit pattern; highorder bit becomes sign bit long unsigned char Preserve loworder byte long unsigned Preserve loworder word short Key: Lost data Misinterpreted data © 2006 Carnegie Mellon University 36ƒƒ Signed Integer Conversions 1 When a signed integer is converted to an unsigned integer of equal or greater size and the value of the signed integer is not negative the value is unchanged the signed integer is signextended A signed integer is converted to a shorter signed integer by truncating the highorder bits. © 2006 Carnegie Mellon University 37ƒƒ Signed Integer Conversions 2 When signed integer types are converted to the corresponding unsigned integer type bit pattern is preserved—no lost data highorder bit loses its function as a sign bit If the value of the signed integer is not negative, the value is unchanged. If the value is negative, the resulting unsigned value is evaluated as a large, unsigned integer. © 2006 Carnegie Mellon University 38From To Method char short Signextend char long Signextend char unsigned char Preserve pattern; highorder bit loses function as sign bit char unsigned short Signextend to short; convert short to unsigned short char unsigned long Signextend to long; convert long to unsigned long short char Preserve loworder byte short long Signextend short unsigned char Preserve loworder byte short unsigned short Preserve bit pattern; highorder bit loses function as sign bit short unsigned long Signextend to long; convert long to unsigned long long char Preserve loworder byte long short Preserve loworder word long unsigned char Preserve loworder byte long unsigned short Preserve loworder word long unsigned long Preserve pattern; highorder bit loses function as sign bit Key: © 2006 Carnegie Mellon University 39 Lost data Misinterpreted dataSigned Integer Conversion Example 1. unsigned int l = ULONGMAX; 2. char c = 1; The value of c is compared to the 3. if (c == l) value of l. 4. printf("1 = 4,294,967,295\n"); 5. Because of integer promotions, c is converted to an unsigned integer with a value of 0xFFFFFFFF or 4,294,967,295. © 2006 Carnegie Mellon University 40Signed/Unsigned Characters The type char can be signed or unsigned. When a signedchar with its high bit set is saved in an integer, the result is a negative number. Use unsigned char for buffers, pointers, and casts when dealing with character data that may have values greater than 127 (0x7f). © 2006 Carnegie Mellon University 41Integer Section Agenda Representation Types Conversions Error conditions Operations © 2006 Carnegie Mellon University 42ƒƒƒ Integer Error Conditions Integer operations can resolve to unexpected values as a result of an overflow sign error truncation © 2006 Carnegie Mellon University 43Overflow An integer overflow occurs when an integer is increased beyond its maximum value or decreased beyond its minimum value. Overflows can be signed or unsigned. A signed overflow An unsigned overflow occurs when a value is occurs when the underlying carried over to the sign representation can no longer bit. represent a value. © 2006 Carnegie Mellon University 44Overflow Examples 1 1. int i; 2. unsigned int j; 3. i = INTMAX; // 2,147,483,647 4. i++; i=2,147,483,648 5. printf("i = d\n", i); 6. j = UINTMAX; // 4,294,967,295; 7. j++; j = 0 8. printf("j = u\n", j); © 2006 Carnegie Mellon University 45Overflow Examples 2 9. i = INTMIN; // 2,147,483,648; 10. i; i = 2,147,483,647 11. printf("i = d\n", i); 12. j = 0; 13. j; 14. printf("j = u\n", j); j = 4,294,967,295 © 2006 Carnegie Mellon University 46ƒƒ Truncation Errors Truncation errors occur when an integer is converted to a smaller integer type and the value of the original integer is outside the range of the smaller type Loworder bits of the original value are preserved and the highorder bits are lost. © 2006 Carnegie Mellon University 47Truncation Error Example 1. char cresult, c1, c2, c3; 2. c1 = 100; Adding c1 and c2 exceeds the max size of signed char (+127) 3. c2 = 90; 4. cresult = c1 + c2; Truncation occurs when the Integers smaller than int value is assigned to a type are promoted to int or that is too small to represent unsigned int before being the resulting value operated on © 2006 Carnegie Mellon University 48ƒƒ Sign Errors Can occur when converting an unsigned integer to a signed integer converting a signed integer to an unsigned integer © 2006 Carnegie Mellon University 49ƒƒƒƒƒ Converting to Signed Integer Converting an unsigned integer to a signed integer of equal size preserve bit pattern; highorder bit becomes sign bit greater size the value is zeroextended then converted lesser size preserve loworder bits If the highorder bit of the unsigned integer is not set the value is unchanged set results in a negative value © 2006 Carnegie Mellon University 50ƒƒƒƒƒ Converting to Unsigned Integer Converting a signed integer to an unsigned integer of equal size bit pattern of the original integer is preserved greater size the value is signextended then converted lesser size preserve loworder bits If the value of the signed integer is not negative the value is unchanged negative a (typically large) positive value © 2006 Carnegie Mellon University 51Sign Error Example 1. int i = 3; 2. unsigned short u; Implicit conversion to smaller unsigned integer 3. u = i; 4. printf("u = hu\n", u); There are sufficient bits to represent the value so no truncation occurs. The two’s complement representation is interpreted as a large signed value, however, so u = 65533. © 2006 Carnegie Mellon University 52Integer Section Agenda Representation Types Conversions Error conditions Operations © 2006 Carnegie Mellon University 53ƒƒ Integer Operations Integer operations can result in errors and unexpected values. Unexpected integer values can cause unexpected program behavior security vulnerabilities Most integer operations can result in exceptional conditions. © 2006 Carnegie Mellon University 54Integer Addition Addition can be used to add two arithmetic operands or a pointer and an integer. If both operands are of arithmetic type, the usual arithmetic conversions are performed on them. Integer addition can result in an overflow if the sum cannot be represented in the allocated bits. © 2006 Carnegie Mellon University 55ƒƒƒ Add Instruction IA32 instruction set includes an add instruction that takes the form add destination, source Adds the 1st (destination) op to the 2nd (source) op Stores the result in the destination operand Destination operand can be a register or memory location Source operand can be an immediate, register, or memory location Signed and unsigned overflow conditions are detected and reported. © 2006 Carnegie Mellon University 56ƒƒƒƒ Add Instruction Example The instruction add eax, ebx adds the 32bit ebx register to the 32bit eax register leaves the sum in the eax register The add instruction sets flags in the flags register overflow flag indicates signed arithmetic overflow carry flag indicates unsigned arithmetic overflow © 2006 Carnegie Mellon University 57Layout of the Flags Register 0 15 Overflow Direction Interrupt Sign Zero Auxiliary Carry Parity Carry © 2006 Carnegie Mellon University 58Interpreting Flags There are no distinctions between the addition of signed and unsigned integers at the machine level. Overflow and carry flags must be interpreted in context. © 2006 Carnegie Mellon University 59Adding signed and unsignedint Both signed int and unsigned int values are added as follows: si1 + si2 7. mov eax, dword ptr ui1 8. add eax, dword ptr ui2 © 2006 Carnegie Mellon University 60Adding signed long long int The add instruction adds the loworder 32 bits sll1 + sll2 9. mov eax, dword ptr sll1 10. add eax, dword ptr sll2 11. mov ecx, dword ptr ebp98h 12. adc ecx, dword ptr ebp0A8h The adc instruction adds the highorder 32 bits and the value of the carry bit © 2006 Carnegie Mellon University 61ƒƒƒƒ Unsigned Overflow Detection The carry flag denotes an unsigned arithmetic overflow. Unsigned overflows can be detected using the jc instruction (jump if carry) jnc instruction (jump if not carry) Conditional jump instructions are placed after the add instruction in the 32bit case adc instruction in the 64bit case © 2006 Carnegie Mellon University 62ƒƒƒƒ Signed Overflow Detection The overflow flag denotes a signed arithmetic overflow. Signed overflows can be detected using the jo instruction (jump if overflow) jno instruction (jump if not overflow) Conditional jump instructions are placed after the add instruction in the 32bit case adc instruction in the 64bit case © 2006 Carnegie Mellon University 63ƒƒ Integer Subtraction The IA32 instruction set includes sub (subtract) sbb (subtract with borrow) The sub and sbb instructions set the overflow and carry flags to indicate an overflow in the signed or unsigned result. © 2006 Carnegie Mellon University 64Integer Multiplication Multiplication is prone to overflow errors because relatively small operands can overflow. One solution is to allocate storage for the product that is twice the size of the larger of the two operands. © 2006 Carnegie Mellon University 65ƒƒ Signed/Unsigned Examples n The max value for an unsigned integer is 2 1 n n 2n n+1 2n 2 1 x 2 1 = 2 –2 +1 2 n1 The minimum value for a signed integer is 2 n1 n1 2n2 2n 2 x2 = 2 2 © 2006 Carnegie Mellon University 66ƒƒƒƒ Multiplication Instructions The IA32 instruction set includes a mul (unsigned multiply) instruction imul (signed multiply) instruction The mul instruction st performs an unsigned multiplication of the 1 nd (destination) operand and the 2 (source) operand stores the result in the destination operand © 2006 Carnegie Mellon University 67Unsigned Multiplication 1. if (OperandSize == 8) Product of 8bit operands is stored in 16bit 2. AX = AL SRC; destination registers 3. else 4. if (OperandSize == 16) Product of 16bit operands 5. DX:AX = AX SRC; is stored in 32bit destination registers 6. 7. else // OperandSize == 32 8. EDX:EAX = EAX SRC; 9. Product of 32bit operands is stored in 64bit destination registers 10. © 2006 Carnegie Mellon University 68Signed/Unsigned int Multiplication siproduct = si1 si2; uiproduct = ui1 ui2; 9. mov eax, dword ptr ui1 10. imul eax, dword ptr ui2 11. mov dword ptr uiproduct, eax © 2006 Carnegie Mellon University 69ƒƒ Upcasting Cast both operands to an integer with at least 2x bits and then multiply. For unsigned integers Check highorder bits in the next larger integer. If any are set, throw an error. For signed integers, all zeros or all ones in the highorder bits and the sign bit in the loworder bit indicate no overflow. © 2006 Carnegie Mellon University 70Upcast Example void AllocBlocks(sizet cBlocks) // allocating no blocks is an error if (cBlocks == 0) return NULL; // Allocate enough memory // Upcast the result to a 64bit integer // and check against 32bit UINTMAX // to make sure there's no overflow unsigned long long alloc = cBlocks 16; return (alloc UINTMAX) malloc(cBlocks 16) : NULL; Multiplication results in a 32bit value. The result is assigned to an unsigned long long but the calculation may have already overflowed. © 2006 Carnegie Mellon University 71Standard Compliance To be compliant with C99, multiplying two 32bit numbers in this context must yield a 32bit result. The language was not modified because the result would be burdensome on architectures that do not have widening multiply instructions. The correct result could be achieved by casting one of the operands. © 2006 Carnegie Mellon University 72Corrected Upcast Example void AllocBlocks(sizet cBlocks) // allocating no blocks is an error if (cBlocks == 0) return NULL; // Allocate enough memory // Upcast the result to a 64bit integer // and check against 32bit UINTMAX // to make sure there's no overflow unsigned long long alloc = (unsigned long long)cBlocks16; return (alloc UINTMAX) malloc(cBlocks 16) : NULL; © 2006 Carnegie Mellon University 73ƒƒ Integer Division An integer overflow condition occurs when the minimum integer value for 32bit or 64bit integers is divided by 1. In the 32bit case, –2,147,483,648/1 should be equal to 2,147,483,648. 2,147,483,648 /1 = 2,147,483,648 Because 2,147,483,648 cannot be represented as a signed 32bit integer, the resulting value is incorrect. © 2006 Carnegie Mellon University 74ƒƒ Error Detection The IA32 instruction set includes the div and idiv instructions. The div instruction divides the (unsigned) integer value in the ax, dx:ax, or edx:eax registers (dividend) by the source operand (divisor) stores the result in the ax (ah:al), dx:ax, or edx:eax registers The idiv instruction performs the same operations on (signed) values. © 2006 Carnegie Mellon University 75Signed Integer Division siquotient = sidividend / sidivisor; 1. mov eax, dword ptr sidividend 2. cdq 3. idiv eax, dword ptr sidivisor 4. mov dword ptr siquotient, eax The cdq instruction copies the sign (bit 31) of the value in the eax register into every bit position in the edx register. NOTE: Assembly code generated by Visual C++ © 2006 Carnegie Mellon University 76Unsigned Integer Division uiquotient = ui1dividend / uidivisor; 5. mov eax, dword ptr uidividend 6. xor edx, edx 7. div eax, dword ptr uidivisor 8. mov dword ptr uiquotient, eax NOTE: Assembly code generated by Visual C++ © 2006 Carnegie Mellon University 77ƒƒ Error Detection The Intel division instructions div and idiv do not set the overflow flag. A division error is generated if the source operand (divisor) is zero the quotient is too large for the designated register A divide error results in a fault on interrupt vector 0. When a fault is reported, the processor restores the machine state to the state before the beginning of execution of the faulting instruction. © 2006 Carnegie Mellon University 78ƒƒƒƒ Microsoft Visual Studio C++ exception handling does not allow recovery from a hardware exception a fault such as – an access violation – divide by zero Visual Studio provides structured exception handling (SEH) facility for dealing with hardware and other exceptions extensions to the C language that enable C programs to handle Win32 structured exceptions Structured exception handling is an operating system facility that is distinct from C++ exception handling. © 2006 Carnegie Mellon University 79Structured Exception Handling in C int x, y; try x = INTMIN; y = 1; x = x / y; except (GetExceptionCode() == EXCEPTIONINTOVERFLOW EXCEPTIONEXECUTEHANDLER : EXCEPTIONCONTINUESEARCH) printf("Integer overflow during division.\n"); © 2006 Carnegie Mellon University 80C++ Exception Handling 1. Sint operator /(unsigned int divisor) 2. try 3. return ui / divisor; 4. 5. catch (...) 6. throw SintException( ARITHMETICOVERFLOW ); C++ exceptions in Visual C++ are implemented 7. using structured exceptions, making it possible to use C++ exception handling on this platform. 8. © 2006 Carnegie Mellon University 81Linux Error Handling 1 In the Linux environment, hardware exceptions such as division errors are managed using signals. If the source operand (divisor) is zero or if the quotient is too large for the designated register, a SIGFPE (floating point exception) is generated. To prevent abnormal termination of the program, a signal handler can be installed. signal(SIGFPE, Sint::divideerror); © 2006 Carnegie Mellon University 82ƒƒ Linux Error Handling 2 The signal() call accepts two parameters: signal number address of signal handler Because the return address points to the faulting instruction, if the signal handler simply returns, the instruction and the signal handler will be alternately called in an infinite loop. To solve this problem, the signal handler throws a C++ exception that can then be caught by the calling function. © 2006 Carnegie Mellon University 83Signal Handler 1. static void divideerror(int val) 2. throw SintException(ARITHMETICOVERFLOW); 3. © 2006 Carnegie Mellon University 84Agenda Integers Vulnerabilities Mitigation Strategies Notable Vulnerabilities Summary © 2006 Carnegie Mellon University 85Vulnerabilities A vulnerability is a set of conditions that allows violation of an explicit or implicit security policy. Security flaws can result from hardwarelevel integer error conditions or from faulty logic involving integers. These security flaws can, when combined with other conditions, contribute to a vulnerability. © 2006 Carnegie Mellon University 86Vulnerabilities Section Agenda Integer overflow Integer overflow Sign error Sign error Truncation Truncation Nonexceptional Nonexceptional © 2006 Carnegie Mellon University 87JPEG Example Based on a realworld vulnerability in the handling of the comment field in JPEG files. Comment field includes a twobyte length field indicating the length of the comment, including the twobyte length field. To determine the length of the comment string (for memory allocation), the function reads the value in the length field and subtracts two. The function then allocates the length of the comment plus one byte for the terminating null byte. © 2006 Carnegie Mellon University 88Integer Overflow Example 1. void getComment(unsigned int len, char src) 2. unsigned int size; 0 byte malloc() succeeds 3. size = len 2; 4. char comment = (char )malloc(size + 1); 5. memcpy(comment, src, size); 6. return; Size is interpreted as a large positive value of 0xffffffff 7. 8. int tmain(int argc, TCHAR argv) 9. getComment(1, "Comment "); 10. return 0; Possible to cause an overflow by creating an image with a comment length field of 1 11. © 2006 Carnegie Mellon University 89ƒƒ Memory Allocation Example Integer overflow can occur in calloc() and other memory allocation functions when computing the size of a memory region. A buffer smaller than the requested size is returned, possibly resulting in a subsequent buffer overflow. The following code fragments may lead to vulnerabilities: C: p = calloc(sizeof(elementt), count); C++: p = new ElementTypecount; © 2006 Carnegie Mellon University 90ƒƒ Memory Allocation The calloc() library call accepts two arguments: the storage size of the element type the number of elements The element type size is not specified explicitly in the case of the new operator in C++. To compute the size of the memory required, the storage size is multiplied by the number of elements. © 2006 Carnegie Mellon University 91Overflow Condition If the result cannot be represented in a signed integer, the allocation routine can appear to succeed but allocate an area that is too small. The application can write beyond the end of the allocated buffer, resulting in a heapbased buffer overflow. © 2006 Carnegie Mellon University 92Vulnerabilities Section Agenda Integer overflow Integer overflow Sign error Sign error Truncation Truncation Nonexceptional Nonexceptional © 2006 Carnegie Mellon University 93Program accepts two Sign Error Example 1 arguments (the length of data to copy and 1. define BUFFSIZE 10 the actual data) 2. int main(int argc, char argv) len declared as a signed integer 3. int len; 4. char bufBUFFSIZE; argv1 can be 5. len = atoi(argv1); a negative value 6. if (len BUFFSIZE) A negative value 7. memcpy(buf, argv2, len); bypasses the check 8. Value is interpreted as an unsigned value of type sizet 9. © 2006 Carnegie Mellon University 94ƒƒ Sign Errors Example 2 The negative length is interpreted as a large, positive integer with the resulting buffer overflow. This vulnerability can be prevented by restricting the integer len to a valid value. more effective range check that guarantees len is greater than 0 but less than BUFFSIZE declare as an unsigned integer – eliminates the conversion from a signed to unsigned type in the call to memcpy() – prevents the sign error from occurring © 2006 Carnegie Mellon University 95Vulnerabilities Section Agenda Integer overflow Integer overflow Sign error Sign error Truncation Truncation Nonexceptional Nonexceptional © 2006 Carnegie Mellon University 96Vulnerable Implementation 1. bool func(char name, long cbBuf) 2. unsigned short bufSize = cbBuf; 3. char buf = (char )malloc(bufSize); 4. if (buf) 5. memcpy(buf, name, cbBuf); cbBuf is used to initialize 6. return true; bufSize, which is used to allocate memory for 7. buf 8. return false; cbBuf is declared as a long and 9. used as the size in the memcpy() operation © 2006 Carnegie Mellon University 97Vulnerability 1 cbBuf is temporarily stored in the unsigned short bufSize. The maximum size of an unsigned short for both GCC and the Visual C++ compiler on IA32 is 65,535. The maximum value for a signed long on the same platform is 2,147,483,647. A truncation error will occur on line 2 for any values of cbBuf between 65,535 and 2,147,483,647. © 2006 Carnegie Mellon University 98Vulnerability 2 This would only be an error and not a vulnerability if bufSize were used for both the calls to malloc() and memcpy(). Because bufSize is used to allocate the size of the buffer and cbBuf is used as the size on the call to memcpy(), it is possible to overflow buf by anywhere from 1 to 2,147,418,112 (2,147,483,647 65,535) bytes. © 2006 Carnegie Mellon University 99Vulnerabilities Section Agenda Integer overflow Integer overflow Sign error Sign error Truncation Truncation Nonexceptional Nonexceptional © 2006 Carnegie Mellon University 100NonExceptional Integer Errors Integerrelated errors can occur without an exceptional condition (such as an overflow) occurring. © 2006 Carnegie Mellon University 101Negative Indices 1. int table = NULL; 2. int insertintable(int pos, int value) 3. if (table) 4. table = (int )malloc(sizeof(int) 100); 5. Storage for the 6. if (pos 99) array is allocated on 7. return 1; pos is not 99 the heap 8. 9. tablepos = value; 10. return 0; value is inserted into the 11. array at the specified position © 2006 Carnegie Mellon University 102ƒƒ Vulnerability There is a vulnerability resulting from incorrect range checking of pos. Because pos is declared as a signed integer, both positive and negative values can be passed to the function. An outofrange positive value would be caught but a negative value would not. © 2006 Carnegie Mellon University 103Agenda Integers Vulnerabilities Mitigation Strategies Notable Vulnerabilities Summary © 2006 Carnegie Mellon University 104Mitigation Section Agenda Type range checking Strong typing Compiler checks Safe integer operations Testing and reviews © 2006 Carnegie Mellon University 105Type Range Checking Type range checking can eliminate integer vulnerabilities. Languages such as Pascal and Ada allow range restrictions to be applied to any scalar type to form subtypes. Ada allows range restrictions to be declared on derived types using the range keyword: type day is new INTEGER range 1..31; Range restrictions are enforced by the language runtime. C and C++ are not nearly as good at enforcing type safety. © 2006 Carnegie Mellon University 106Type Range Checking Example 1. define BUFFSIZE 10 2. int main(int argc, char argv) 3. unsigned int len; Implicit type check from the declaration as an 4. char bufBUFFSIZE; unsigned integer 5. len = atoi(argv1); . 6. if ((0len) (lenBUFFSIZE) ) 7. memcpy(buf, argv2, len); 8. Explicit check for both upper and lower bounds 9. else 10. printf("Toomuch data\n"); © 2006 Carnegie Mellon University 107 11. Range Checking Explained Declaring len to be an unsigned integer is insufficient for range restriction because it only restricts the range from 0..MAXINT. Checking upper and lower bounds ensures no outofrange values are passed to memcpy(). Using both the implicit and explicit checks may be redundant but is recommended as “healthy paranoia.” © 2006 Carnegie Mellon University 108ƒƒƒƒ Range Checking External inputs should be evaluated to determine whether there are identifiable upper and lower bounds. These limits should be enforced by the interface. It’s easier to find and correct input problems than it is to trace internal errors back to faulty inputs. Limit input of excessively large or small integers. Typographic conventions can be used in code to distinguish constants from variables distinguish externally influenced variables from locally used variables with welldefined ranges © 2006 Carnegie Mellon University 109Mitigation Section Agenda Type range checking Strong typing Compiler checks Safe integer operations Testing and reviews © 2006 Carnegie Mellon University 110Strong Typing One way to provide better type checking is to provide better types. Using an unsigned type can guarantee that a variable does not contain a negative value. This solution does not prevent overflow. Strong typing should be used so that the compiler can be more effective in identifying range problems. © 2006 Carnegie Mellon University 111Problem: Representing Object Size Really bad: short total = strlen(argv1)+ 1; Better: sizet total = strlen(argv1)+ 1; Better still: rsizet total = strlen(argv1)+ 1; © 2006 Carnegie Mellon University 112Problem with sizet Extremely large object sizes are frequently a sign that an object’s size was calculated incorrectly. As we have seen, negative numbers appear as very large positive numbers when converted to an unsigned type like sizet. © 2006 Carnegie Mellon University 113ƒƒ rsizet rsizet cannot be greater than RSIZEMAX. For applications targeting machines with large address spaces, RSIZEMAX should be defined as the smaller of the size of the largest object supported (SIZEMAX 1) (even if this limit is smaller than the size of some legitimate, but very large, objects) rsizet is the same type as sizet so they are binary compatible © 2006 Carnegie Mellon University 114ƒƒƒ Strong Typing Example Declare an integer to store the temperature of water using the Fahrenheit scale: unsigned char waterTemperature; waterTemperature is an unsigned 8bit value in the range 1255. unsigned char sufficient to represent liquid water temperatures, which range from 32 degrees Fahrenheit (freezing) to 212 degrees Fahrenheit (the boiling point) does not prevent overflow allows invalid values (e.g., 131 and 213255) © 2006 Carnegie Mellon University 115Abstract Data Type One solution is to create an abstract data type in which waterTemperature is private and cannot be directly accessed by the user. A user of this data abstraction can only access, update, or operate on this value through public method calls. These methods must provide type safety by ensuring that the value of waterTemperature does not leave the valid range. If implemented properly, there is no possibility of an integer type range error occurring. © 2006 Carnegie Mellon University 116Mitigation Section Agenda Type range checking Strong typing Compiler checks Safe integer operations Testing and reviews © 2006 Carnegie Mellon University 117ƒƒ Visual C++ Compiler Checks Visual C++ .NET 2003 generates a warning (C4244) when an integer value is assigned to a smaller integer type. At level 1 a warning is issued if int64 is assigned to unsigned int. At level 3 and 4, a “possible loss of data” warning is issued if an integer is converted to a smaller type. For example, the following assignment is flagged at warning level 4: int main() int b = 0, c = 0; short a = b + c; // C4244 © 2006 Carnegie Mellon University 118Visual C++ Runtime Checks Visual C++ .NET 2003 includes runtime checks that catch truncation errors as integers are assigned to shorter variables that result in lost data. The /RTCc compiler flag catches those errors and creates a report. Visual C++ includes a runtimechecks pragma that disables or restores the /RTC settings but does not include flags for catching other runtime errors such as overflows. Runtime error checks are not valid in a release (optimized) build for performance reasons. © 2006 Carnegie Mellon University 119ƒƒƒ GCC Runtime Checks GCC compilers provide an ftrapv option provides limited support for detecting integer exceptions at runtime generates traps for signed overflow for addition, subtraction, and multiplication generates calls to existing library functions GCC runtime checks are based on post conditions—the operation is performed and the results are checked for validity © 2006 Carnegie Mellon University 120ƒƒƒ Postcondition For unsigned integers, if the sum is smaller than either operand, an overflow has occurred. For signed integers, let sum = lhs + rhs. If lhs is nonnegative and sum rhs, an overflow has occurred. If lhs is negative and sum rhs, an overflow has occurred. In all other cases, the addition operation succeeds. © 2006 Carnegie Mellon University 121Adding Signed Integers Function from the gcc runtime system used to detect errors resulting from the addition of signed 16bit integers 1. Wtype addvsi3 (Wtype a, Wtype b) 2. const Wtype w = a + b; 3. if (b = 0 w a : w a) The addition is performed 4. abort (); and the sum is compared to the operands to determine if 5. return w; an error occurred 6. abort() is called if •b is nonnegative and w a •b is negative and w a © 2006 Carnegie Mellon University 122Mitigation Section Agenda Type range checking Strong typing Compiler checks Safe integer operations Testing and reviews © 2006 Carnegie Mellon University 123ƒƒ Safe Integer Operations 1 Integer operations can result in error conditions and possible lost data. The first line of defense against integer vulnerabilities should be range checking. explicitly implicitly through strong typing It is difficult to guarantee that multiple input variables cannot be manipulated to cause an error to occur in some operation somewhere in a program. © 2006 Carnegie Mellon University 124Safe Integer Operations 2 An alternative or ancillary approach is to protect each operation. This approach can be labor intensive and expensive to perform. Use a safe integer library for all operations on integers where one or more of the inputs could be influenced by an untrusted source. © 2006 Carnegie Mellon University 125ƒƒ Safe Integer Solutions C language compatible library written by Michael Howard at Microsoft detects integer overflow conditions using IA32 specific mechanisms © 2006 Carnegie Mellon University 126Unsigned Add Function 1. int bool UAdd(sizet a, sizet b, sizet r) 2. asm 3. mov eax, dword ptr a 4. add eax, dword ptr b 5. mov ecx, dword ptr r 6. mov dword ptr ecx, eax 7. jc short j1 8. mov al, 1 // 1 is success 9. jmp short j2 10. j1: 11. xor al, al // 0 is failure 12. j2: 13. ; 14. © 2006 Carnegie Mellon University 127Unsigned Add Function Example 1. int main(int argc, char const argv) 2. unsigned int total; 3. if (UAdd(strlen(argv1), 1, total) UAdd(total, strlen(argv2), total)) 4. char buff = (char )malloc(total); 5. strcpy(buff, argv1); 6. strcat(buff, argv2); 7. else The length of the combined strings is 8. abort(); calculated using UAdd() with appropriate checks for error conditions. 9. 10. © 2006 Carnegie Mellon University 128SafeInt Class SafeInt is a C++ template class written by David LeBlanc. Implements a precondition approach that tests the values of operands before performing an operation to determine if an error will occur. The class is declared as a template, so it can be used with any integer type. Every operator has been overridden except for the subscript operator. © 2006 Carnegie Mellon University 129The variables s1 and s2 are declared as SafeInt types SafeInt Example 1. int main(int argc, char const argv) 2. try 3. SafeIntunsigned long s1(strlen(argv1)); 4. SafeIntunsigned long s2(strlen(argv2)); 5. char buff = (char ) malloc(s1 + s2 + 1); 6. strcpy(buff, argv1); 7. strcat(buff, argv2); 8. 9. catch(SafeIntException err) 10. abort(); When the + operator is invoked it uses the 11. safe version of the operator implemented as part of the SafeInt class. 12. © 2006 Carnegie Mellon University 130ƒƒ Addition Addition of unsigned integers can result in an integer overflow if the sum of the lefthand side (LHS) and righthand side (RHS) of an addition operation is greater than UINTMAX for addition of unsigned int type ULLONGMAX for addition of unsigned long long type © 2006 Carnegie Mellon University 131Precondition Example Overflow occurs when A andB are unsigned int and A + B UINTMAX To prevent the addition from overflowing the operator+ tests that A UINTMAX – B © 2006 Carnegie Mellon University 132ƒƒƒ Safe Integer Solutions Compared SafeInt library has several advantages: more portable than safe arithmetic operations that depend on assembly language instructions more usable – operators can be used inline in expressions – SafeInt uses C++ exception handling better performance (with optimized code) However, SafeInt fails to provide correct integer promotion behavior. © 2006 Carnegie Mellon University 133ƒƒ When to Use Safe Integers Use safe integers when integer values can be manipulated by untrusted sources such as the size of a structure the number of structures to allocate void CreateStructs(int StructSize, int HowMany) SafeIntunsigned long s(StructSize); Structure size multiplied by required to s = HowMany; determine size of memory to allocate return malloc(s.Value()); The multiplication can overflow the integer and create a buffer overflow vulnerability © 2006 Carnegie Mellon University 134ƒƒ When Not to Use Safe Integers Don’t use safe integers when no overflow is possible. tight loop variables are not externally influenced … char aINTMAX; for (int i = 0; i INTMAX; i++) ai = '\0'; … © 2006 Carnegie Mellon University 135Mitigation Section Agenda Type range checking Strong typing Compiler checks Safe integer operations Testing and reviews © 2006 Carnegie Mellon University 136ƒƒ Testing 1 Input validation does not guarantee that subsequent operations on integers will not result in an overflow or other error condition. Testing does not provide any guarantees either. It is impossible to cover all ranges of possible inputs on anything but the most trivial programs. If applied correctly, testing can increase confidence that the code is secure. © 2006 Carnegie Mellon University 137ƒƒ Testing 2 Integer vulnerability tests should include boundary conditions for all integer variables. If type range checks are inserted in the code, test that they function correctly for upper and lower bounds. If boundary tests have not been included, test for minimum and maximum integer values for the various integer sizes used. Use white box testing to determine the types of integer variables. If source code is not available, run tests with the various maximum and minimum values for each type. © 2006 Carnegie Mellon University 138ƒƒƒƒ Source Code Audit Source code should be audited or inspected for possible integer range errors. When auditing check that integer type ranges are properly checked input values are restricted to a valid range based on their intended use Integers that do not require negative values are declared as unsigned properly rangechecked for upper and lower bounds Operations on integers originating from untrusted sources are performed using a safe integer library. © 2006 Carnegie Mellon University 139Agenda Integers Vulnerabilities Mitigation Strategies Notable Vulnerabilities Summary © 2006 Carnegie Mellon University 140ƒƒƒƒƒƒ Notable Vulnerabilities Integer Overflow In XDR Library SunRPC xdrarray buffer overflow http://xforce.iss.net/xforce/xfdb/9170 Windows DirectX MIDI Library eEye Digital Security advisory AD20030723 http://www.eeye.com/html/Research/Advisories/AD200 30723.html Bash CERT Advisory CA199622 http://www.cert.org/advisories/CA199622.html © 2006 Carnegie Mellon University 141Agenda Integers Vulnerabilities Mitigation Strategies Notable Vulnerabilities Summary © 2006 Carnegie Mellon University 142ƒƒƒ Summary The key to preventing integer vulnerabilities is to understand integer behavior in digital systems. Concentrate on integers used as indices (or other pointer arithmetic), lengths, sizes, and loop counters Use safe integer operations to eliminate exception conditions Range check all integer values used as indices. Use sizet or rsizet for all sizes and lengths (including temporary variables) © 2006 Carnegie Mellon University 143Questions about Integers © 2006 Carnegie Mellon University 144For More Information ® Visit the CERT web site http://www.cert.org/securecoding/ Contact Presenter Robert C. Seacord rcscert.org Contact CERT Coordination Center Software Engineering Institute Carnegie Mellon University 4500 Fifth Avenue Pittsburgh PA 152133890 Hotline: 4122687090 CERT/CC personnel answer 8:00 a.m.–5:00 p.m. and are on call for emergencies during other hours. Fax: 4122686989 Email: certcert.org © 2006 Carnegie Mellon University 145Backup Slides © 2006 Carnegie Mellon Universityƒƒƒƒƒ sub Instruction nd st Subtracts the 2 (source) operand from the 1 (destination) operand. Stores the result in the destination operand. The destination operand can be a register memory location The source operand can be a(n) immediate register memory location © 2006 Carnegie Mellon University 147sbb Instruction The sbb instruction is executed as part of a multibyte or multiword subtraction. nd The sbb instruction adds the 2 (source) operand st and the carry flag and subtracts the result from the 1 (destination) operand. The result of the subtraction is stored in the destination operand. The carry flag represents a borrow from a previous subtraction. © 2006 Carnegie Mellon University 148signed long long int Sub The sub instruction subtracts sll1 sll2 the loworder 32 bits 1. mov eax, dword ptr sll1 2. sub eax, dword ptr sll2 3. mov ecx, dword ptr ebp0E0h 4. sbb ecx, dword ptr ebp0F0h The sbb instruction subtracts the loworder 32 bits NOTE: Assembly code generated by Visual C++ for Windows 2000 © 2006 Carnegie Mellon University 149Accepts two string arguments and calculates Introductory their combined length (plus an extra byte for the terminating null character) Example 1 int main(int argc, char const argv) 2. unsigned short int total; 3. total = strlen(argv1) + strlen(argv2) + 1; 4. char buff = (char ) malloc(total); 5. strcpy(buff, argv1); Memory is allocated to store 6. strcat(buff, argv2); both strings 7. st The 1 argument is copied into the buffer nd and the 2 argument is concatenated to st the end of the 1 argument © 2006 Carnegie Mellon University 150ƒƒ Vulnerability An attacker can supply arguments such that the sum of the lengths of the strings cannot be represented by the unsigned short int total. The strlen() function returns a result of type sizet, an unsigned long int on IA32. As a result, the sum of the lengths + 1 is an unsigned long int. This value must be truncated to assign to the unsigned short int total. If the value is truncated, malloc() allocates insufficient memory and strcpy() and strcat() will overflow the dynamically allocated memory. © 2006 Carnegie Mellon University 151
sharer
Presentations
Free
Document Information
Category:
Presentations
User Name:
NicolusNorton
User Type:
Professional
Country:
Germany
Uploaded Date:
08-07-2017