Lably
Skip to content

Buffer overflow

Anomaly in computer security and programming

  • 18 min read
  • 4 chapters

Related on Lably

Through Computer programming, Computer program and Execution (computing)

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 memory access errors, incorrect results, and crashes.

Exploiting the behavior of a buffer overflow is a well-known security exploit. Files specifically created to exploit buffer overflow vulnerabilities are often called 'crafted' files. On many systems, the memory layout of a program, or the system as a whole, is well defined. By sending in data designed to cause a buffer overflow, it is possible to write into areas known to hold executable code and replace it with malicious code, or to selectively overwrite data pertaining to the program's state, therefore causing behavior that was not intended by the original programmer. Buffers are widespread in operating system (OS) code, so it is possible to make attacks that perform privilege escalation and gain unlimited access to the computer's resources. The famed Morris worm in 1988 used this as one of its attack techniques.

Programming languages commonly associated with buffer overflows include C and C++, which provide no built-in protection against accessing or overwriting data in any part of memory and do not automatically check that data written to an array (the built-in buffer type) is within the boundaries of that array. Bounds checking can prevent buffer overflows, but requires additional code and processing time. Modern operating systems use a variety of techniques to combat malicious buffer overflows, notably by randomizing the layout of memory, or deliberately leaving space between buffers and looking for actions that write into those areas ("canaries").

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. 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.

<span id="mwQw"></span><span class="kt" id="mwRA">char</span><span class="w" id="mwRQ"> </span><span class="n" id="mwRg">a</span><span class="p" id="mwRw">[</span><span class="mi" id="mwSA">8</span><span class="p" id="mwSQ">]</span><span class="w" id="mwSg"> </span><span class="o" id="mwSw">=</span><span class="w" id="mwTA"> </span><span class="s" id="mwTQ">""</span><span class="p" id="mwTg">;</span> <span class="kt" id="mwTw">unsigned</span><span class="w" id="mwUA"> </span><span class="kt" id="mwUQ">short</span><span class="w" id="mwUg"> </span><span class="n" id="mwUw">b</span><span class="w" id="mwVA"> </span><span class="o" id="mwVQ">=</span><span class="w" id="mwVg"> </span><span class="mi" id="mwVw">1979</span><span class="p" id="mwWA">;</span>

Initially, a contains nothing but zero bytes, and b contains the number 1979.

Now, the program attempts to store the null-terminated string "excessive" with ASCII encoding in the A buffer.

<span id="mwhw"></span><span class="n" id="mwiA">strcpy</span><span class="p" id="mwiQ">(</span><span class="n" id="mwig">a</span><span class="p" id="mwiw">,</span><span class="w" id="mwjA"> </span><span class="s" id="mwjQ">"excessive"</span><span class="p" id="mwjg">);</span>

"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:

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 strcpy could be replaced with strlcpy, which takes the maximum capacity of a (including a null-termination character) as an additional parameter and ensures that no more than this amount of data is written to a:

<span id="mw0g"></span><span class="n" id="mw0w">strlcpy</span><span class="p" id="mw1A">(</span><span class="n" id="mw1Q">a</span><span class="p" id="mw1g">,</span><span class="w" id="mw1w"> </span><span class="s" id="mw2A">"excessive"</span><span class="p" id="mw2Q">,</span><span class="w" id="mw2g"> </span><span class="k" id="mw2w">sizeof</span><span class="p" id="mw3A">(</span><span class="n" id="mw3Q">a</span><span class="p" id="mw3g">));</span>

When available, the strlcpy library function is preferred over strncpy which does not null-terminate the destination buffer if the source string's length is greater than or equal to the size of the buffer (the third argument passed to the function). Therefore a may not be null-terminated and cannot be treated as a valid C-style string.

Sign in to keep reading

3 more chapters are free with a Lably account.

More in Computing and communication