Array Indexing Errors

Array Indexing Errors

Array indexing errors are much less commonly exploited than buffer overruns, but it amounts to the same thing a string is just an array of characters, and it stands to reason that arrays of other types could also be used to write to arbitrary memory locations. If you don t look deeply at the problem, you might think that an array indexing error would allow you to write to memory locations only higher than the base of the array, but this isn t true. I ll discuss this issue later in this section.

Let s look at sample code that demonstrates how an array indexing error can be used to write memory in arbitrary locations:

/* ArrayIndexError.cpp */ #include <stdio.h> #include <stdlib.h> int* IntVector; void bar(void) { printf("Augh! I've been hacked!\n"); } void InsertInt(unsigned long index, unsigned long value) { //We're so sure that no one would ever pass in //a value more than 64 KB that we're not even going to //declare the function as taking unsigned shorts //or check for an index out of bounds - doh! printf("Writing memory at %p\n", &(IntVector[index])); IntVector[index] = value; } bool InitVector(int size) { IntVector = (int*)malloc(sizeof(int)*size); printf("Address of IntVector is %p\n", IntVector); if(IntVector == NULL) return false; else return true; } int main(int argc, char* argv[]) { unsigned long index, value; if(argc != 3) { printf("Usage is %s [index] [value]\n"); return -1; } printf("Address of bar is %p\n", bar); //Let's initialize our vector - 64 KB ought to be enough for //anyone <g>. if(!InitVector(0xffff)) { printf("Cannot initialize vector!\n"); return -1; } index = atol(argv[1]); value = atol(argv[2]); InsertInt(index, value); return 0; }

ArrayIndexError.cpp is also available on the companion CD in the folder SecureCo\Chapter 3. The typical way to get hacked with this sort of error occurs when the user tells you how many elements to expect and is allowed to randomly access the array once it s created because you ve failed to enforce bounds checking.

Now let s look at the math. The array in our example starts at 0x00510048, and the value we d like to write is guess what? the return value on the stack, which is located at 0x0012FF84. The following equation describes how the address of a single array element is determined by the base of the array, the index, and the size of the array elements:

Address of array element = base of array + index * sizeof(element)

Substituting the example s values into the equation, we get

0x10012FF84 = 0x00510048 + index * 4

Note that 0x10012FF84 is used in our equation instead of 0x0012FF84. I ll discuss this truncation issue in a moment. A little quick work with Calc.exe shows that index is 0x3FF07FCF, or 1072725967, and that the address of bar (0x00401000) is 4198400 in decimal. Here are the program results:

[d:\]ArrayIndexError.exe 1072725967 4198400 Address of bar is 00401000 Address of IntVector is 00510048 Writing memory at 0012FF84 Augh! I've been hacked!

As you can see, this sort of error is trivial to exploit if the attacker has access to a debugger. A related problem is that of truncation error. To a 32-bit operating system, 0x100000000 is really the same value as 0x00000000. Programmers with a background in engineering are familiar with truncation error, so they tend to write more solid code than those who have studied only computer sciences. (As with any generalization about people, there are bound to be exceptions.) I attribute this to the fact that many engineers have a background in numerical analysis dealing with the numerical instability issues that crop up when working with floating-point data tends to make you more cautious. Even if you don t think you ll ever be doing airfoil simulations, a course in numerical analysis will make you a better programmer because you ll have a better appreciation for truncation errors.

Some famous exploits are related to truncation error. On a UNIX system, the root (superuser) account has a user ID of 0. The network file system daemon (service) would accept a user ID that was a signed integer value, check to see whether the value was nonzero, and then truncate it to an unsigned short. This flaw would let users pass in a user ID (UID) of 0x10000, which isn t 0, truncate it to 2 bytes ending up with 0x0000 and then grant them superuser access because their UID was 0. Be very careful when dealing with anything that could result in either a truncation error or an overflow.



Writing Secure Code
Writing Secure Code, Second Edition
ISBN: 0735617228
EAN: 2147483647
Year: 2005
Pages: 153

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net