User:Abaddon314159/sandbox

From Wikipedia, the free encyclopedia

In software, a stack buffer overflow occurs when a program accesses an invalid memory address on the program's call stack.[1] [2] Stack buffer overflow bugs are caused when a program writes more data to a buffer located on the stack than there was actually allocated for that buffer. This almost always results in corruption of adjacent data on the stack, and in cases where the overflow was triggered by mistake, will usually cause the program to crash. This type of overflow is part of the more general class of programming bugs known as buffer overflows.[1]

If the effected program is running with special priviledges, or accepts data from untrusted network hosts (e.g. a webserver) then the bug is a potencial security vulnerability. If the stack buffer is filled with data supplied from an untrusted user then that user can corrupt the stack in such a way as to inject executable code into the running program and take control of the process. This is one of the oldest and more reliable methods for crackers to gain unauthorized access to a computer).[3][4] [5]

Exploiting stack buffer overflows[edit]

The cannonical method for exploiting a stack based buffer overflow is to overwrite the function return address with a pointer to attacker controled data (usually on the stack itself).[3][6] This is illustrated in the example below:

An example with strcpy

void foo (char *bar) {
  char  c[12];

  strcpy(c, bar);  // no bounds checking...
}

int main (int argc, char **argv) {
  foo(argv[1]); 
}

This code takes an argument from the command line and copies it to a local stack variable c. This works fine for command line arguments smaller than 12 characters (as you can see in figure B below). Any arguments larger than 11 characters long will result in corruption of the stack.

The program stack in foo() with various inputs
A - Before data is copied.
B. - "hello" is the first command line argument.
C. - "AAAAAAAAAAAAAAAAAAAA\x08\x35\xC0\x80" is the first command line argument.

Notice in figure C above, when an argument larger than 11 bytes is supplied on the command line foo() overwrites local stack data, the saved frame pointer, and most importantly, the return address. When foo() returns it pops the return address off the stack and jumps to that address (i.e. starts executing instructions from that address). As you can see in figure C above, the attacker has overwritten the return address with a pointer to the stack buffer char c[12], which now contains attacker supplied data. In an actual stack buffer overflow exploit the string of "A"'s would be replaced with shellcode suitable to the platform and desired function. If this program had special priviledges (e.g. the SUID bit set to run as the superuser), then the attacker could use this vulnerability to gain superuser priviledges on the effected machine.[3]

Practical considerations[edit]

The example above demonstrates the basic concepts of how an attacker is able to exploit a stack based buffer overflow to gain control of the effected program, but it will rarely work in real world examples. The problem is that using this method we need to know the exact location of the effected buffer on the stack so that we can overwrite the return pointer with that address. In most cases its not practical to try to find this address for a number of reasons. The start of the stack may be different for each thread in an application, the depth of the current stack at the time of exploitation may be difficult or impossible to determine, etc.[3] There are a number of methods an attacker can employ to overcome these considerations. The most important techniques are the NOP-sled, and the jump to ESP technique.

The NOP-sled technique[edit]

D - Illustration of a NOP-sled payload on the stack.

A NOP-sled is oldest and the most widely known technique for successfully exploiting a stack buffer overflow.[7] It solves the problem of finding the exact address to the buffer by effectively increasing the size of the target area. To do this much larger sections of the stack are corrupted with the no-op machine instruction. At the end of the attacker supplied data, after the no-op instructions, is placed an instruction to perform a relative jump to the top of the buffer where the shellcode is located. This collection of no-ops is refered to as the "NOP-sled" because if the return address is overwritten with any address within the no-op region of the buffer it will "slide" down the no-op's until it is redirected to the actual malicious code by the jump at the end. This technique requires the attacker to guess where on the stack the NOP-sled is instead of the, comparitively small, shellcode.[3][8]

Because of the popularity of this technique many vendors of Intrusion prevention systems will search for this pattern of no-op machine instructions in an attempt to detect shellcode in use. Its important to note that a NOP-sleds does not nessisarily contain only traditional no-op machine instructions; any instruction that does not corrupt the machine state to a point where the shellcode will not run can be used in place of the hardware assited no-op. As a result it has become common practice for exploit writers to compose the no-op sled with randomly chosen instructions which will have no real effect on the shellcode execution.[9]

While this method greatly improves the chances that at attack will be successful it is not without problems. Exploits using this technique still must rely on some amount of luck that they will guess offsets on the stack that are within the NOP-sled region.[3][10] An incorrect guess will usually result in the target program crashing and could alert the system administrator to the attacker's activities. Another problem is that the NOP-sled requires a much larger amount of memory in which to hold a NOP-sled large enough to be over any use. This can be a problem when the allocated size of the effected buffer is too small and the current depth of the stack is shallow (i.e. there is not much space from the end of the current stack frame to the start of the stack). Dispite its problems, the NOP-sled is often the only method that will work for a given platform, environment, or situation; as such it is still an important technique.

The jump to ESP technique[edit]

