Bei Microsoft ist im Laufe der letzten Woche eine weitere Sicherheitslücke bekannt geworden. Es war Benutzern und, unter bestimmten Voraussetzungen, auch organisationsfremden Benutzern (Gäste) möglich, ihren sogenannten „User Principal Name (UPN)“ zu ändern. Der UPN ist das primäre Anmeldeattribut, an dem in der Microsoft-Welt die Identität festgestellt wird.
Auch der Bypass von Intune Compliant Device Kontrollen ist noch aktuell
⚠️ Bei Hybriden Benutzern, die aus dem Active Directory synchronisiert werden, wurden Änderungen wieder überschrieben, dies eröffnete jedoch ein Zeitfenster für potenziellen Missbrauch. ⚠️
Im Admin Center konnte ein User auf seinem eigenen Profil den Präfix (Max.Mustermann@…) und die Domain (…@Firma.de) anpassen, und so auch weitere gültige Emailadressen für sich erstellen. Diese Änderung konnte auch über die API vorgenommen werden.
Normalerweise wird zwar das Feld als editierbar gezeigt, es folgt aber beim speichern eine Fehlermeldung:
Seit mindestens dem 22. Januar 2025 blieb die Fehlermeldung aus. Der Fehler wurde am 24. Januar 2025 im Laufe des Nachmittags behoben. Bis heute hat Microsoft nicht mitgeteilt, seit wann genau das Problem bestand (Stand 29. Januar 2025).
In Entra ID gibt es verschiedene Möglichkeiten, Gäste zu verwalten. Standardmäßig ist ihr Zugriff eingeschränkt. Wenn Gästen jedoch die gleichen Rechte wie regulären Benutzern eingeräumt werden (was ich ausdrücklich nicht empfehle!), umfasste dies auch das Recht, den eigenen UPN zu ändern.
Mir sind folgende Szenarien offensichtlich, es gibt aber sicherlich weitere Möglichkeiten die Änderung des UPNs auszunutzen.
Die Änderung des UPN führt zur Anpassung der Email- und Chatadresse. Nutzer könnten so ihre Identität verschleiern (z. B. „Geschäftsführer@…“), da der Anzeigename in der Office-Kontaktkarte organisationsübergreifend oft nicht sichtbar ist. Alte UPNs bleiben mit dem Postfach verknüpft, wodurch ungenutzte Adressen (z. B. „Betriebsrat@…“) missbraucht werden könnten, um Emails abzufangen. Gäste könnten sich durch UPN-Änderung zudem als interne Mitarbeiter ausgeben.
Automatische Gruppenregeln basieren oft auf Emailadressen. So könnten Angreifer über Änderungen des UPN unberechtigten Zugriff auf organisationsweite Teams oder Dateien erhalten. Auch Namenskonventionen, die für Sicherheitsmechanismen wie Conditional Access genutzt werden, könnten durch findige Administratoren umgangen werden.
Tipp: Für Administratoren sollten explizite Zuweisungen und geschützte Attribute genutzt werden.
Obwohl aktive UPNs in Entra eindeutig sind, könnten Konten ausgeschiedener Benutzer in Drittanbieterapplikationen weiterverwendet werden. Da Benutzer dort oft nicht gelöscht werden, könnte umfangreicher Zugriff auf Systeme wie HR-Software oder Finanzbuchhaltung erlangt werden.
Wir haben etabliert, dass es wichtig ist, ein Auge auf alle vorgenommenen Änderungen zu werfen – aber wie finden wir in einem unbekannten Zeitraum problematische UPNs?
Microsoft hat angekündigt, im Falle von Missbrauch die Administratoren betroffener Tenants zu kontaktieren. Da jedoch weder der Zeitpunkt noch die Details dieses Kontakts bekannt sind, ist es sinnvoll, eigenständig (soweit möglich) nach potenzieller Ausnutzung dieses Verhaltens zu suchen.
Vorab ist wichtig zu wissen: Ohne eine Entra ID Premium-Lizenz werden Audit Logs nur 7 Tage lang gespeichert. Wenn diese Logs nicht in einen Log Analytics Workspace oder ein anderes Archiv weitergeleitet werden, ist es sehr unwahrscheinlich, dass Sie eigenständig Missbrauch identifizieren können.
Nachträgliches Hinzufügen von im folgenden gelisteten Speicherlösungen bringt keine verlorenen Daten zurück – was weg ist, bleibt weg.
Die einfachste Möglichkeit, auf die Audit Logs zuzugreifen ist über das Entra admin center. Es reicht Berechtigung als Global Reader oder Report Reader.
Mit Entra Premium-Lizenzen, wie sie Teil der Enterprise-Lizenzen sind, werden Änderungen für 30 Tage aufbewahrt.
Zwar kann im Portal nach Benutzeränderungen gefiltert werden (Activity = „Update User“), jedoch bleibt die Ansicht schon in mittelgroßen Tenants unübersichtlich.
Es ist daher sinnvoller, die Ergebnisse zu exportieren und anschließend per Skript zu analysieren. Hier ein Beispielskript, das eine CSV-Datei des Audit Logs einliest und nach verdächtigen Änderungen filtert:
param ( [parameter(Mandatory = $false)] [string]$auditCSVPath ) # If Path not provided or not found, prompt user to select the Audit Log Export if (-not $(Test-Path "$auditCSVPath") ) { Add-Type -AssemblyName System.Windows.Forms $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = [Environment]::GetFolderPath('Desktop') Filter = 'CSV Export (*.csv)|*.csv' } $null = $FileBrowser.ShowDialog() $auditCSVPath = $FileBrowser.FileName } $auditlogImport = import-csv $auditCSVPath if ($auditlogImport.Count -eq 250000) { Write-Warning "Please specify a (more restrictive) filter in the GUI or use the API, you have reached the maximum number of records" } # Filter relevant entries $selfEdits = $auditlogImport | Where-Object {$_.Activity -eq "Update user" -and $_.Target1ObjectId -eq $_.ActorObjectId} $suspiciousEdits = $selfEdits | Where-Object {$($_ | ConvertTo-Json) -match '"UserPrincipalName",' } if (-not $suspiciousEdits){ Write-Output "No suspicious changes found"; break } $Report = [System.Collections.Generic.List[Object]]::new() forEach ($item in $suspiciousEdits) { $obj = [PSCustomObject][ordered]@{ "Timestamp" = "$(get-date ($item.'Date (UTC)') -Format 'dd-MMM-yyyy HH:mm')" "User GUID" = $item.Target1ObjectId "Old UPN" = $item.ActorUserPrincipalName "New UPN" = $item.Target1UserPrincipalName } $report.Add($obj) } $Report | Out-gridview -Title "Please verify, carefully, these UPN changes"
Wenn man über erweiterte Rechte verfügt, empfiehlt es sich, eine Enterprise App einzurichten und direkt die Graph API für den Abruf der Audit Logs zu verwenden. Für die erstmalige Einrichtung ist jedoch das Recht „Privileged Authentication Administrator“ erforderlich.
Connect-MgGraph -Scope "AuditLog.Read.All, Directory.Read.All" -NoWelcome $filter = "activityDateTime le 2025-01-25 and activityDisplayName eq 'Update user'" $auditLogs = Invoke-MgGraphRequest GET "https://graph.microsoft.com/v1.0/auditLogs/directoryaudits?`$filter=$filter" -OutputType PSObject # Identify UPN Changes initiated by the user himself $upnchanges = $auditlogs.value | Where-Object {$_.targetresources.modifiedproperties.displayname -eq "Userprincipalname"} $suspiciousEdits = $upnchanges | Where-Object {$_.Initiatedby.user.id -eq $_.targetresources.id} if (-not $suspiciousEdits){ Write-Output "No suspicious changes found"; break } # Create and show report $Report = [System.Collections.Generic.List[Object]]::new() forEach ($item in $suspiciousEdits) { $modifiedProperty = $item.targetresources.modifiedproperties | Where-Object {$_.displayname -eq "Userprincipalname"} $obj = [PSCustomObject][ordered]@{ "Timestamp" = "$(get-date ($item.activityDateTime) -Format 'dd-MMM-yyyy HH:mm')" "User GUID" = $item.Initiatedby.user.id "Old UPN" = $modifiedProperty.oldValue "New UPN" = $modifiedProperty.newValue } $report.Add($obj) } $Report | Out-gridview -Title "Please verify, carefully, these UPN changes"
Wenn ein Export des Audit Logs in einen Azure Log Analytics Workspace eingerichtet wurde, profitieren Sie von einer potenziell erheblich längeren Aufbewahrungsperiode und effizienteren Suchmöglichkeiten.
Es muss nur die Logsuche geöffnet werden und dieses KQL genutzt werden um Fälle zu Zeigen wo ein Benutzer sein eigenen UPN geändert hat:
AuditLogs | where TimeGenerated between (datetime(2024-06-01) .. datetime(2025-01-25) ) | where OperationName == "Update user" //Filter common Service Identities to reduce costly parsing | where not(Identity in ("Azure MFA StrongAuthenticationService", "Microsoft Substrate Management", "Azure Credential Configuration Endpoint Service", "Microsoft password reset service", "Microsoft Online Services", "Office 365 SharePoint Online")) | extend Target = parse_json(TargetResources)[0] // Check whether the UPN was changed before we expand | where Target.modifiedProperties has "UserPrincipalName" | mv-expand Target.modifiedProperties | where tostring(Target_modifiedProperties.displayName) == "UserPrincipalName" // Add the Initiator to check whether the user changed himself | extend Initiatior = parse_json(InitiatedBy) | where tostring(Initiatior.user.id) == tostring(Target.id) | extend newValue = tostring(Target_modifiedProperties.newValue) | extend oldValue = tostring(Target_modifiedProperties.oldValue) | where newValue != oldValue | project TimeGenerated, User_GUID = Target.id, newValue, oldValue
Einfach so möchte ich hier Julian Rasmussen erwähnen.
Sollte sich herausstellen, dass die Sicherheitslücke länger als 30 Tage bestand oder Sie erst spät darauf aufmerksam wurden, gibt es eine Alternative – selbst wenn kein Log Analytics Workspace eingerichtet wurde.
Das Purview Audit Log (Auch: Exchange Unified Audit Log) speichert Compliance-Daten für:
Dieses Feature ist standardmäßig aktiviert, erfordert jedoch spezielle Rechte:
Mit diesen Voraussetzungen kann das Unified Audit Log mithilfe des folgenden PowerShell-Skripts durchsucht werden:
Inspiriert von https://practical365.com/audit-log-query-api/
#Requires -modules Microsoft.Graph.Authentication # If you have a longer retention you may specify it (Default: 180 days) param ( [parameter(Mandatory = $false)] [int]$logRetentionDays = 180 ) Connect-MgGraph -scope "AuditLogsQuery-Entra.Read.All" -NoWelcome # Function to Handle Graph Pagination function Get-GraphData { param ( [Parameter(Mandatory = $true)] [string]$Uri, [hashtable]$headers = @{}, [System.Collections.Arraylist]$result ) $response = Invoke-MgGraphRequest -Method GET -Uri $Uri -Headers $headers -OutputType PSObject $result.AddRange($response.value) if ($response.'@odata.nextLink') { Get-GraphData -Uri $response.'@odata.nextLink' -headers $headers -result $result } } Write-Output "Creating query..." $SearchName = ("UPNChange_$(Get-Date -format 'dd-MMM-yyyy HH:mm')") # Subtract retention period, if out of available range API throws an error [String]$StartDate = (Get-Date).AddDays(-$logRetentionDays).Tostring("yyyy-MM-ddT00:00:00Z") # End on date the issue was fixed [String]$EndDate = "2025-01-25T00:00:00Z" $SearchParameters = @{ displayName = "$SearchName" filterStartDateTime = "$StartDate" filterEndDateTime = "$EndDate" serviceFilter = "AzureActiveDirectory" operationFilters = @("Update user.") } $SearchQuery = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/beta/security/auditLog/queries" -Body $SearchParameters $SearchId = $SearchQuery.Id Write-Output "Waiting for query completion..." do { $search = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/beta/security/auditLog/queries/$searchid" Start-Sleep -Seconds 10 } while ( $search.status -notin @("failed", "succeeded", "cancelled") ) If ( $search.status -in @("failed", "cancelled") ) { Write-Error "The search did not complete successfully. Please check the Security & Compliance Portal - https://security.microsoft.com/auditlogsearch?viewid=Async%20Search" ; break } Write-Output "Fetching results..." $result = [System.Collections.Arraylist]::new() $Uri = ("https://graph.microsoft.com/beta/security/auditLog/queries/{0}/records" -f $SearchId) Get-GraphData -Uri $Uri -result $result $suspiciousEdits = $result | Where-Object {$_.auditdata.modifiedproperties.name -eq "userprincipalname" -and ($_.auditData.Actor.id -match "^\w{8}([-]\w{4}){3}-\w{12}$") -eq ($_.auditData.Target.id -match "^\w{8}([-]\w{4}){3}-\w{12}$") } if (-not $suspiciousEdits) { Write-Output "No suspicious changes found"; break } $Report = [System.Collections.Generic.List[Object]]::new() forEach ($item in $suspiciousEdits) { $modifiedProperty = $item.auditdata.ModifiedProperties | Where-Object {$_.name -eq "userprincipalname"} $obj = [PSCustomObject][ordered]@{ "Timestamp" = "$(get-date ($item.createdDateTime) -Format 'dd-MMM-yyyy HH:mm')" "User GUID" = $item.auditData.Actor.id -match "^\w{8}([-]\w{4}){3}-\w{12}$" "Old UPN" = $modifiedProperty.oldValue "New UPN" = $modifiedProperty.newValue } $report.Add($obj) } $Report | Out-gridview -Title "Please verify, carefully, these UPN changes"
Es ist positiv, dass Microsoft schnell und konsequent auf die Meldungen aus der Community reagiert hat. Dennoch zeigt sich, dass unabhängige Prüfungen weiterhin ein wichtiger Bestandteil einer sicheren Zukunft bei Microsoft bleiben.
Weitere Artikel von früh involvierten Kollegen:
Ihr persönlicher Ansprechpartner
Bei welchem Projekt oder welcher Herausforderung dürfen wir Sie unterstützen? Wir sind gerne für Sie da.
MICHAEL WILDGRUBER | Team Lead Digital Workplace – Cloud Productivity
Wollen Sie immer up2date sein? Dann melden Sie sich jetzt zu unserem Newsletter an
Bleiben Sie auf dem Laufenden. Wir informieren Sie regelmäßig über aktuelle Trends und technologische Neuerungen sowie geplante Webinare und Events. Sie erhalten Einblick in interessante Kundenprojekte und werfen einen Blick hinter die Kulissen. Melden Sie sich jetzt an.