# HAS\_SPN

## Summary

|                            |           |
| -------------------------- | --------- |
| **FSProtect ACL Alias**    | HAS\_SPN  |
| **Affected Object Types**  | Computers |
| **Exploitation Certainty** | Unlikely  |

## Description

The `HAS_SPN` attribute in Active Directory indicates that a machine’s Service Principal Name (SPN) attribute is populated with one or more SPNs. SPNs are unique identifiers that link a service instance to the service account under which it runs, playing a critical role in Kerberos authentication. When a machine has one or more SPNs registered, it signifies that the system is configured to offer Kerberos-based services. This allows clients to request service tickets that correctly identify and authenticate the service, ensuring that the proper service account is engaged during the authentication process.

## Identification

### PowerShell

#### Active Directory Module

Using the ActiveDirectory PowerShell module, you can enumerate HAS\_SPN entries.

Function: Find-HASSPN

```powershell
function Find-HASSPN {
    [CmdletBinding()]
    param ([string]$Target = $null,[string]$SearchBase = $null,[string]$OutputPath = "ServicePrincipalName.csv")
    Import-Module ActiveDirectory -ErrorAction Stop
    Write-Host "Gathering computer objects with 'ServicePrincipalName' property..."
    $adComputerParams = @{
        Filter      = "*"
        Properties  = "ServicePrincipalName"
        ErrorAction = "Stop"
    }
    if ($SearchBase) {
        $adComputerParams.Add("SearchBase", $SearchBase)
        Write-Host "Searching for computers within '$SearchBase'."
    } else {
        $adComputerParams.Add("SearchBase", (Get-ADRootDSE).DefaultNamingContext)
        Write-Host "Searching for all computers in the domain."
    }
    $computersToScan = @()
    $spnResults = @()
    try {
        if ($Target) {
            Write-Host "Searching for ServicePrincipalName on specific computer: '$Target'."
            $computersToScan += Get-ADComputer -Identity $Target -Properties "ServicePrincipalName" -ErrorAction Stop
        } else {
            $computersToScan = Get-ADComputer @adComputerParams
        }
    }
    catch {
        Write-Error "Failed to retrieve computer objects from Active Directory: $($_.Exception.Message)"
        return
    }
    if (-not $computersToScan) {
        Write-Output "No computer objects found to process."
        return
    }
    foreach ($computer in $computersToScan) {
        if ($computer.ServicePrincipalName) {
            foreach ($spn in $computer.ServicePrincipalName) {
                $spnResults += [PSCustomObject]@{
                    'Service'     = $spn
                    'Working on'  = $computer.Name
                }
            }
        }
    }
    if ($spnResults.Count -gt 0) {
        Write-Host "Found $($spnResults.Count) ServicePrincipalName entry(ies)."
        try {
            $spnResults | Sort-Object -Unique 'Service', 'Working on' | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 -ErrorAction Stop
            Write-Output "Results exported successfully to '$OutputPath'"
        }
        catch { Write-Error "Failed to export results to CSV file '$OutputPath': $($_.Exception.Message)"}
    } else { Write-Output "No computer objects found with 'ServicePrincipalName' property set."}
}
```

**1.** Scan all domain computers

```powershell
Find-HASSPN
```

**2.** Scan a specific object

```powershell
Find-HASSPN -Target "FSSQL"
```

**3.** Using SearchBase to limit the scope

```powershell
Find-HASSPN -SearchBase "OU=Workstations,DC=forestall,DC=labs"
```

#### Active Directory Users and Computers

**1.** Open Active Directory Users and Computers on your Windows server.

**2.** Right-click on the Computer.

**3.** Select Properties from the context menu.

**4.** In the Properties window, navigate to the Attribute Editor tab.

**5.** In the attribute editor's list, locate and check the option servicePrincipalName with double click.

**6.** Click OK to close the dialogs.

## Exploitation

No viable exploitation technique has been identified for this finding. The "Exploitation" section is included for completeness, but no method or proof-of-concept is currently available to exploit the issue.

## Mitigation

No specific mitigation can be applied to the `HAS_SPN` edge. Since this edge only represents the existence of a `Service Principal Name` and does not correspond to an exploitable path, no direct mitigation is required.

## Detection

Adding new Access Control Entries on Active Directory objects changes the `ntSecurityDescriptor` attribute of the objects themselves. These changes can be detected using Event IDs 5136 and 4662 to identify dangerous modifications.

| Event ID | Description                              | Fields/Attributes      | References                                                                                                                     |
| -------- | ---------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| 5136     | A directory service object was modified. | ntSecurityDescriptor   | <https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-5136>                                     |
| 4662     | An operation was performed on an object. | AccessList, AccessMask | <https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4662>                                     |
| 4742     | A computer account was changed.          | Subject, Account Name  | <https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4742> |

## References

* [What is Service Principal Names & Service Accounts - Payatu](https://payatu.com/blog/what-is-service-principal-names-service-accounts/)
* [MS-ADTS: Active Directory Technical Specification - Service Principal Names](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/cd328386-4d97-4666-be33-056545c1cad2)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forestall.io/fsprotect/edges/ad/has_spn.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
