Get a Pentest and security assessment of your IT network.

Cyber Security

Buffer Overflow: Canary Protection

TL;DR

Terminator canaries (stack canaries) are a security measure to detect buffer overflows on the stack. They work by placing a known value (the canary) just before the return address on the stack. If a buffer overflow overwrites the canary, it indicates a potential attack. When the function returns, the program checks if the canary has been modified. If it has, the program terminates to prevent malicious code execution.

How Buffer Overflow with Canaries Works

Stack canaries don’t prevent buffer overflows; they detect them. Here’s how:

  1. Canary Placement: When a function is called, the compiler inserts a random value (the canary) onto the stack immediately before the saved return address.
  2. Overflow Attempt: If a buffer overflow occurs within that function, it may overwrite the canary value.
  3. Return Check: Before returning from the function, the program checks if the canary value has changed.
  4. Detection & Termination: If the canary is different from its original value, the program knows a buffer overflow likely happened and terminates (often with an error message like ‘Stack smashing detected’).

Steps to Understand and Test Canary Protection

  1. Compilation with Canaries: Most compilers enable stack canaries by default. However, you might need to explicitly enable them using compiler flags. For GCC, use the -fstack-protector flag.
    gcc -fstack-protector vulnerable_program.c -o vulnerable_program
  2. Vulnerable Code Example: Consider this simple C code:
    #include <stdio.h>
    #include <string.h>
    
    int main() {
      char buffer[64];
      printf("Enter input: ");
      gets(buffer); // Vulnerable function!
      printf("You entered: %sn", buffer);
      return 0;
    }
    

    This code uses gets(), which doesn’t perform bounds checking.

  3. Attempting an Overflow (Without Canaries): If you compile this without canaries and provide input larger than 64 bytes, you can overwrite the return address and potentially hijack execution.
  4. Attempting an Overflow (With Canaries): When compiled with -fstack-protector, attempting the same overflow will likely result in a ‘Stack smashing detected’ error before your malicious code runs. The program terminates because the canary was overwritten.
  5. Disabling Canaries (For Testing – Use Caution!): You can disable stack canaries for testing purposes using the -fno-stack-protector flag. However, this makes your program vulnerable and should only be done in a controlled environment.
    gcc -fno-stack-protector vulnerable_program.c -o vulnerable_program
  6. Examining the Stack (GDB): Use GDB to examine the stack layout and see how the canary is placed.
    • Start GDB: gdb ./vulnerable_program
    • Set a breakpoint before the return: break main
    • Run the program: run
    • Examine the stack: x/20wx $rsp (This shows 20 words starting from the stack pointer)

    You should see a random value (the canary) just before the return address.

Bypassing Canaries

Canary protection isn’t foolproof. Attackers can sometimes bypass it using techniques like:

  • Information Leaks: If an attacker can leak the canary value (e.g., through a format string vulnerability), they can include it in their overflow payload.
  • Multiple Overflows: In some cases, multiple smaller overflows can be used to overwrite parts of the stack without triggering the canary check.
  • Return-Oriented Programming (ROP): ROP allows attackers to chain together existing code snippets within the program to achieve their goals, even if they don’t have direct control over the return address.

Mitigation Strategies

  • Use Safe Functions: Avoid vulnerable functions like gets() and use safer alternatives like fgets() that allow you to specify a maximum buffer size.
  • Address Space Layout Randomization (ASLR): ASLR makes it harder for attackers to predict the location of important data, including the canary value.
  • Data Execution Prevention (DEP/NX): DEP prevents code from being executed in memory regions that are intended for data storage.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation