root@thehacksparrow:~/writeups$ SYSTEM ONLINE
root@sparrow:~/writeups$ cat cyborg.md
// Offensive

Cyborg

10 Feb 2023 · 9 min read
Executive summary — Cyborg is an Easy Linux room on TryHackMe that chains a web information leak, hash cracking and an encrypted backup. The app exposes a Squid proxy configuration containing an APR1 hash that we crack with John; that password turns out to be the passphrase of a Borg repository downloaded from the admin panel, from which we recover SSH credentials for user alex. Once inside, the final escalation abuses a script runnable as root via sudo. A Web → Borg → SSH → Root journey.
PlatformTryHackMe
Operating systemLinux
DifficultyEasy
RoomCyborg
Target IPMACHINE_IP

Attack map

[80/HTTP]  web application
   |  /etc/squid/passwd exposed -> APR1 hash (music_archive)
   v
[CRACK]  john + rockyou -> music_archive:squidward
   |  download archive.tar from /admin -> Borg repository
   v
[BORG]  borg extract (passphrase: squidward) -> alex's note.txt
   |  recovered SSH credentials
   v
[SSH]  alex@MACHINE_IP  ->  user.txt
   |  sudo -l  ->  abusable root-run script (PATH / writable)
   v
[ROOT]  root.txt

1. Reconnaissance

We start by mapping the attack surface with a full TCP scan, running default scripts and version detection:

sudo nmap -sC -sV -T4 -p- MACHINE_IP

Why these flags:

  • -sC → runs the default NSE scripts (banners, HTTP titles, etc.).
  • -sV → identifies each service's version.
  • -p- → scans all 65535 TCP ports, not just the top 1000.
  • -T4 → aggressive timing template (fast but not reckless).

Relevant result: 22/tcp (SSH) and 80/tcp (HTTP) are open.

Analysis: with SSH and a web service exposed, the entry vector is almost certainly the web application; SSH is saved for later, once we hold credentials.

2. Web enumeration and hash retrieval

We brute-force common and interesting paths with a directory-enumeration tool:

gobuster dir -u http://MACHINE_IP/ -w /usr/share/wordlists/dirb/common.txt -x php,txt

Two paths stand out: /admin (an authentication panel) and /etc, which turns out to be browsable and mirrors the box's real OS filesystem — a serious misconfiguration on its own. Walking into /etc/squid/ we find Squid's configuration and password file served directly over HTTP. We fetch the password file:

curl -s http://MACHINE_IP/etc/squid/passwd | tee passwd.hash

The content is an MD5-crypt (APR1) hash for user music_archive — the $apr1$... format used by Apache/Squid for basic authentication.

Public background — how Squid stores this: Squid's basic_auth scheme doesn't check credentials itself; it delegates to an external helper (commonly basic_ncsa_auth), wired up in squid.conf with a line such as auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd. That helper reads a standard htpasswd-format file — the same format Apache uses for HTTP Basic Auth — where each line is user:$apr1$salt$hash. APR1 ("Apache MD5") is MD5 run through roughly 1,000 salted iterations: slower to crack than raw MD5, but still far weaker than modern KDFs like bcrypt/scrypt/yescrypt — well within reach of john/hashcat (mode 1600) against a wordlist like rockyou.
The lesson here: serving internal configuration files (/etc/squid/) through the web server is a serious information leak. They should never be reachable from the document root.

3. Cracking the APR1 hash with John

With the hash in a file, we run John the Ripper against the rockyou wordlist. John auto-detects the APR1 format:

john passwd.hash --wordlist=/usr/share/wordlists/rockyou.txt
john --show passwd.hash

Result:

music_archive:squidward
Keep this password: squidward is not just music_archive's credential; later on it turns out to be the passphrase of the Borg repository. Password reuse is what chains the whole box together.

4. Downloading and extracting the site archive

In the site's admin panel (http://MACHINE_IP/admin, Archive → Download section) there is a downloadable archive.tar. We unpack it:

# after downloading archive.tar from http://MACHINE_IP/admin
tar -xvf archive.tar

Inside we find a Borg repository at home/field/dev/final_archive, with the typical Borg files: README, config, data/, index, nonce and integrity/hint files.

What Borg is: borgbackup is a deduplicating, encrypted backup tool. In its default repokey/keyfile encryption modes, the repository key is derived from the passphrase (via PBKDF2) and used to drive AES-256 in CTR mode for confidentiality plus HMAC-SHA256 for integrity/authentication of every chunk. That is exactly why a repository is not read «by hand»: without the correct passphrase the on-disk data/, index and nonce files are opaque ciphertext, and only the borg client can unwrap them.

5. Listing and extracting the Borg repository

We install borgbackup if missing and list the repository. The passphrase is the password we cracked earlier, squidward:

sudo apt-get update && sudo apt-get install -y borgbackup
borg list ./home/field/dev/final_archive
borg extract ./home/field/dev/final_archive::music_archive

Why it works: borg list shows the repository's archives (snapshots) — here, one named music_archive. borg extract dumps its contents into the current directory. When prompted for the passphrase, we enter squidward.

After extracting, we inspect the recovered files looking for credentials:

grep -Rni "alex" .
cat home/alex/Documents/note.txt

The recovered note contains SSH credentials for user alex.

Chain so far: Squid hash leak → cracking → Borg passphrase → SSH credential theft from a backup. A «minor» flaw (exposed config file) becomes system access.

6. SSH access and user flag

With the recovered credentials, we log in over SSH as alex:

ssh alex@MACHINE_IP

And read the user flag:

cat ~/user.txt

7. Privilege escalation

First reflex after landing a user: check what we can run with sudo without a password:

sudo -l

The box escalates through a script executed with root privileges (something like backup.sh) that is abusable. Depending on how it is configured, the vector fits one of these two classic patterns:

  • PATH injection: if the root script calls a binary by name (no absolute path), we create a malicious binary with that name and prepend its directory to PATH before invoking it.
  • Writable script: if the script —or a file it executes— sits in a writable path, we replace it with one that spawns a shell.
Consistent approach: enumerate sudo -l, locate root-run scripts that are readable/writable, and analyze how they use PATH and which commands they invoke. That is where the escalation lives.

Once exploited, we confirm privileges and read the root flag:

id
cat /root/root.txt

Vulnerability summary

PhaseComponentVulnerabilityImpact
WebHTTP serverSquid configuration file (/etc/squid/passwd) exposed over HTTPLeak of music_archive's APR1 hash
CredentialsAPR1 hashWeak password crackable with rockyouReused passphrase (squidward)
BackupBorg repositoryEncrypted backup downloadable with a known passphraseSSH credentials for alex
PrivEscsudo / root-run scriptScript runnable as root, abusable via PATH or write accessExecution as root

Lessons learned

  • Config leak: never serve internal files (/etc/squid/) from the document root. A leaked hash is a starting point.
  • Password reuse: squidward was both a web credential and the Borg passphrase. A single weak password toppled several layers.
  • Backups as a target: an encrypted backup is not safe if the passphrase is weak or stored elsewhere. They hold juicy secrets (here, SSH credentials).
  • Sudoers hygiene: allowing a poorly written root-run script (PATH-based calls, writable files) is equivalent to handing out a root shell. Audit it.