Lukas' Notes

security memory c

Definition

Buffer Overflow

A buffer overflow is a memory-safety bug in which a program writes past the bounds of a fixed-size buffer, overwriting the adjacent memory. For a buffer stored on the stack the memory immediately above it holds the saved base pointer and the saved return address — so an overflow past the buffer’s upper bound walks directly into the control data the CPU uses to direct execution on return.

Local Variables Live on the Stack

Stack layout that makes an overflow dangerous

In C, a local array such as char buffer[10] = {0}; lives in the calling function’s stack frame, at addresses below the saved base pointer and saved return address. The stack grows towards lower addresses, so the saved return address sits above the buffer.

Example

TP-Link httpd (2019)

A buffer overflow vulnerability in the httpd daemon of TP-Link router firmware allowed remote takeover of the router.

  • the failed defence
    • the firmware imposed a character limit on the password field, but only enforced it in the user interface
  • the bypass
    • an attacker who inspects and modifies the network request directly can append more characters than the UI would have allowed, defeating the length check
  • the consequence
    • the over-long input overflows the server-side buffer in httpd and lets the attacker take over the router from across the network

Unsafe Operations That Trigger It

Operations that can overflow a stack buffer

The C standard library exposes several operations that copy attacker-controlled input without checking the destination’s size:

  • gets(buf) — reads from stdin into buf until a newline, with no length bound; never use.
  • strcpy(dst, src) / strcat(dst, src) — copy/concatenate until a null terminator in src, never bounded by dst’s size.
  • read(fd, buf, n) / memcpy(dst, src, n) with n derived from attacker input — the missing bounds check is the bug (see Heartbleed).

The bounded replacements — fgets, strlcpy/strlcat, and computing n against the destination size — are the safer alternatives, but they only help where the programmer remembered to use them.

Consequence

Obs

There are two outcomes for an overflow past a stack buffer, and the difference is the whole point of the attack:

  • overwriting the saved return address with an invalid address — the function tries to return to a non-executable or unmapped region and the process dies with a segmentation fault, which is the benign, noisy failure mode the read(0, buffer, 100) demo crashes with;
  • overwriting the saved return address with a valid, attacker-chosen address — the function returns into the attacker’s code, turning a length bug into control-flow hijack.

The cluster attacks (lecture 12+ onward) build on this second case.