Skip to content

Commit

Permalink
Merge pull request #171 from T0pCyber/bugfix/162-modernize-authentica…
Browse files Browse the repository at this point in the history
…tion-to-replace-azuread-with-microsoft-graph

Bugfix/162 modernize authentication to replace azuread with microsoft graph
  • Loading branch information
T0pCyber authored Dec 8, 2024
2 parents 51cc62a + 842dd4e commit d263b55
Show file tree
Hide file tree
Showing 21 changed files with 652 additions and 643 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
branches:
- master
- Development
- bugfix/157-bug-multiple-failed-tests-after-fixing-workflow
- bugfix/162-modernize-authentication-to-replace-azuread-with-microsoft-graph

jobs:
validate:
Expand Down
15 changes: 7 additions & 8 deletions Hawk/Hawk.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
RootModule = 'Hawk.psm1'

# Version number of this module.
ModuleVersion = '3.1.1'
ModuleVersion = '3.1.2'

# ID used to uniquely identify this module
GUID = '1f6b6b91-79c4-4edf-83a1-66d2dc8c3d85'
Expand Down Expand Up @@ -31,9 +31,8 @@
@{ModuleName = 'PSFramework'; ModuleVersion = '1.12.346' },
@{ModuleName = 'PSAppInsights'; ModuleVersion = '0.9.6' },
@{ModuleName = 'ExchangeOnlineManagement'; ModuleVersion = '3.0.0' },
@{ModuleName = 'AzureAD'; ModuleVersion = '2.0.2.182' },
@{ModuleName = 'Microsoft.Graph.Authentication'; ModuleVersion = '1.23.0' },
@{ModuleName = 'Microsoft.Graph.Identity.DirectoryManagement'; ModuleVersion = '1.23.0' }
@{ModuleName = 'Microsoft.Graph.Authentication'; ModuleVersion = '2.25.0' },
@{ModuleName = 'Microsoft.Graph.Identity.DirectoryManagement'; ModuleVersion = '2.25.0' }
)

# Assemblies that must be loaded prior to importing this module
Expand All @@ -50,7 +49,7 @@
'Get-HawkTenantConfiguration',
'Get-HawkTenantEDiscoveryConfiguration',
'Get-HawkTenantInboxRules',
'Get-HawkTenantConsentGrants',
'Get-HawkTenantConsentGrant',
'Get-HawkTenantRBACChanges',
'Get-HawkTenantAzureAppAuditLog',
'Get-HawkUserAuthHistory',
Expand All @@ -73,11 +72,11 @@
'Get-HawkUserAutoReply',
'Get-HawkUserMessageTrace',
'Get-HawkUserMobileDevice',
'Get-HawkTenantAZAdmins',
'Get-HawkTenantAZAdmin',
'Get-HawkTenantEXOAdmins',
'Get-HawkTenantMailItemsAccessed',
'Get-HawkTenantAppAndSPNCredentialDetails',
'Get-HawkTenantAzureADUsers',
'Get-HawkTenantAppAndSPNCredentialDetail',
'Get-HawkTenantEntraIDUser',
'Get-HawkTenantDomainActivity',
'Get-HawkTenantEDiscoveryLog'