The "jump to ESP" technique allows for reliable exploitation of stack buffer overflows without the need for extra room for a NOP-sled and without having to guess stack offsets. The strategy is to overwrite the return pointer with something that will cause the program to jump to top of the stack (where the attacker's shellcode is stored) in a dynamic way; so no matter where the top of the stack is, the program will jump there upon return. To accomplish this the return pointer is overwritten with an address within the main program code that contains the machine instructions to jump to the top of the stack. On i386 this instruction is jmp esp. This technique is so named because it is most often used on i386 platforms. To avoid this platform specific nomenclature this technique is sometimes refered to as the "jump through register" technique.[11]

E - An instruction from ntdll.dll to call the DbgPrint() routine contains the i386 machine opcode for jmp esp.

In practice it is extremely rare for a program to intentionally contain instructions to jump to the top of the program stack. The traditional solution is to find an unintentional instance of a suitable opcode at a fixed location somewhere within the program memory. This usually requires that the machine architecture allow for memory access at unaligned addresses (see the section platform related differences for special cases). In figure E on the left you can see an example of such an unintentional instance of the i386 jmp esp instruction. The opcode for this instruction is FF E4.[12] This two byte sequence can be found at a one byte offset from the start of the instruction call DbgPrint at address 0x7C941EED. If an attacker overwrites the program return address with this address the program will first jump to 0x7C941EED, interpret the opcode FF E4 as the jmp esp instruction, and will then jump to the top of the stack and execute the attacker's code.[13]

When this technique is possible the severity of the vulnerability increases considerably. This is because exploitation will work reliably enough to automate an attack with a virtual garantee of success when it is run. For this reason, this is the technique most commonly used in internet worms that exploit stack buffer overflow vulnerabilities.[14]

Platform related differences[edit]

A number of platforms have subtle differences in their implimentation of the call stack that can effect the way a stack buffer overflow exploit will work. Some machine architectures store the top level return address of the call stack in a register. This means that any overwritten return address will not be used until a later unwinding of the call stack. Another example of a machine specific detail that can effect the choice of exploitation techniques is the fact that most RISC style machine architectures will not allow for unaligned access to memory.[15] Combined with a fixed length for machine opcodes this machine limitation can make the jmp to ESP technique almost impossible to impliment (with the one exception being when the program actually contains the unlikely code to explicitly jmp to the stack register).[16][17]

Stacks that grow up[edit]

Within the topic of stack buffer overflows an often discussed, but rarely seen architecture is one in which the stack grows in the oposite direction. This change in architecture is frequently suggested as a solution to the stack buffer overflow problem because any overflow of a stack buffer that occurs within the same stack frame can not overwrite the return pointer. Further investigation of this claimed protection finds it to be a nieve solution at best. Any overflow that occurs in a buffer from a previous stack frame will still overwrite a return pointer and allow for malicious exploitation of the bug.[18] For instance in the example above, the return pointer for foo will not be overwritten because the overflow actually occurs within the stack frame for strcpy. However, because the buffer that overflows during the call to strcpy resides in a previous stack frame, the return pointer for strcpy will have a numerically higher memory address than the buffer. This means that instead of the return pointer for foo being overwritten, the return pointer for strcpy will be overwritten thus allowing exploitation anyways. At most this means that growing the stack in the oposite direction will change some details of how stack buffer overflows are exploitable, but will not nessisarily cause a signifigant reduction in the number of exploitable bugs.

Protection schemes[edit]

Over the years a number of schemes have been developed to inhibit malicious stack buffer overflow exploitation. These usually have taken one of two forms. The first method is to detect that a stack buffer overflow has occured and thus prevent redirection of the instruction pointer to malicious code. The second attempts to prevent the execution of malicious code from the stack without directly detecting the stack buffer overflow.[19]

Stack canaries[edit]

Stack canaries, so named because they operate as a canary in the mine so to speak, are used to detect a stack buffer overflow before execution of malicious code can occur. This method works by placing a small integer, the value of which is randomly chosen at program start, in memory just before the stack return pointer. Most buffer overflows overwrite memory from lower to higher memory addresses, so in order to overwrite the return pointer (and thus take control of the process) the canary value must also be overwritten. This value is checked to make sure it has not changed before a routine uses the return pointer on the stack.[2] This technique can greatly increase the difficulty of exploiting a stack buffer overflow because it forces the attacker to gain control of the instruction pointer by some nontraditional means such as corrupting other important variables on the stack.[2]

Nonexecutable stack[edit]

Another aproach to preventing stack buffer overflow exploitation is to enforce memory policy on stack memory region to disallow execution from the stack. This means that in order to execute shellcode from the stack an attacker must either find a way to disable the execution protection from memory, or find a way to put his shellcode payload in a non-protected region of memory. This method is becoming more popular now that hardware support for the no-execute flag is available in most desktop processors. While this method definately makes the canonical aproach to stack buffer overflow exploitation fail it is not without its problems. First it is common to find ways to store shellcode in unprotected memory regions like the heap, and so very little need change in the way of exploitation.[20] Even if this were not so there are other ways. The most damning is the so called return to libc method for shellcode creation. In this attack the malicious payload will load, the stack not with shellcode, but with a proper call stack so that execution is vectored to a chain of standard library calls, usually with the effect of disabling memory execute protections and allowing shellcode to run as normal.[21] This works because the execution never actually vectors to the stack itself. Still if used in conjuction with techniques like ASLR a nonexecutable stack can be somewhat resistent to return to libc attacks and thus can greatly improve the security of an application.

Notable examples[edit]

See also[edit]

References[edit]

  1. ^ a b Fithen, William L (2007-03-27). "VT-MB. Violation of Memory Bounds". US CERT. {{cite web}}: Unknown parameter |coauthors= ignored (|author= suggested) (help)
  2. ^ a b c Dowd, Mark (November 2006). The Art Of Software Security Assessment. Addison Wesley. pp. 169–196. ISBN 0-321-44442-6. {{cite book}}: Unknown parameter |coauthors= ignored (|author= suggested) (help)CS1 maint: date and year (link)
  3. ^ a b c d e f Levy, Elias (1996-11-08). "Smashing the stack for fun and profit". Phrack. 1 (49): 14.
  4. ^ Pincus, J.; Baker, B. (July-Aug. 2004). "Beyond Stack Smashing: Recent Advances in Exploiting Buffer Overruns" (PDF). IEEE Security & Privacy. 2 (4): 20–27. doi:10.1109/MSP.2004.36. S2CID 6647392. {{cite journal}}: Check date values in: |date= (help)
  5. ^ Burebista. "Stack Overflows" (Document). {{cite document}}: Cite document requires |publisher= (help); Unknown parameter |url= ignored (help)
  6. ^ Bertrand, Louis (2002). "OpenBsd: Fix the Bugs, Secure the System". MUSESS '02: McMaster University Software Engineering Symposium.
  7. ^ Vangelis (2004-12-08). "Stack-based Overflow Exploit: Introduction to Classical and Advanced Overflow Technique" (Document). Wowhacker via Neworder. {{cite document}}: Unknown parameter |format= ignored (help); Unknown parameter |url= ignored (help)
  8. ^ Balaban, Murat. "Buffer Overflows Demystified" (Document). Enderunix.org. {{cite document}}: Unknown parameter |format= ignored (help); Unknown parameter |url= ignored (help)
  9. ^ Akritidis, P. (2005). "STRIDE: Polymorphic Sled Detection through Instruction Sequence Analysis." (PDF). Proceedings of the 20th IFIP International Information Security Conference (IFIP/SEC 2005). IFIP International Information Security Conference. {{cite conference}}: Unknown parameter |coauthors= ignored (|author= suggested) (help)
  10. ^ Klein, Christian (September 2004). "Buffer Overflow" (Document). {{cite document}}: Cite document requires |publisher= (help); Unknown parameter |url= ignored (help)
  11. ^ Shah, Saumil (2006). "Writing Metasploit Plugins: from vulnerability to exploit" (PDF). Hack In The Box. Kuala Lumpur.
  12. ^ Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 2A: Instruction Set Reference, A-M (PDF). Intel Corporation. May 2007. pp. 3–508.
  13. ^ Alvarez, Sergio (2004-09-05). "Win32 Stack BufferOverFlow Real Life Vuln-Dev Process" (Document). IT Security Consulting. {{cite document}}: Unknown parameter |url= ignored (help)
  14. ^ Ukai, Yuji (2004). "Environment Dependencies in Windows Exploitation". BlackHat Japan. Japan: eEye Digital Security. {{cite conference}}: Unknown parameter |coauthors= ignored (|author= suggested) (help)
  15. ^ pr1. "Exploiting SPARC Buffer Overflow vulnerabilities" (Document). {{cite document}}: Cite document requires |publisher= (help); Unknown parameter |format= ignored (help); Unknown parameter |url= ignored (help)CS1 maint: numeric names: authors list (link)
  16. ^ Curious (2005-01-08). "Reverse engineering - PowerPC Cracking on OSX with GDB". Phrack. 11 (63): 16.
  17. ^ {{cite document | author = Sovarel, Ana Nora | coauthors= Evans, David; Paul, Nathanael | title =Where's the FEEB? The Effectiveness of Instruction Set Randomization | url =http://www.cs.virginia.edu/feeb/paper/ | format =[[HTML] }}
  18. ^ Zhodiac (2001-12-28). "HP-UX (PA-RISC 1.1) Overflows". Phrack. 11 (58): 11.
  19. ^ Ward, Craig E. (2005-06-13). "C/C++ Buffer Overflows" (PDF). Unix Users Association of Southern California. Orange County, California.
  20. ^ Foster, James C. (2005). Buffer Overflow Attacks: Detect, Exploit, Prevent (PDF). United States of America: Syngress Publishing,Inc. ISBN 1-932266-67-4. {{cite book}}: Unknown parameter |coauthors= ignored (|author= suggested) (help)
  21. ^ Nergal (2001-12-28). "The advanced return-into-lib(c) exploits: PaX case study". Phrack. 11 (58): 4.


Category:Programming bugs Category:Software anomalies Category:Security exploits