If you’re a penetration tester, then you probably already know that escalating from a local administrator to a Domain Admin only requires a few steps. Those steps typically involve stealing Domain Admin passwords, password hashes, or authentication tokens via various methods. However, if you aren’t lucky enough to have a Domain Admin logged into the system you just compromised, then you’ll have to go looking for one that does. A while back I wrote a short blog called “5 Ways to Find Systems Running Domain Admin Processes” that outlines a few common approaches, but recently I found another one. So in this blog I’ll cover how to find systems where Domain Admins are likely to be logged in by querying the “ServicePrincipleName” attribute of accounts in LDAP. I’ve also written a little PowerShell module to automate the process. Hopefully it will be useful to penetration testers and admins interested in knowing where their domain accounts are running services on the domain.
LDAP Overview
For those who are not familiar with the Lightwieght Directory Access Protocol (LDAP), it is exactly what it sounds like – a directory of information. Although LDAP is used across many platforms, in Windows domain environments it lives at the heart of Active Directory Services (ADS). ADS performs authentication and authorization for Windows Domains, but also houses a ton of information. That information includes, but is not limited to domain accounts, computer accounts, domain groups, security policies, and software updates. Each object has multiple attributes associated with it, and almost all of them can be queried via LDAP. For example, every user account has a “Created” attribute that indicates when the account was created. Similarly every account has a “ServicePrincipleName” attribute which will be the focus of the rest of this blog.
ServicePrincipleName Overview
Microsoft’s documentation states, “A service principal name (SPN) is the name by which a client uniquely identifies an instance of a service.” Based some light reading it sounds like the official use is to facilitate Kerberos authentication on Windows domains. However, we are going to use it for something else. For our purposes, the multi-value ServicePrincpleName attribute is handy, because each user and computer object in Active Directory stores all of the services that the account runs on the domain. So it’s it easy to locate common servers like IIS, SQL Server, and LDAP. It’s also handy because it can tell us where accounts are configured to be running or logged in (like Domain Admins). This is relatively easy, because SPNs have a standardized naming convention. SPNs are usually formatted as SERVICE/HOST, but sometimes they also include a port like SERVICE/HOST:PORT.
For example, if a domain account was used to run DNS and SQL Server services on the acme.com domain then the SPN entries would look something like the following:
Querying LDAP for basic SPN information is pretty straight forward. For example, adfind.exe (www.joeware.net) can be used to list all of the SQL Server instances registered on a domain with the following command as an authenticated user:
Also, the “setspn.exe” tool that comes with Windows Server 2008 can be used to quickly lookup the SPNs for a specific account.
C: >setspn.exe –l user1
I’ve found during penetration tests that most enterprise environments have Domain Admins accounts that are used to run services on the domain. As result, it is possible to simply query LDAP for all of the Domain Admins and review their SPN entries for servers where they are likely to be logged in during escalation. No shell spraying required. However, adfind and setspn lack default options to quickly run SPN queries against groups so I wrote a little PowerShell module called “Get-SPN” to help make my life easier.
Get-SPN PowerShell Module
The Get-SPN PowerShell module provides an easy way to quickly search LDAP for accounts that match a specific user, group, or SPN service name. For those who are interested it can be downloaded from my Github account here. Please note that it does require PowerShell v3. The module can be installed manually by downloading the Get-SPN.psm1 file to one of two locations:
It can then be imported with the following command:
Import-Module .Get-SPN.psm1
After it’s installed for your current session you should be good to go. Below are a few examples from my small test environment to help get you started. More examples can be found in the help for the command.
Get-Help Get-SPN -full
Find All Servers where Domain Admins are Registered to Run Services
If you are executing the command as domain user or LocalSystem from a domain computer then you can use the command below:
The command can also be run without the “-list” options for more verbose output. For example:
Get-SPN -type group -search "Domain Admins"
If you are executing from a non domain system with domain credentials you can use the command below. The “DomainController” and “Credential” options can be used with any of the Get-SPN queries.
Finding All ServicePrincipalName Entries for Domain Users Matching String
If you are executing the command as domain user or LocalSystem from a domain computer then you can use the command below:
Get-SPN -type user -search "*svc*" -List yes
Wrap Up
At this point there are a few limitations I should call out if you are planning to use SPNs to locate systems where Domain Admin accounts are logged on:
Not all Domain Admin accounts will be used to run services.
SPNs are automatically registered when an application is installed, but in most cases if the account is changed after the initial installation then it will not be reflected in the SPN unless manually added.
As a result, most of the time SPNs are very useful for finding Domain Admins, but in some environments they are relatively useless. Regardless, leveraging them to find Domain Admin systems means that you don’t have to perform scanning or shell spraying over the network. This is nice in the end, because it helps reduce the attack fingerprint and detection during penetration tests. Finally, don’t forget that ServicePrincpleNames can be used to locate high value data targets such as SQL Servers, Web Servers, etc on the domain. Good hunting. Have fun and hack responsibly. 🙂
Necessary cookies help make a website usable by enabling basic functions like page navigation and access to secure areas of the website. The website cannot function properly without these cookies.
Name
Domain
Purpose
Expiry
Type
YSC
youtube.com
YouTube session cookie.
52 years
HTTP
Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user and thereby more valuable for publishers and third party advertisers.
Name
Domain
Purpose
Expiry
Type
VISITOR_INFO1_LIVE
youtube.com
YouTube cookie.
6 months
HTTP
Analytics cookies help website owners to understand how visitors interact with websites by collecting and reporting information anonymously.
We do not use cookies of this type.
Preference cookies enable a website to remember information that changes the way the website behaves or looks, like your preferred language or the region that you are in.
We do not use cookies of this type.
Unclassified cookies are cookies that we are in the process of classifying, together with the providers of individual cookies.
We do not use cookies of this type.
Cookies are small text files that can be used by websites to make a user's experience more efficient. The law states that we can store cookies on your device if they are strictly necessary for the operation of this site. For all other types of cookies we need your permission. This site uses different types of cookies. Some cookies are placed by third party services that appear on our pages.
Cookie Settings
Discover why security operations teams choose NetSPI.