views:

180

answers:

5

Does anyone have a detailed explanation on how integers can be exploited? I have been reading a lot about the concept, and I understand what an it is, and I understand buffer overflows, but I dont understand how one could modify memory reliably, or in a way to modify application flow, by making an integer larger than its defined memory....

+5  A: 

It is definitely exploitable, but depends on the situation of course.

Old versions ssh had an integer overflow which could be exploited remotely. The exploit caused the ssh daemon to create a hashtable of size zero and overwrite memory when it tried to store some values in there.

More details on the ssh integer overflow: http://www.kb.cert.org/vuls/id/945216

More details on integer overflow (thanks to Shaji): http://www.owasp.org/index.php/Integer_overflow

Moron
+1 More information is here http://www.owasp.org/index.php/Integer_overflow
Shaji
as the example explained below by Ira Baxter, it has to be a specific situation like that - where you over/under flow an integer when allocating a hash/buffer/array which allows you access to memory you shouldnt have access to, then having a way to calculate FP, etc.
wuntee
@wuntee: I don't think there is any point trying to narrow it down like that. Each situation is different. Resourceful people find ways one cannot even imagine! I remember in netscape there was a single off-by-one error that overwrote a single byte with a space. People were able to exploit it!
Moron
+2  A: 

It depends on how the variable is used. If you never make any security decisions based on integers you have added with input integers (where an adversary could provoke an overflow), then I can't think of how you would get in trouble (but this kind of stuff can be subtle).

Then again, I have seen plenty of code like this that doesn't validate user input (although this example is contrived):

int pricePerWidgetInCents = 3199;
int numberOfWidgetsToBuy = int.Parse(/* some user input string */);
int totalCostOfWidgetsSoldInCents = pricePerWidgetInCents * numberOfWidgetsToBuy; // KA-BOOM!

// potentially much later
int orderSubtotal = whatever + totalCostOfWidgetInCents;

Everything is hunky-dory until the day you sell 671,299 widgets for -$21,474,817.95. Boss might be upset.

Doug McClean
yes, but the how do you use that to your advantage? how can you cause that to override the frame pointer - for example...
wuntee
a better example would be:int arraySize = [some user input];int array[arraySize];
wuntee
You can't use this example to override the frame pointer. You can, however, use it to steal 42 million dollars, which is still exploiting a security problem.
Doug McClean
+3  A: 

I used APL/370 in the late 60s on an IBM 360/40. APL is language in which essentially everything thing is a multidimensional array, and there are amazing operators for manipulating arrays, including reshaping from N dimensions to M dimensions, etc.

Unsurprisingly, an array of N dimensions had index bounds of 1..k with a different positive k for each axis.. and k was legally always less than 2^31 (positive values in a 32 bit signed machine word). Now, an array of N dimensions has an location assigned in memory. Attempts to access an array slot using an index too large for an axis is checked against the array upper bound by APL. And of course this applied for an array of N dimensions where N == 1.

APL didn't check if you did something incredibly stupid with RHO (array reshape) operator. APL only allowed a maximum of 64 dimensions. So, you could make an array of 1-64 dimension, and APL would do it if the array dimensions were all less than 2^31. Or, you could try to make an array of 65 dimensions. In this case, APL goofed, and surprisingly gave back a 64 dimension array, but failed to check the axis sizes. (This is in effect where the "integer overflow occurred"). This meant you could create an array with axis sizes of 2^31 or more... but being interpreted as signed integers, they were treated as negative numbers.

The right RHO operator incantation applied to such an array to could reduce the dimensionaly to 1, with an an upper bound of, get this, "-1". Call this matrix a "wormhole" (you'll see why in moment). Such an wormhole array has a place in memory, just like any other array. But all array accesses are checked against the upper bound... but the array bound check turned out to be done by an unsigned compare by APL. So, you can access WORMHOLE[1], WORMHOLE[2], ... WORMHOLE[2^32-2] without objection. In effect, you can access the entire machine's memory.

APL also had an array assignment operation, in which you could fill an array with a value. WORMHOLE[]<-0 thus zeroed all of memory.

I only did this once, as it erased the memory containing my APL workspace, the APL interpreter, and obvious the critical part of APL that enabled timesharing (in those days it wasn't protected from users)... the terminal room went from its normal state of mechanically very noisy (we had 2741 Selectric APL terminals) to dead silent in about 2 seconds. Through the glass into the computer room I could see the operator look up startled at the lights on the 370 as they all went out. Lots of runnning around ensued.

While it was funny at the time, I kept my mouth shut.

With some care, one could obviously have tampered with the OS in arbitrary ways.

Ira Baxter
i could definitely see how one could take advantage of this (as you can access all memory of the machine). I guess the idea is that it all depends on the specific situation - in this, the application does not bounds check the allocation of an array, where the array's size is an integer. My mind was stuck on the simple 'buffer overflow' and was thinking there was some way to have 'int x = y + z * w' where y and z and w were all user defined, and in that statement could somehow write over memory in a reliable fashion.
wuntee
Ira Baxter
+1  A: 

A common case would be code that prevents against buffer overflow by asking for the number of inputs that will be provided, and then trying to enforce that limit. Consider a situation where I claim to be providing 2^30+10 integers. The receiving system allocates a buffer of 4*(2^30+10)=40 bytes (!). Since the memory allocation succeeded, I'm allowed to continue. The input buffer check won't stop me when I send my 11th input, since 11 < 2^30+10. Yet I will overflow the actually allocated buffer.

MSalters
A: 

I just wanted to sum up everything I have found out about my original question.

The reason things were confusing to me was because I know how buffer overflows work, and can understand how you can easily exploit that. An integer overflow is a different case - you cant exploit the integer overflow to add arbitrary code, and force a change in the flow of an application.

However, it is possible to overflow an integer, which is used - for example - to index an array to access arbitrary parts of memory. From here, it could be possible to use that mis-indexed array to override memory and cause the execution of an application to alter to your malicious intent.

Hope this helps.

wuntee