Memory management
A computer's memory is made up of several different types of memory that are used for various purposes. I won't go into heavy detail here, but these different types include cache, random access memory (RAM), and read only memory (ROM). Cache memory is a high speed read/write memory used to store values for a temporary amount of time, often between operations performed by the processor. Most often, if a value is going to be needed several times during a process it will be stored in cache memory. RAM is another type of memory used for temporary storage. RAM is significantly larger than cache and is used for read/write activities by the operating system and applications. Both RAM and cache are volatile memory, meaning that when they lose their power they lose any data they were storing. ROM is a non-volatile type of memory used for permanent storage of data (until you want to erase or overwrite it) which takes significantly longer to read and write to.When a program or the operating system wants to access memory, an address has to be loaded into the processor. Memory addresses, as used by the operating system, are completely sequential. This works well for the operating system because it can easily say, "oh, you want to run notepad.exe? That program is stored in memory location 0x84B2." The difficulty arises when applications want to access memory. A developer cannot know where their program will be stored in memory, or what memory addresses will be available. To solve this problem, applications use what's called virtual memory. Virtual memory allows an application to say, "store this value at space 0", which in reality is memory address 0x2A91. A memory management program is employed to map the logical addresses (the address an application uses) to the absolute addresses (the address the operating system uses).
Buffer overflows
A buffer is an allocated segment of memory. When an application is performing a process that accepts user input, it will set up a buffer to store the value of that input. If the application fails to check the input, a value that is too large for the buffer may be passed, causing the application to overwrite memory outside of the buffer which previously held program instructions or data. This may be done for the purpose of causing havoc or attempting to run another program of the attacker's choosing.
So how exactly can overwriting some memory segments lead to an attacker being able to run a program? To understand this, we need to look at how buffers are set up. When an application sets up a buffer, it creates what's called a stack. The first thing the application places on the stack is a pointer to it's address in memory so that when the process is finished it can return control to the application. On top of the stack pointer the application writes the data passed as variables. The process that the stack is passed to then works from the top, taking the data off as it goes, until it reaches the stack pointer at the bottom which tells it where to return control.
The danger comes when values passed as inputs aren't checked to ensure they fit within the buffer. If a value that is too large is passed, it can overwrite the stack pointer. At this point, if the attack has been crafted correctly, a new stack pointer can be placed at the bottom which sends control to the attackers program that is loaded in the stack. To successfully create a buffer overflow, the attacker has to be able to view how big a stack is and where in memory it resides. If an attacker can figure this out, they can write an exploit for the application.
If developers want to prevent buffer overflows, the simplest protection is secure coding practices. Inputs given by users or other applications should always be checked to ensure they fit within the buffer. Additionally, safe versions of functions such as strcpy (which does not validate input) should always be used.
No comments:
Post a Comment