Skip to content

GrossmanOri/vulnerable-http-server

Repository files navigation

Vulnerable HTTP Server — Security Exploitation Demo

A deliberately vulnerable HTTP server written in C, built to demonstrate four classic vulnerability classes against a real running process on Apple Silicon (ARM64).

This project was built as part of a security engineering course at Shenkar College. Every exploit targets a genuine binary — no CTF scaffolding, no synthetic wrappers.


Vulnerabilities Demonstrated

1. Variable Overflow — check_auth

A struct lays char password_buffer[16] immediately before volatile int is_authenticated in memory. The copy loop is bounded by sizeof(struct) (20) rather than the buffer size (16), so writing 17 bytes overwrites the authentication flag without ever knowing the password.

2. Stack Buffer Overflow — do_login / write_creds

write_creds performs an unbounded copy into a 16-byte stack buffer. Sending 48 bytes past the dummy strip overwrites the saved return address (x30 on ARM64) on the stack.

3. Return Address Hijack → Backdoor Database Dump

The overflow from #2 redirects x30 to dump_user_database, a function that is never called in normal execution. It reads passwords.txt and sends the full contents to the client socket, then calls exit(0) to avoid crashing on the corrupted stack frame.

4. Timing Side-Channel — slow_strcmp

The password comparison calls usleep(2000) for every matching character before continuing. This creates a ~2ms measurable RTT increase per correct character. The attack recovers the password one character at a time by measuring median response latency over 30 samples per candidate.


Technical Details

Target: ARM64 Apple Silicon (macOS), compiled with Clang
Stack frame verified by: otool -tV disassembly + LLDB disassemble --name do_login

do_login frame layout (confirmed by disassembly)

sub  sp, sp, #0x40            ; 64-byte frame
stp  x29, x30, [sp, #0x30]   ; saved x29 at sp+48, x30 at sp+56
add  x0, sp, #0x10            ; password_buf at sp+16

sp+16 .. sp+31   password_buf[16]         ← overflow starts here
sp+32 .. sp+55   padding, stored args, x29
sp+56 .. sp+63   saved x30 (return addr)  ← hijack target

Distance from password_buf → saved x30: 40 bytes
Payload: fill(16) + bridge(24) + addr(8) = 48 bytes after dummy strip

Why the protections are disabled

Flag Protection removed Effect
-fno-stack-protector Stack canary Canary would catch the overflow before ret
-mbranch-protection=none ARM64 PAC PAC validates x30 before ret; hijacked address would trap
-O0 Compiler optimization Keeps stack layout deterministic

Build

make clean && make

Requires: gcc, make, macOS with Xcode Command Line Tools.


Running the Attacks

Attack 1 — Variable Overflow (auth bypass)

./server &
python3 attack1.py
# Expected: [+] ACCESS GRANTED

Attack 2+3 — Return Address Hijack + Database Dump

# Terminal 1
lldb ./server
(lldb) settings set target.disable-aslr true
(lldb) run
(lldb) image lookup -n dump_user_database   # note the address
(lldb) continue

# Terminal 2
python3 attack2.py <address>
# Expected: [+] ACCESS GRANTED then === BACKDOOR: PASSWORD DATABASE DUMP ===

Attack 4 — Timing Side-Channel

./server &
python3 timing_attack.py
# Recovers 'secret123' character by character (~5 minutes)

How the Timing Attack Works

slow_strcmp sleeps 2ms per matching character. Measuring median RTT over 30 samples per candidate produces a consistent ~2ms gap for the correct character at each position:

Position 0:  's'   2.95 ms   gap: +1.96 ms
Position 1:  'e'   5.47 ms   gap: +2.11 ms
Position 2:  'c'   7.79 ms   gap: +1.90 ms
Position 3:  'r'  10.11 ms   gap: +2.22 ms
Position 4:  'e'  13.31 ms   gap: +2.41 ms
Position 5:  't'  14.74 ms   gap: +2.15 ms
Position 6:  '1'  16.97 ms   gap: +2.08 ms
Position 7:  '2'  19.96 ms   gap: +2.11 ms
→  [+] PASSWORD FOUND: 'secret123'

The script uses statistics.median() over 30 samples and a 1.2ms minimum gap threshold to reject OS jitter and prevent cascade failures from a single wrong character.


Mitigations (what stops these in production)

Attack Mitigation
Variable overflow Bound the copy loop to the buffer size, not sizeof(struct)
Stack buffer overflow Use bounded copy functions (strncpy, memcpy with size check)
Return address hijack Stack canary (-fstack-protector) + ARM64 PAC (-mbranch-protection=standard)
Timing side-channel Constant-time comparison (memcmp on fixed-length buffers, or CRYPTO_memcmp)

Project Structure

├── main.c            entry point
├── httpd.c           fork-based server loop, HTTP dispatch
├── http_protocol.c   HTTP parser
├── router.c          route handlers + all four vulnerabilities
├── httpd.h           shared types and macros
├── Makefile
├── passwords.txt     sample credential store
├── attack1.py        Attack 1 — variable overflow
├── attack2.py        Attack 2+3 — return address hijack
└── timing_attack.py  Attack 4 — timing side-channel

Note: This server is intentionally insecure and is intended for educational and demonstration purposes only. Do not expose it on a network.

About

Deliberately vulnerable HTTP server with ARM64 stack exploitation, return address hijacking, and timing side-channel attack — Shenkar security engineering course

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors