Skip to content
Back to all posts

HTB: Blocky

· 12 min easy Linux Blocky

A custom Minecraft plugin with hardcoded database credentials leads to SSH access via credential reuse, and sudo group membership completes the chain to root.

Overview

Blocky is an Easy-rated Linux machine hosting a Minecraft community website built on WordPress 4.8. The box teaches a lesson that penetration testers encounter constantly in real engagements: custom application code is almost always a higher-value target than framework CVEs.

No WordPress vulnerability is exploited. Instead, a custom Minecraft plugin JAR file exposed via Apache directory listing contains hardcoded MySQL credentials in a public Java field. That password works for SSH as the notch user, who happens to be in the sudo group. Root follows in one command.

Reconnaissance

I start with a service scan:

nmap -sC -sV 10.129.13.88
PortServiceProduct / VersionNotes
21FTP(unknown)No banner grabbed
22SSHOpenSSH 7.2p2 Ubuntu 4ubuntu2.2Ubuntu 16.04
80HTTPApache httpd 2.4.18 (Ubuntu)Redirects to blocky.htb

After adding blocky.htb to /etc/hosts, the site loads: a WordPress 4.8 installation with the TwentySeventeen theme, titled “BlockyCraft: Under Construction!”. It is a Minecraft server community site.

Attack Surface Analysis

User enumeration

WordPress author enumeration via ?author=1 reveals the user notch (the Minecraft creator’s handle). This gives us a target username for credential testing.

Plugin discovery

A custom “Cute file browser” page at /plugins/ exposes /plugins/files/ with Apache directory listing enabled:

BlockyCore.jar              2017-07-02  883 bytes
griefprevention-1.11.2-3.1.1.298.jar  2017-07-02  520K

BlockyCore.jar is 883 bytes. That is tiny for a Java application; it is almost certainly a configuration class with minimal logic.

Vulnerability Analysis

The WordPress installation itself has no obvious vulnerabilities. WPScan would identify the version (4.8) and theme (TwentySeventeen), but the interesting attack surface is not the CMS; it is the custom plugin.

I download and decompile the JAR:

wget http://blocky.htb/plugins/files/BlockyCore.jar
jar tf BlockyCore.jar
# META-INF/MANIFEST.MF
# com/myfirstplugin/BlockyCore.class

javap -c -p com.myfirstplugin.BlockyCore
public class com.myfirstplugin.BlockyCore {
    public String sqlHost = "localhost";
    public String sqlUser = "root";
    public String sqlPass = "8YsqfCTnvxAUeduzjNSXe22";
}

Hardcoded MySQL credentials stored as public fields. No encryption, no configuration file indirection, no environment variable lookup. The onPlayerJoin() method has a TODO comment for username retrieval, confirming this is development-quality code deployed to production.

The vulnerability here is not technical complexity; it is operational carelessness. The same pattern appears in production codebases regularly: database credentials embedded directly in application source.

Exploitation

Credential reuse: SSH as notch

The MySQL root password works for SSH as notch:

ssh [email protected]
# Password: 8YsqfCTnvxAUeduzjNSXe22
id
# uid=1000(notch) gid=1000(notch) groups=1000(notch),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare)

The user flag is at /home/notch/user.txt. The group memberships are immediately revealing: sudo (gid=27) provides direct root access, lxd (gid=110) provides container escape, and adm (gid=4) provides log file access for credential harvesting. Three independent escalation paths from a single credential reuse finding.

Privilege escalation: sudo group

notch is a member of the sudo group (gid=27). Full root access:

sudo -i
# Password: 8YsqfCTnvxAUeduzjNSXe22

Root flag at /root/root.txt.

Alternative escalation paths exist but are unnecessary: lxd group membership (container escape) and adm group (log file access for credential harvesting).

Post-Exploitation

With root access, I enumerate the system to understand the full exposure:

uname -a
# Linux Blocky 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64

cat /etc/os-release | head -2
# NAME="Ubuntu"
# VERSION="16.04.2 LTS (Xenial Xerus)"

The WordPress database contains additional user hashes that could be cracked for credential reuse testing against other systems. The MySQL instance is accessible locally with the same root password. WordPress configuration at /var/www/html/wp-config.php confirms the database credentials match:

grep DB_PASSWORD /var/www/html/wp-config.php
# define('DB_PASSWORD', '8YsqfCTnvxAUeduzjNSXe22');

The lxd group membership is worth noting. LXD container escape provides an alternative root path that does not require knowing the user’s password. The technique involves importing an Alpine image, mounting the host filesystem into the container, and reading files as root from within. On this box it is unnecessary, but in engagements where sudo requires a different credential, the lxd group is an immediate escalation vector.

What a real attacker does next

In a production network, the post-exploitation checklist would include:

  • Credential harvesting: WordPress password hashes from the database, SSH keys in /home/*/.ssh/, any credentials in application config files
  • Network reconnaissance: arp -a, netstat -tlnp, internal DNS
  • Persistence: SSH key injection, cron job, WordPress admin backdoor
  • Pivot: Minecraft server communities often run multiple game servers; the credentials may grant access to additional hosts

Defensive Analysis

Detection opportunities

PhaseMITRE ATT&CKDetection
ReconnaissanceT1083Web server access logs showing requests to /plugins/files/
Credential accessT1552.001Static analysis: hardcoded credentials in committed JAR files
Lateral movementT1078.003SSH login with database credentials (credential reuse)
Priv escalationT1078.003sudo -i from a user account (audit sudo usage)

Build pipeline: A secrets scanner (truffleHog, gitleaks, Semgrep) in the CI/CD pipeline would flag the hardcoded password in the Java source before the JAR is ever deployed.

Web server: Apache directory listing on the plugins directory is the entry point. Disabling Options Indexes in the Apache configuration prevents directory browsing entirely.

Authentication: SSH login from an unexpected source IP with a database credential is suspicious. Correlating SSH auth logs with database access logs would identify credential reuse.

Remediation

PriorityActionEffortImpact
P0Rotate the MySQL root password and all reused credentialsLowCritical
P0Remove hardcoded credentials from BlockyCore.jar; use environment variables or a config file outside the webrootLowCritical
P1Disable Apache directory listing (Options -Indexes)LowHigh
P1Remove notch from the sudo group unless administrative access is genuinely requiredLowHigh
P2Add a secrets scanner to the build pipelineMediumMedium
P2Implement key-based SSH authentication; disable password authLowMedium
P3Remove notch from the lxd groupLowLow

The root cause is not a software vulnerability; it is an operational failure. Hardcoded credentials, password reuse across services, and overly permissive group membership are all configuration decisions, not bugs in third-party software.

Key Takeaways

  1. Custom code is higher value than framework CVEs. BlockyCore.jar (883 bytes of custom code) contained the entire attack chain. No WordPress vulnerability was needed. Always prioritise source code analysis over blind exploitation.

  2. Directory listings on plugin/upload paths are common misconfigurations. The /plugins/files/ directory had Apache autoindex enabled, exposing JAR files that were not linked from the application. A single Apache directive closes this gap.

  3. Credential reuse remains the most reliable lateral movement technique. Database credentials worked for SSH because the developer reused the same password across services. Unique, randomly generated credentials per service, stored in a secrets manager, would have stopped this chain entirely.

  4. Excessive group membership compounds the impact. The notch user was in sudo, lxd, and adm groups simultaneously. Even if one escalation path is blocked, two alternatives remain. User group membership should follow least-privilege: only grant group access that is operationally required.