Skip to content

pdoffl/CanaryTakeover

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

Repository files navigation

image

Summary

Implemented a Python-based Proof-of-Concept for exploiting stack-based buffer overflow vulnerability in a Linux application leveraging stack canary protection.

A critical stack-based buffer overflow vulnerability exists in the target echo1 binary that allows remote attackers to execute arbitrary code by bypassing stack canary protection through a bruteforce attack. The vulnerability is exploitable due to the application's fork-and-run architecture, which maintains consistent canary values across child processes.

The application can be hosted and run in a containerized environment as well by using the following Docker image - sierraneu/canarynuid

Vulnerability Overview

  • Severity: Critical
  • CVSSv3 Score: 9.8 (Critical)
  • Attack Vector: Network
  • Attack Complexity: Low
  • Privileges Required: None
  • User Interaction: None

Vulnerability Details

  • Affected Binary: echo1 (ELF 64-bit LSB)
  • Vulnerability Type: Stack-based Buffer Overflow (CWE-121)
  • Root Cause: Insufficient input validation in message handling routine
  • Bypass Technique: Stack canary bruteforce via persistent memory layout

Technical Analysis

Security Mechanisms Present

$ checksec --file=echo1
RELRO           STACK CANARY      NX            PIE
Partial RELRO   Canary found      NX enabled    No PIE

Protections Identified:

  • Stack Canary (SSP) - BYPASSED
  • NX (Non-Executable Stack) - CIRCUMVENTED via ROP
  • PIE (Position Independent Executable) - Not enabled
  • ASLR - Irrelevant due to static function addresses

Vulnerability Analysis

The echo1 application exhibits the following exploitable characteristics:

  1. Input Buffer Overflow: User-controlled input overflows into stack canary region at 56-byte boundary
  2. Fork-and-Run Architecture: Child processes inherit identical memory layout, maintaining consistent canary values
  3. Deterministic Response: Server returns "Request complete, Closing..." only when canary remains intact
  4. Static Function Addresses: The win() function exists at fixed address 0x40152f

Exploitation Strategy

The exploit operates in three distinct phases:

Phase 1: Buffer Size Discovery

Incrementally send increasing payload sizes until server fails to respond (no "Request complete, Closing..." response), indicating canary corruption. The pseudocode below demonstrates the idealogy behind buffer size discovery.

Payload: 'A' * N (where N = 1, 2, 3, ... until no response)
Result: Buffer size = 56 bytes

Phase 2: Canary Bruteforce

Abuse fork-and-run behavior to bruteforce each canary byte independently. If the server runs a response post canary byte overwrite, it means the correct canary byte was guessed. The pseudocode below explains how it works.

For each byte position (0-7):
    For each possible value (0x00-0xFF):
        Send: buffer + known_canary_bytes + test_byte
        If response received: canary_byte = test_byte

Complexity: 8 bytes × 256 values = ~2,048 attempts (worst case)
Time: ~6-7 minutes at 0.2s per attempt

Phase 3: Control Flow Hijack

Construct final payload to overwrite return address with win() function pointer.

Payload Structure:
[Buffer: 56 bytes] + [Canary: 8 bytes] + [SFP: 8 bytes] + [RET: 0x40152f]

Memory Layout

Low Address
+------------------------+
|   Buffer (56 bytes)    |  <- User input
+------------------------+
|   Canary (8 bytes)     |  <- Stack protection
+------------------------+
|   SFP (8 bytes)        |  <- Saved frame pointer
+------------------------+
|   RET (8 bytes)        |  <- Return address (TARGET)
+------------------------+
High Address

Proof of Concept

Prerequisites

# Install required dependencies
sudo apt-get update
sudo apt-get install python3 docker.io

# Pull vulnerable server
sudo docker pull sierraneu/canarynuid
sudo docker run -dit -p 9999:9999 --name echo1_server sierraneu/canarynuid

Exploitation

# Clone repository
git clone https://github.com/pdoffl/CanaryTakeover.git
cd CanaryTakeover

# Run exploit
python3 CanaryTakeover-PoC.py <TARGET_IP> <TARGET_PORT>

# Example
python3 exploit-script.py 127.0.0.1 9999

Expected Output

<----- Checking for 'echo1' server's reachability -----> 
[*] Connection to the server succeeded. Proceeding with the exploit.

<----- Starting interaction to determine buffer length ----->
[+] BUFFER LENGTH FOUND: 56

<----- Initiating procedure to bruteforce canary value ----->
[+] Found byte #1 of canary: 0x0
[+] Found byte #2 of canary: 0xde
[+] Found byte #3 of canary: 0xce
[+] Found byte #4 of canary: 0xc3
[+] Found byte #5 of canary: 0x14
[+] Found byte #6 of canary: 0x4c
[+] Found byte #7 of canary: 0xf3
[+] Found byte #8 of canary: 0xd2

[+] Canary value identified: 0x0, 0xde, 0xce, 0xc3, 0x14, 0x4c, 0xf3, 0xd2

<----- Initiating procedure to overwrite return address ----->
[+] HERE'S THE FLAG:

FLAG{STACK_SMASHING_NOT_DETECTED_RayXd9GW}

Report

Read the full report here to understand more about the Proof-of-Concept.

Impact Assessment

Severity Justification

Critical - This vulnerability allows unauthenticated remote attackers to:

  • Execute arbitrary code with server privileges
  • Read sensitive files (flag.txt, configuration data)
  • Establish persistent backdoor access
  • Pivot to internal network segments

Real-World Scenarios

While this is an academic challenge, similar vulnerabilities have been observed in:

  • IoT device management services
  • Legacy network services with poor input validation

Mitigation & Remediation

Immediate Actions

  1. Network Segmentation: Restrict access via firewall rules
  2. Monitoring: Deploy IDS signatures for canary bruteforce patterns

Long-Term Fixes

  • Implement proper input validation: For instance, checking input size before passing it on to the next function.
// Implement proper input validation
#define MAX_INPUT_SIZE 50

ssize_t bytes_read = read(socket_fd, buffer, MAX_INPUT_SIZE);
if (bytes_read >= MAX_INPUT_SIZE) {
    syslog(LOG_WARNING, "Input size exceeded, potential attack detected");
    close(socket_fd);
    exit(1);
}

Defense-in-Depth Recommendations

  1. Enable PIE/ASLR: Compile with -fPIE -pie flags
  2. Implement FORTIFY_SOURCE: Add -D_FORTIFY_SOURCE=2 during compilation
  3. Use Safe Functions: Replace gets(), strcpy() with bounds-checked alternatives
  4. Add Length Checks: Validate all input against maximum buffer sizes
  5. Limit Fork Behavior: Implement request rate limiting and connection throttling

Screenshots

image
  • Figure (Left): Using 'netcat' as a client to interact with the 'echo1' application
  • Figure (Right): 'echo1' application's response

PratikDas-SC6-OLD

  • Figure: Using the Python PoC against 'echo1' application deployed on a server

Credits

  • Institution: Northeastern University
  • Course: CY5130 (Computer Systems Security)
  • Instructor: Dr. Jose Sierra
  • Date: Spring 2024

Disclaimer

Educational Purpose Only

This proof of concept is provided for educational and research purposes only. The author does not condone or encourage the use of this exploit against systems without explicit authorization.

Use at your own risk. The author assumes no liability for misuse of this information.

About

A Python-based PoC for a Linux based application vulnerable to stack-based buffer overflow. Implemented for NEU's CY5130 Project.

Topics

Resources

Stars

Watchers

Forks

Contributors

Languages