AADInternals

Full documentation can be found below

Install AADInternals

To install AADInternals open an administrator powershell terminal and run the following command. Note: you may need to run "powershell -ep bypass" depending on your systems security settings.

PS> Install-Module AADInternals

Using AADInterals

Once we've installed AADInternals we can import it into our current powershell prompt.

> Import-Module AADInternals
    ___    ___    ____  ____      __                        __
   /   |  /   |  / __ \/  _/___  / /____  _________  ____ _/ /____
  / /| | / /| | / / / // // __ \/ __/ _ \/ ___/ __ \/ __ `/ / ___/
 / ___ |/ ___ |/ /_/ _/ // / / / /_/  __/ /  / / / / /_/ / (__  )
/_/  |_/_/  |_/_____/___/_/ /_/\__/\___/_/  /_/ /_/\__,_/_/____/

 v0.9.3 by @DrAzureAD (Nestori Syynimaa)

Outsider Recon

Get Tenant ID from Domain

Login information, including tenant ID

PS> Get-AADIntTenantID -Domain rotta.dev
f2a9b807-95f4-4a5f-9783-eaf2e0f18c7b

API: login.microsoftonline.com//.well-known/openid-configuration

Get All domains of the tenant

All domains of the tenant

PS> Get-AADIntTenantDomains -Domain rotta.dev
NETORGFT16900538.onmicrosoft.comrotta.dev

API: autodiscover-s.outlook.com/autodiscover/autodiscover.svc

Check if User Exists

PS> Invoke-AADIntUserEnumerationAsOutsider -UserName [email protected]

UserName                       Exists
--------                       ------
[email protected]   True

Check if User Exists (wordlist)

We can quickly check for users using a wordlist.

PS> Get-Content .\users.txt | Invoke-AADIntUserEnumerationAsOutsider -Method Normal

UserName                        Exists
--------                        ------
[email protected]    False
[email protected]  False
[email protected]    True
[email protected]      True
[email protected]   False
[email protected]...   True
[email protected]...  False

Invoke-AADIntReconAsOutsider

Starts tenant recon of the given domain. Gets all verified domains of the tenant and extracts information such as their type.

Also checks whether Desktop SSO (aka Seamless SSO) is enabled for the tenant.

PS> Invoke-AADIntReconAsOutsider -DomainName rottadev.onmicrosoft.com | Format-Table
Tenant brand:       Rotta
Tenant name:        rottadev.onmicrosoft.com                                                                            Tenant id:          4229582f-b81c-4623-b205-723775863d4f                                                                Tenant region:      NA                                                                                                  DesktopSSO enabled: False                                                                                                                                                                                                                       Name                      DNS   MX  SPF DMARC  DKIM MTA-STS Type    STS
----                      ---   --  --- -----  ---- ------- ----    ---
rottadev.onmicrosoft.com True True True False False   False Managed

Guest Recon

Authenticate as Guest

We can authenticate with a user and password using AADInternals. It will prompt for MFA.

PS> Get-AADIntAccessTokenForAzureCoreManagement -SaveToCache

List Tenants

PS> Get-AADIntAzureTenants

Id                                   Country Name  Domains
--                                   ------- ----  -------
4229582f-b81c-4623-b205-723775863d4f US      Rotta {rottadev.onmicrosoft.com}

Login to Tenant as Guest

Any user can authenticate to a tenant as guest if they have a valid microsoft account and the tenant ID. This will prompt for MFA

PS> Get-AADIntAccessTokenForAzureCoreManagement 
-Tenant 4229582f-b81c-4623-b205-723775863d4f -SaveToCache

Invoke Recon as Guest

PS> $results = Invoke-AADIntReconAsGuest

Tenant brand:                Rotta
Tenant name:                 rottadev.onmicrosoft.com
Tenant id:                   4229582f-b81c-4623-b205-723775863d4f
Azure AD objects:            213/50000
Domains:                      ( verified)
Non-admin users restricted?  False
Users can register apps?     True
Directory access restricted? False
Guest access:                Normal
CA policies:                 0
Access package admins:       0

List all domains

This displays all the domains, their authentication type, verification status, supported servers, and password validity period.

PS> $results.domains | Select-Object id,authen*,isverified,supported*,password* | Format-Table

id                       authenticationType isVerified supportedServices                   passwordValidityPeriodInDays passwordNotificationWindowInD
                                                                                                                                                  ays
--                       ------------------ ---------- -----------------                   ---------------------------- -----------------------------
rottadev.onmicrosoft.com Managed                  True {Email, OfficeCommunicationsOnline}                   2147483647                            14

Note: The password validity period of 2147483647 (0x7FFFFFFF) indicates that passwords do not expire.

List allowed actions

We can see rights the user has access to. (I authenticated as admin so everything).

PS> $results.allowedActions


administrativeunit              : {create, read, update, delete...}
application                     : {create, read, update, delete...}
approleassignment               : {create, read, update, delete...}
collaborationspace              : {create, read, update, delete...}
contact                         : {create, read, update, delete...}
contract                        : {create, read, update, delete...}

Enumerate Users

PS> $results = Invoke-AADIntUserEnumerationAsGuest -GroupMembers 
-Manager -Subordinates -Roles

Tenant brand: Rotta
Tenant name:  rottadev.onmicrosoft.com
Tenant id:    4229582f-b81c-4623-b205-723775863d4f
Logged in as: [email protected]
Users:        5
Groups:       2
Roles:        0

Enumerate Groups

Enumerate Membership rules

List some relevant information from the returned groups:

PS> $results.Groups | Select-Object displayName,id,membershiprule,description