Expand Down
90 changes: 90 additions & 0 deletions Hawk/functions/Tenant/Get-HawkTenantAZAdmin.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
Function Get-HawkTenantAZAdmin {
<#
.SYNOPSIS
Tenant Azure Active Directory Administrator export using Microsoft Graph.
.DESCRIPTION
Tenant Azure Active Directory Administrator export. Reviewing administrator access is key to knowing who can make changes
to the tenant and conduct other administrative actions to users and applications.
.EXAMPLE
Get-HawkTenantAZAdmin
Gets all Azure AD Admins
.OUTPUTS
AzureADAdministrators.csv
.LINK
https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.identity.directorymanagement/get-mgdirectoryrole
.NOTES
Requires Microsoft.Graph.Identity.DirectoryManagement module
#>
[CmdletBinding()]
param()

BEGIN {
# Initializing Hawk Object if not present
if ([string]::IsNullOrEmpty($Hawk.FilePath)) {
Initialize-HawkGlobalObject
}
Out-LogFile "Gathering Azure AD Administrators"

Test-GraphConnection
}

PROCESS {
try {
# Get all directory roles
$directoryRoles = Get-MgDirectoryRole -ErrorAction Stop
Out-LogFile "Retrieved $(($directoryRoles | Measure-Object).Count) directory roles"

$roles = foreach ($role in $directoryRoles) {
# Get members for each role
$members = Get-MgDirectoryRoleMember -DirectoryRoleId $role.Id -ErrorAction Stop

if (-not $members) {
[PSCustomObject]@{
AdminGroupName = $role.DisplayName
Members = "No Members"
MemberType = "None" # Added member type for better analysis
MemberId = $null
}
}
else {
foreach ($member in $members) {
# Determine member type and get appropriate properties
if ($member.AdditionalProperties.'@odata.type' -eq "#microsoft.graph.user") {
[PSCustomObject]@{
AdminGroupName = $role.DisplayName
Members = $member.AdditionalProperties.userPrincipalName
MemberType = "User"
MemberId = $member.Id
}
}
else {
# Groups or Service Principals
[PSCustomObject]@{
AdminGroupName = $role.DisplayName
Members = $member.AdditionalProperties.displayName
MemberType = ($member.AdditionalProperties.'@odata.type' -replace '#microsoft.graph.', '')
MemberId = $member.Id
}
}
}
}
}

if ($roles) {
$roles | Out-MultipleFileType -FilePrefix "AzureADAdministrators" -csv -json
Out-LogFile "Successfully exported Azure AD Administrators data"
}
else {
Out-LogFile "No administrator roles found or accessible" -notice
}
}
catch {
Out-LogFile "Error retrieving Azure AD Administrators: $($_.Exception.Message)" -notice
Write-Error -ErrorRecord $_ -ErrorAction Continue
}
}

END {
Out-LogFile "Completed exporting Azure AD Admins"
}
}
56 changes: 0 additions & 56 deletions Hawk/functions/Tenant/Get-HawkTenantAZAdmins.ps1

This file was deleted.

