← all walkthroughs

Blocky

Linux· Easy· Web
owned
2026-07-02
time to own
2m24s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I browsed a publicly exposed file-listing page co-hosted on the WordPress server, downloaded a custom Minecraft plugin JAR, and recovered hardcoded MySQL root credentials stored in plaintext in the compiled bytecode. Those same credentials had been reused as the Linux login password for the local account 'notch', granting an immediate SSH shell and the user flag.

Because notch held unrestricted sudo rights, a single sudo command with the already-known password produced a root shell and full system control.

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>"

Attack path — how the box was taken

1ReconnaissanceNetwork service enumeration
Mapped open services and confirmed WordPress on port 80
I scanned the target and identified FTP on port 21, SSH on port 22, and an HTTP server on port 80 hosting a WordPress site under the virtual host blocky.htb. This gave a clear map of the attack surface before any exploitation began.
Exact commands 2
Full port scan with version detection — confirms FTP, SSH, and HTTP services.
nmap -sC -sV -p- -oN nmap_blocky.txt $TARGET
Confirm WordPress is serving the blocky.htb vhost on port 80.
curl -sS -I -H 'Host: blocky.htb' http://$TARGET/
2DiscoveryUnauthenticated directory listing / exposed sensitive files (CWE-548)
Found an unauthenticated file-browser page exposing downloadable plugin JARs
Browsing the web root revealed a co-hosted file-listing application at /plugins/. The page required no login and listed a files/ subdirectory containing two Java plugin archives — BlockyCore.jar and a griefprevention jar — available for direct download by anyone on the internet.
Curl returned an HTTP 200 listing BlockyCore.jar under /plugins/files/ with no authentication challenge.
Exact commands 2
Confirm the file-browser landing page is publicly accessible.
curl -sS -H 'Host: blocky.htb' http://$TARGET/plugins/
Trigger the directory listing — reveals BlockyCore.jar and the griefprevention jar in files/.
curl -sS -H 'Host: blocky.htb' http://$TARGET/plugins/scan.php
FixRemove or authenticate the plugin file-browser directoryHigh
WeaknessA file-listing web application at /plugins/ allowed any internet user to browse and download all plugin archives with no login. This turned an internal development artifact into a publicly readable credential store that required no attack tooling to exploit — just a browser.
FixRemove the file-browser plugin from the production web server entirely; it has no legitimate public-facing purpose. Block web access to all non-public directories at the web server level (nginx: 'deny all;' inside the location block; Apache: 'Require all denied'). If plugin files must be distributed, serve them from an authenticated portal or a private object-storage bucket with signed URLs. Perform a full audit of the web root for any other directories or files that should not be publicly accessible.
3Credential AccessHardcoded credentials in compiled artifact (T1552.001)
Extracted hardcoded MySQL root credentials from the downloaded JAR
BlockyCore.jar was downloaded and its contents extracted. The compiled class com.myfirstplugin.BlockyCore contained plaintext string literals in its constant pool: sqlUser set to 'root' and sqlPass set to the full database password. These had been written directly into the plugin's source code during development and were visible to anyone who ran strings or a Java decompiler against the file.
Strings and javap against BlockyCore.class both surfaced sqlUser=root and sqlPass=[REDACTED: recovered credential] directly from the bytecode constant pool.
Exact commands 4
Download the JAR to a local working directory.
mkdir -p /tmp/blocky && curl -sS -H 'Host: blocky.htb' -o /tmp/blocky/BlockyCore.jar http://$TARGET/plugins/files/BlockyCore.jar
Extract the compiled .class files from the archive.
cd /tmp/blocky && unzip -o BlockyCore.jar
Quick strings pass — immediately surfaces sqlUser and sqlPass literals.
strings /tmp/blocky/com/myfirstplugin/BlockyCore.class | grep -A2 -B2 sql
Bytecode disassembly for confirmation — shows constant-pool entries for both credential strings.
javap -classpath /tmp/blocky -c -p -v com.myfirstplugin.BlockyCore 2>/dev/null | grep -A1 'root\|sql\|Pass'
FixRemove hardcoded credentials from source code and build artifactsCritical
WeaknessDatabase credentials were embedded as plaintext string literals inside the BlockyCore plugin's Java source code. They shipped inside a publicly downloadable JAR file, where any visitor could extract them in seconds using only the standard 'strings' utility — no reverse-engineering skill required.
FixReplace all hardcoded secrets with references to environment variables, an OS-level secrets manager, or a configuration file stored outside the web root and excluded from version control (add to .gitignore). Rotate the exposed MySQL root password immediately and change every other account that shares it. Add a pre-commit secret-scanning hook (e.g., git-secrets, Gitleaks, or truffleHog) to catch credentials before they enter the repository. Audit existing repository history for previously committed secrets and purge them with git-filter-repo.
4Initial AccessCredential reuse / Valid Accounts (T1078)
Logged into the server over SSH using the reused MySQL password
The database root password recovered from the JAR had been reused as the Linux login password for the local account 'notch'. A standard SSH login with those credentials succeeded immediately, granting an interactive shell without any exploitation of a software vulnerability. This single step delivered the user flag.
SSH authenticated as uid=1000(notch), groups including sudo and lxd. /home/notch/user.txt was readable and yielded the user flag.
Exact commands 2
Interactive SSH — enter password [REDACTED: recovered credential] when prompted.
ssh notch@$TARGET
Non-interactive one-liner used in the engagement — confirms foothold and returns <user.txt>.
sshpass -p '[REDACTED: recovered credential]' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null notch@$TARGET 'id; cat /home/notch/user.txt'
FixEnforce unique passwords and disable SSH password authenticationCritical
WeaknessThe MySQL root password was identical to the Linux login password for the 'notch' account. A single leaked secret unlocked both the database and an interactive OS shell, collapsing two independent security boundaries into one.
FixMandate unique, randomly generated passwords for every service and account; use a password manager or secrets vault. Change the 'notch' account password immediately and audit all other accounts for reuse of the exposed value. Disable SSH password authentication entirely by setting 'PasswordAuthentication no' and 'ChallengeResponseAuthentication no' in /etc/ssh/sshd_config, then restart the SSH daemon. Require SSH key pairs for all remote access so that a leaked password alone cannot grant a shell.
5Local EnumerationSudo privilege enumeration
Confirmed notch holds unrestricted sudo rights
From the notch shell, checking sudo privileges revealed the entry '(ALL : ALL) ALL' — meaning notch can run any command as any user on the system using only the account password already in hand. No further research or exploitation was needed to plan the escalation.
Sudo -S -l returned '(ALL : ALL) ALL' for notch on Blocky with no restrictions.
Exact commands 1
Run from the notch shell — lists all sudo rights; confirm unrestricted ALL entry.
printf '%s\n' '[REDACTED: recovered credential]' | sudo -S -l
6Privilege EscalationSudo misconfiguration — unrestricted (ALL:ALL) ALL (T1548.003)
Escalated to root with a single sudo command
With unrestricted sudo and a known password, I ran 'sudo -i' to open a root shell. The same password notch uses to log in was accepted by sudo, so no additional credentials or exploits were required. This delivered the root flag and complete control over the server.
Sudo sh confirmed uid=0(root) on Blocky; /root/root.txt was readable and yielded the root flag.
Exact commands 3
Run from the notch shell — opens a root shell using password [REDACTED: recovered credential].
sudo -i
Read the root flag from the root shell — value is <root.txt>.
cat /root/root.txt
Non-interactive one-liner used in the engagement — confirms root and returns <root.txt>.
sshpass -p '[REDACTED: recovered credential]' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null notch@$TARGET "printf '%s\n' '[REDACTED: recovered credential]' | sudo -S sh -c 'id; cat /root/root.txt'"
FixRemove unrestricted sudo rights from the notch accountCritical
WeaknessThe 'notch' account had a sudoers entry of '(ALL : ALL) ALL', permitting any command as root with nothing more than the account's own password. This means that owning the notch account — through any means, including the credential reuse above — immediately means owning the entire server.
FixApply the principle of least privilege: grant sudo rights only for the specific binaries the account legitimately needs (e.g., '/usr/bin/systemctl restart myservice'). Edit /etc/sudoers via 'visudo' to replace the blanket ALL entry with a narrowly scoped command list, or remove the entry entirely if notch requires no elevated rights. Run 'sudo -l' against every account on the system to audit the full sudoers posture. Remove notch from the sudo group if no elevated access is needed ('deluser notch sudo').

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

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