displayName          id                                   membershipRule                                                             description                   
-----------          --                                   --------------                                                             -----------                   
All guests           b4c40137-6d42-4102-aa3b-023ba7d6e484 (user.userType -eq "Guest") or (user.userPrincipalName -match ".*#EXT#.*") All guests and externals users
Teams with externals b25791fc-7c20-4027-93d8-4a39a9ed186c   

Enumerate Members

List users within a group:

PS> $results.Groups | Select-Object displayName,id,members
displayName          id                                   members                                                                                                                                                              
-----------          --                                   -------                                                                                                                                                              
All guests           b4c40137-6d42-4102-aa3b-023ba7d6e484 {user_gmail.com#EXT#@Mcompany.onmicrosoft.com, user_outlook.com#EXT#@company.onmicrosoft.com, ...}
Teams with externals b25791fc-7c20-4027-93d8-4a39a9ed186c {[email protected], [email protected], user_outlook.com#EXT#@Mcompany.onmicrosoft.com} 

Note: Many organizations have created a dynamic group to contain all guest and/or extrernal users. Usually this is used to assign conditional access rules etc. to these users. However, the group will contain all guests of the organization, including business partners, clients, etc. And yes, guest users can list the members of any group!

Enumerating members is massive for us. We can use the information to conduct phishing campaigns and brute forcing.

Group Member Enumeration

The following will extract all users from all the groups the given user is member of:

PS> $results = Invoke-AADIntUserEnumerationAsGuest -UserName "[email protected]" -GroupMembers 
-Manager -Subordinates -Roles

Tenant brand: Company Ltd
Tenant name:  company.onmicrosoft.com
Tenant id:    6e3846ee-e8ca-4609-a3ab-f405cfbd02cd
Logged in as: live.com#[email protected]
Users:        32
Groups:       4
Roles:        3

List Group Information

PS> $results.Groups | Select-Object displayName,id,membershiprule,description

displayName          id                                   membershipRule               description                                                                                     
-----------          --                                   --------------               -----------                                                                                     
Secret stuff teams   740f43a5-c7f8-4a1a-a6b8-2d57a1f6cda6                              This teams is meant for internal secret stuff! Mostly sensitive discussions with M&A candidates.
Teams with externals b25791fc-7c20-4027-93d8-4a39a9ed186c                              Teams with externals                                                                            
abc                  9202b94b-5381-4270-a3cb-7fcf0d40fef1                              abc                                                                                             
All company          2ce444bc-6112-4429-922c-dbf6be59a6c3 (user.userType -eq "Member") All company users 

List Role Information

PS> $results.Roles | Select-Object id,members

id                                   members                                                                                                                                   
--                                   -------                                                                                                                                   
8b517a6e-d13e-4e97-a2c0-278ae38d46a6 {[email protected]}                                                                                                         
294cdfc8-abb4-419f-bdbb-c5d616644f9a {[email protected]}
028e7f7b-c99a-41bb-9d5c-2d22457b5549 {[email protected], [email protected]}     

Insider Recon

Authenticate as Insider

We can authenticate with a username and password

PS> Get-AADIntAccessTokenForAzureCoreManagement -SaveToCache

Invoke Insider Recon

PS> $results = Invoke-AADIntReconAsInsider

Tenant brand:                Rotta
Tenant name:                 rottadev.onmicrosoft.com
Tenant id:                   4229582f-b81c-4623-b205-723775863d4f
Tenant SKU:
Azure AD objects:            213/50000
Domains:                      ( verified)
Non-admin users restricted?  False
Users can register apps?     True
Directory access restricted? False
Directory sync enabled?      false
Global admins:               2
CA policies:                 0
MS Partner IDs:
MS Partner DAP enabled?      False
MS Partner contracts:        0
MS Partners:                 0

User Enumeration

PS> $results = Invoke-AADIntUserEnumerationAsInsider -Groups
Users:        4
Groups:       3

List Users

PS> $results.Users


id                              : be7cc3bb-fe07-401d-aa27-50420392b009
displayName                     : alice
userPrincipalName               : [email protected]
userType                        : Member
onPremisesImmutableId           :
onPremisesLastSyncDateTime      :
onPremisesSamAccountName        :
onPremisesSecurityIdentifier    :
onPremisesDistinguishedName     :
refreshTokensValidFromDateTime  : 2024-07-09T19:00:53Z
signInSessionsValidFromDateTime : 2024-07-09T19:00:53Z
proxyAddresses                  : {}
businessPhones                  : {}
identities                      : {@{signInType=userPrincipalName; issuer=rottadev.onmicrosoft.com; [email protected]}}

id                              : fdbd3d73-b316-4bd0-ab55-d5ef650e53da
displayName                     : bob
userPrincipalName               : [email protected]
userType                        : Member
onPremisesImmutableId           :
onPremisesLastSyncDateTime      :
onPremisesSamAccountName        :
...

Note: We can list one by $results.Users[x]

Global Admin Recon

Authenticate as Global Admin

# Get an access token and save it to the cache
Get-AADIntAccessTokenForAzureCoreManagement -SaveToCache

# Grant Azure User Access Administrator role 
Grant-AADIntAzureUserAccessAdminRole

# Update the access token after elevation and save to cache
Get-AADIntAccessTokenForAzureCoreManagement -SaveToCache

List Subscriptions of current Tenant

PS> Get-AADIntAzureSubscriptions

subscriptionId                       displayName          state
--------------                       -----------          -----
f14038db-c8d7-48df-8d66-adf35489efc4 Azure subscription 1 Enabled

Last updated