150 changes: 150 additions & 0 deletions Hawk/functions/Tenant/Get-HawkTenantAppAndSPNCredentialDetail.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
Function Get-HawkTenantAppAndSPNCredentialDetail {
<#
.SYNOPSIS
Tenant Azure Active Directory Applications and Service Principal Credential details export using Microsoft Graph.
.DESCRIPTION
Tenant Azure Active Directory Applications and Service Principal Credential details export. Credential details can be used to
review when credentials were created for an Application or Service Principal. If a malicious user created a certificate or password
used to access corporate data, then knowing the key creation time will be instrumental to determining the time frame of when an attacker
had access to data.
.EXAMPLE
Get-HawkTenantAppAndSPNCredentialDetail
Gets all Tenant Application and Service Principal Details
.OUTPUTS
SPNCertsAndSecrets.csv
ApplicationCertsAndSecrets
.LINK
https://learn.microsoft.com/en-us/graph/api/serviceprincipal-list
https://learn.microsoft.com/en-us/graph/api/application-list
.NOTES
Updated to use Microsoft Graph API instead of AzureAD module
#>
[CmdletBinding()]
param()

BEGIN {
if ([string]::IsNullOrEmpty($Hawk.FilePath)) {
Initialize-HawkGlobalObject
}

# Create Tenant folder path if it doesn't exist
$tenantPath = Join-Path -Path $Hawk.FilePath -ChildPath "Tenant"
if (-not (Test-Path -Path $tenantPath)) {
New-Item -Path $tenantPath -ItemType Directory -Force | Out-Null
}

Test-GraphConnection
Send-AIEvent -Event "CmdRun"

# Initialize arrays to collect all results
$spnResults = @()
$appResults = @()

Out-LogFile "Collecting Azure AD Service Principals"
try {
$spns = Get-MgServicePrincipal -All | Sort-Object -Property DisplayName
Out-LogFile "Collecting Azure AD Registered Applications"
$apps = Get-MgApplication -All | Sort-Object -Property DisplayName
}
catch {
Out-LogFile "Error retrieving Service Principals or Applications: $($_.Exception.Message)" -Notice
Write-Error -ErrorRecord $_ -ErrorAction Continue
}
}

PROCESS {
try {
Out-LogFile "Exporting Service Principal Certificate and Password details"
foreach ($spn in $spns) {
# Process key credentials
foreach ($key in $spn.KeyCredentials) {
$newapp = [PSCustomObject]@{
AppName = $spn.DisplayName
AppObjectID = $spn.Id
KeyID = $key.KeyId
StartDate = $key.StartDateTime
EndDate = $key.EndDateTime
KeyType = $key.Type
CredType = "X509Certificate"
}
# Add to array for JSON output
$spnResults += $newapp
# Output individual record to CSV
$newapp | Out-MultipleFileType -FilePrefix "SPNCertsAndSecrets" -csv -append
}

# Process password credentials
foreach ($pass in $spn.PasswordCredentials) {
$newapp = [PSCustomObject]@{
AppName = $spn.DisplayName
AppObjectID = $spn.Id
KeyID = $pass.KeyId
StartDate = $pass.StartDateTime
EndDate = $pass.EndDateTime
KeyType = $null
CredType = "PasswordSecret"
}
# Add to array for JSON output
$spnResults += $newapp
# Output individual record to CSV
$newapp | Out-MultipleFileType -FilePrefix "SPNCertsAndSecrets" -csv -append
}
}

# Output complete SPN results array as single JSON
if ($spnResults.Count -gt 0) {
$spnResults | ConvertTo-Json | Out-File -FilePath (Join-Path -Path $tenantPath -ChildPath "SPNCertsAndSecrets.json")
}

Out-LogFile "Exporting Registered Applications Certificate and Password details"
foreach ($app in $apps) {
# Process key credentials
foreach ($key in $app.KeyCredentials) {
$newapp = [PSCustomObject]@{
AppName = $app.DisplayName
AppObjectID = $app.Id
KeyID = $key.KeyId
StartDate = $key.StartDateTime
EndDate = $key.EndDateTime
KeyType = $key.Type
CredType = "X509Certificate"
}
# Add to array for JSON output
$appResults += $newapp
# Output individual record to CSV
$newapp | Out-MultipleFileType -FilePrefix "ApplicationCertsAndSecrets" -csv -append
}

# Process password credentials
foreach ($pass in $app.PasswordCredentials) {
$newapp = [PSCustomObject]@{
AppName = $app.DisplayName
AppObjectID = $app.Id
KeyID = $pass.KeyId
StartDate = $pass.StartDateTime
EndDate = $pass.EndDateTime
KeyType = $pass.Type
CredType = "PasswordSecret"
}
# Add to array for JSON output
$appResults += $newapp
# Output individual record to CSV
$newapp | Out-MultipleFileType -FilePrefix "ApplicationCertsAndSecrets" -csv -append
}
}

# Output complete application results array as single JSON
if ($appResults.Count -gt 0) {
$appResults | ConvertTo-Json | Out-File -FilePath (Join-Path -Path $tenantPath -ChildPath "ApplicationCertsAndSecrets.json")
}
}
catch {
Out-LogFile "Error processing credentials: $($_.Exception.Message)" -Notice
Write-Error -ErrorRecord $_ -ErrorAction Continue
}
}

END {
Out-Logfile "Completed exporting Azure AD Service Principal and App Registration Certificate and Password Details"
}
}
Loading

0 comments on commit d263b55

Please sign in to comment.