Buffer overflow
In
Buffers are areas of memory set aside to hold data, often while moving it from one section of a program to another, or between programs. Buffer overflows can often be triggered by malformed inputs; if one assumes all inputs will be smaller than a certain size and the buffer is created to be that size, then an anomalous transaction that produces more data could cause it to write past the end of the buffer. If this overwrites adjacent data or executable code, this may result in erratic program behavior, including
Exploiting the behavior of a buffer overflow is a well-known
Technical description
A buffer overflow occurs when data written to a buffer also corrupts data values in memory addresses adjacent to the destination buffer due to insufficient bounds checking.[1]: 41 This can occur when copying data from one buffer to another without first checking that the data fits within the destination buffer.
Example
In the following example expressed in C, a program has two variables which are adjacent in memory: an 8-byte-long string buffer, A, and a two-byte big-endian integer, B.
char A[8] = "";
unsigned short B = 1979;
Initially, A contains nothing but zero bytes, and B contains the number 1979.
variable name | A | B | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
value | [ null string ]
|
1979 | ||||||||
hex value | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 07 | BB |
Now, the program attempts to store the null-terminated string "excessive"
with ASCII encoding in the A buffer.
strcpy(A, "excessive");
"excessive"
is 9 characters long and encodes to 10 bytes including the null terminator, but A can take only 8 bytes. By failing to check the length of the string, it also overwrites the value of B:
variable name | A | B | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
value | 'e' | 'x' | 'c' | 'e' | 's' | 's' | 'i' | 'v' | 25856 | |
hex | 65 | 78 | 63 | 65 | 73 | 73 | 69 | 76 | 65 | 00 |
B's value has now been inadvertently replaced by a number formed from part of the character string. In this example "e" followed by a zero byte would become 25856.
Writing data past the end of allocated memory can sometimes be detected by the operating system to generate a segmentation fault error that terminates the process.
To prevent the buffer overflow from happening in this example, the call to
strlcpy(A, "excessive", sizeof(A));
When available, the
Exploitation
The techniques to
Stack-based exploitation
There are several ways in which one can manipulate a program by exploiting stack-based buffer overflows:
- Changing program behavior by overwriting a local variable located near the vulnerable buffer on the stack;
- By overwriting the return address in a stack frame to point to code selected by the attacker, usually called the shellcode. Once the function returns, execution will resume at the attacker's shellcode;
- By overwriting a exception handlerto point to the shellcode, which is subsequently executed;
- By overwriting a local variable (or pointer) of a different stack frame, which will later be used by the function that owns that frame.[3]
The attacker designs data to cause one of these exploits, then places this data in a buffer supplied to users by the vulnerable code. If the address of the user-supplied data used to affect the stack buffer overflow is unpredictable, exploiting a stack buffer overflow to cause remote code execution becomes much more difficult. One technique that can be used to exploit such a buffer overflow is called "
Heap-based exploitation
A buffer overflow occurring in the heap data area is referred to as a heap overflow and is exploitable in a manner different from that of stack-based overflows. Memory on the heap is dynamically allocated by the application at run-time and typically contains program data. Exploitation is performed by corrupting this data in specific ways to cause the application to overwrite internal structures such as linked list pointers. The canonical heap overflow technique overwrites dynamic memory allocation linkage (such as
Microsoft's GDI+ vulnerability in handling JPEGs is an example of the danger a heap overflow can present.[5]
Barriers to exploitation
Manipulation of the buffer, which occurs before it is read or executed, may lead to the failure of an exploitation attempt. These manipulations can mitigate the threat of exploitation, but may not make it impossible. Manipulations could include conversion to upper or lower case, removal of
Practicalities of exploitation
In real-world exploits there are a variety of challenges which need to be overcome for exploits to operate reliably. These factors include null bytes in addresses, variability in the location of shellcode, differences between environments, and various counter-measures in operation.
NOP sled technique
A NOP-sled is the oldest and most widely known technique for exploiting stack buffer overflows.
Because of the popularity of this technique, many vendors of
While this method greatly improves the chances that an 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.[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 of any use. This can be a problem when the allocated size of the affected 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). Despite its problems, the NOP-sled is often the only method that will work for a given platform, environment, or situation, and as such it is still an important technique.
The jump to address stored in a register technique
The "jump to register" 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 a known pointer stored within a register which points to the controlled buffer and thus the shellcode. For example, if register A contains a pointer to the start of a buffer then any jump or call taking that register as an operand can be used to gain control of the flow of execution.[11]
In practice a program may not intentionally contain instructions to jump to a particular register. The traditional solution is to find an unintentional instance of a suitable opcode at a fixed location somewhere within the program memory. Figure E on the left contains 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 guarantee of success when it is run. For this reason, this is the technique most commonly used in
This method also allows shellcode to be placed after the overwritten return address on the Windows platform. Since executables are mostly based at address 0x00400000
and x86 is a
0x01000000
) and so have addresses containing no null bytes, so this method can remove null bytes (or other disallowed characters) from the overwritten return address. Used in this way, the method is often referred to as "DLL trampolining".
Protective countermeasures
Various techniques have been used to detect or prevent buffer overflows, with various tradeoffs. The following sections describe the choices and implementations available.
Choice of programming language
Assembly, C, and C++ are popular programming languages that are vulnerable to buffer overflow in part because they allow direct access to memory and are not
vector
's member function at()
performs a bounds check and throws an out_of_range
exception if the bounds check fails.[16]Languages that are strongly typed and do not allow direct memory access, such as COBOL, Java, Python, and others, prevent buffer overflow in most cases.
Use of safe libraries
The problem of buffer overflows is common in the C and C++ languages because they expose low level representational details of buffers as containers for data types. Buffer overflows can be avoided by maintaining a high degree of correctness in code that performs buffer management. It has also long been recommended to avoid standard library functions that are not bounds checked, such as
Well-written and tested abstract data type libraries that centralize and automatically perform buffer management, including bounds checking, can reduce the occurrence and impact of buffer overflows. The primary data types in languages in which buffer overflows are common are strings and arrays. Thus, libraries preventing buffer overflows in these data types can provide the vast majority of the necessary coverage. However, failure to use these safe libraries correctly can result in buffer overflows and other vulnerabilities, and naturally any
In September 2007, Technical Report 24731, prepared by the C standards committee, was published.[21] It specifies a set of functions that are based on the standard C library's string and IO functions, with additional buffer-size parameters. However, the efficacy of these functions for reducing buffer overflows is disputable. They require programmer intervention on a per function call basis that is equivalent to intervention that could make the analogous older standard library functions buffer overflow safe.[22]
Buffer overflow protection
Buffer overflow protection is used to detect the most common buffer overflows by checking that the
patches.Microsoft's implementation of
Stronger stack protection is possible by splitting the stack in two: one for data and one for function returns. This split is present in the Forth language, though it was not a security-based design decision. Regardless, this is not a complete solution to buffer overflows, as sensitive data other than the return address may still be overwritten.
This type of protection is also not entirely accurate because it does not detect all attacks. Systems like StackGuard are more centered around the behavior of the attacks, which makes them efficient and faster in comparison to range-check systems.[27]
Pointer protection
Buffer overflows work by manipulating pointers, including stored addresses. PointGuard was proposed as a compiler-extension to prevent attackers from reliably manipulating pointers and addresses.[28] The approach works by having the compiler add code to automatically XOR-encode pointers before and after they are used. Theoretically, because the attacker does not know what value will be used to encode and decode the pointer, one cannot predict what the pointer will point to if it is overwritten with a new value. PointGuard was never released, but Microsoft implemented a similar approach beginning in Windows XP SP2 and Windows Server 2003 SP1.[29] Rather than implement pointer protection as an automatic feature, Microsoft added an API routine that can be called. This allows for better performance (because it is not used all of the time), but places the burden on the programmer to know when its use is necessary.
Because XOR is linear, an attacker may be able to manipulate an encoded pointer by overwriting only the lower bytes of an address. This can allow an attack to succeed if the attacker can attempt the exploit multiple times or complete an attack by causing a pointer to point to one of several locations (such as any location within a NOP sled).[30] Microsoft added a random rotation to their encoding scheme to address this weakness to partial overwrites.[31]
Executable space protection
Executable space protection is an approach to buffer overflow protection that prevents execution of code on the stack or the heap. An attacker may use buffer overflows to insert arbitrary code into the memory of a program, but with executable space protection, any attempt to execute that code will cause an exception.
Some CPUs support a feature called
Some Unix operating systems (e.g. OpenBSD, macOS) ship with executable space protection (e.g. W^X). Some optional packages include:
- PaX[32]
- Exec Shield[33]
- Openwall[34]
Newer variants of Microsoft Windows also support executable space protection, called
Executable space protection does not generally protect against
Address space layout randomization
Address space layout randomization (ASLR) is a computer security feature that involves arranging the positions of key data areas, usually including the base of the executable and position of libraries, heap, and stack, randomly in a process' address space.
Randomization of the
processes and libraries in the virtual address space.Deep packet inspection
The use of deep packet inspection (DPI) can detect, at the network perimeter, very basic remote attempts to exploit buffer overflows by use of attack signatures and
Packet scanning is not an effective method since it can only prevent known attacks and there are many ways that a NOP-sled can be encoded.
Testing
Checking for buffer overflows and patching the bugs that cause them helps prevent buffer overflows. One common automated technique for discovering them is
Once a potential buffer overflow is detected it should be patched. This makes the testing approach useful for software that is in development, but less useful for legacy software that is no longer maintained or supported.History
Buffer overflows were understood and partially publicly documented as early as 1972, when the Computer Security Technology Planning Study laid out the technique: "The code performing this function does not check the source and destination addresses properly, permitting portions of the monitor to be overlaid by the user. This can be used to inject code into the monitor that will permit the user to seize control of the machine."[41] Today, the monitor would be referred to as the kernel.
The earliest documented hostile exploitation of a buffer overflow was in 1988. It was one of several exploits used by the
Since then, at least two major internet worms have exploited buffer overflows to compromise a large number of systems. In 2001, the
In 2003, buffer overflows present in licensed
See also
References
- . Informational.
- ^ "CORE-2007-0219: OpenBSD's IPv6 mbufs remote kernel buffer overflow". Retrieved 2007-05-15.
- ^ "Modern Overflow Targets" (PDF). Archived (PDF) from the original on 2022-10-09. Retrieved 2013-07-05.
- ^ "The Metasploit Opcode Database". Archived from the original on 12 May 2007. Retrieved 2007-05-15.
- ^ "Microsoft Technet Security Bulletin MS04-028". Microsoft. Archived from the original on 2011-08-04. Retrieved 2007-05-15.
- ^ "Creating Arbitrary Shellcode In Unicode Expanded Strings" (PDF). Archived from the original (PDF) on 2006-01-05. Retrieved 2007-05-15.
- ^ Vangelis (2004-12-08). "Stack-based Overflow Exploit: Introduction to Classical and Advanced Overflow Technique". Wowhacker via Neworder. Archived from the original (text) on August 18, 2007.
{{cite journal}}
: Cite journal requires|journal=
(help) - ^ Balaban, Murat. "Buffer Overflows Demystified" (text). Enderunix.org.
{{cite journal}}
: Cite journal requires|journal=
(help) - ^ Akritidis, P.; Evangelos P. Markatos; M. Polychronakis; Kostas D. Anagnostakis (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. Archived from the original (PDF) on 2012-09-01. Retrieved 2012-03-04.
- ^ Klein, Christian (September 2004). "Buffer Overflow" (PDF). Archived from the original (PDF) on 2007-09-28.
{{cite journal}}
: Cite journal requires|journal=
(help) - ^ Shah, Saumil (2006). "Writing Metasploit Plugins: from vulnerability to exploit" (PDF). Hack In The Box. Kuala Lumpur. Retrieved 2012-03-04.
- ^ 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. Archived from the original (PDF) on 2007-11-29.
- ^ Alvarez, Sergio (2004-09-05). "Win32 Stack BufferOverFlow Real Life Vuln-Dev Process" (PDF). IT Security Consulting. Retrieved 2012-03-04.
{{cite journal}}
: Cite journal requires|journal=
(help) - ^ Ukai, Yuji; Soeder, Derek; Permeh, Ryan (2004). "Environment Dependencies in Windows Exploitation". BlackHat Japan. Japan: eEye Digital Security. Retrieved 2012-03-04.
- ^ a b https://www.owasp.org/index.php/Buffer_OverflowsBuffer Overflows article on OWASP Archived 2016-08-29 at the Wayback Machine
- ^ "vector::at - C++ Reference". Cplusplus.com. Retrieved 2014-03-27.
- ^ "Archived copy". wiretap.area.com. Archived from the original on 5 May 2001. Retrieved 6 June 2022.
{{cite web}}
: CS1 maint: archived copy as title (link) - ^ "The Better String Library".
- ^ "The Vstr Homepage". Archived from the original on 2017-03-05. Retrieved 2007-05-15.
- ^ "The Erwin Homepage". Retrieved 2007-05-15.
- ^ International Organization for Standardization (2007). "Information technology – Programming languages, their environments and system software interfaces – Extensions to the C library – Part 1: Bounds-checking interfaces". ISO Online Browsing Platform.
- ^ "CERT Secure Coding Initiative". Archived from the original on December 28, 2012. Retrieved 2007-07-30.
- ^ "Libsafe at FSF.org". Retrieved 2007-05-20.
- ^ "StackGuard: Automatic Adaptive Detection and Prevention of Buffer-Overflow Attacks by Cowan et al" (PDF). Archived (PDF) from the original on 2022-10-09. Retrieved 2007-05-20.
- ^ "ProPolice at X.ORG". Archived from the original on 12 February 2007. Retrieved 2007-05-20.
- ^ "Bypassing Windows Hardware-enforced Data Execution Prevention". Archived from the original on 2007-04-30. Retrieved 2007-05-20.
- ISSN 0038-0644.
- ^ "12th USENIX Security Symposium – Technical Paper". www.usenix.org. Retrieved 3 April 2018.
- ^ "Protecting against Pointer Subterfuge (Kinda!)". msdn.com. Archived from the original on 2010-05-02. Retrieved 3 April 2018.
- ^ "USENIX - The Advanced Computing Systems Association" (PDF). www.usenix.org. Archived (PDF) from the original on 2022-10-09. Retrieved 3 April 2018.
- ^ "Protecting against Pointer Subterfuge (Redux)". msdn.com. Archived from the original on 2009-12-19. Retrieved 3 April 2018.
- ^ "PaX: Homepage of the PaX team". Retrieved 2007-06-03.
- ^ "KernelTrap.Org". Archived from the original on 2012-05-29. Retrieved 2007-06-03.
- ^ "Openwall Linux kernel patch 2.4.34-ow1". Archived from the original on 2012-02-19. Retrieved 2007-06-03.
- ^ "Microsoft Technet: Data Execution Prevention". Archived from the original on 2006-06-22. Retrieved 2006-06-30.
- ^ "BufferShield: Prevention of Buffer Overflow Exploitation for Windows". Retrieved 2007-06-03.
- ^ "NGSec Stack Defender". Archived from the original on 2007-05-13. Retrieved 2007-06-03.
- ^ "PaX at GRSecurity.net". Retrieved 2007-06-03.
- ^ "The Exploitant - Security info and tutorials". Retrieved 2009-11-29.
- ^ Larochelle, David; Evans, David (13 August 2001). "Statically Detecting Likely Buffer Overflow Vulnerabilities". USENIX Security Symposium. 32.
- ^ "Computer Security Technology Planning Study" (PDF). p. 61. Archived from the original (PDF) on 2011-07-21. Retrieved 2007-11-02.
- ^ ""A Tour of The Worm" by Donn Seeley, University of Utah". Archived from the original on 2007-05-20. Retrieved 2007-06-03.
- ^ "Bugtraq security mailing list archive". Archived from the original on 2007-09-01. Retrieved 2007-06-03.
- ^ ""Smashing the Stack for Fun and Profit" by Aleph One". Retrieved 2012-09-05.
- ^ "eEye Digital Security". Archived from the original on 2009-06-20. Retrieved 2007-06-03.
- ^ "Microsoft Technet Security Bulletin MS02-039". Microsoft. Archived from the original on 2008-03-07. Retrieved 2007-06-03.
- ^ "Hacker breaks Xbox protection without mod-chip". Archived from the original on 2007-09-27. Retrieved 2007-06-03.
External links
- "Discovering and exploiting a remote buffer overflow vulnerability in an FTP server" by Raykoid666
- "Smashing the Stack for Fun and Profit" by Aleph One
- Gerg, Isaac (2005-05-02). "An Overview and Example of the Buffer-Overflow Exploit" (PDF). IAnewsletter. 7 (4). Information Assurance Technology Analysis Center: 16–21. Archived from the original (PDF) on 2006-09-27. Retrieved 2019-03-17.
- CERT Secure Coding Standards
- CERT Secure Coding Initiative
- Secure Coding in C and C++
- SANS: inside the buffer overflow attack
- "Advances in adjacent memory overflows" by Nomenumbra
- A Comparison of Buffer Overflow Prevention Implementations and Weaknesses
- More Security Whitepapers about Buffer Overflows
- Chapter 12: Writing Exploits III from Sockets, Shellcode, Porting & Coding: Reverse Engineering Exploits and Tool Coding for Security Professionals by James C. Foster (ISBN 1-59749-005-9). Detailed explanation of how to use Metasploit to develop a buffer overflow exploit from scratch.
- Computer Security Technology Planning Study, James P. Anderson, ESD-TR-73-51, ESD/AFSC, Hanscom AFB, Bedford, MA 01731 (October 1972) [NTIS AD-758 206]
- "Buffer Overflows: Anatomy of an Exploit" by Nevermore
- Secure Programming with GCC and GLibc Archived 2008-11-21 at the Wayback Machine (2008), by Marcel Holtmann
- "Criação de Exploits com Buffer Overflor – Parte 0 – Um pouco de teoria " (2018), by Helvio Junior (M4v3r1ck)