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.
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.
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.
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.
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.
Target: ARM64 Apple Silicon (macOS), compiled with Clang
Stack frame verified by: otool -tV disassembly + LLDB disassemble --name do_login
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
| 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 |
make clean && makeRequires: gcc, make, macOS with Xcode Command Line Tools.
./server &
python3 attack1.py
# Expected: [+] ACCESS GRANTED# 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 ===./server &
python3 timing_attack.py
# Recovers 'secret123' character by character (~5 minutes)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.
| 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) |
├── 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.