Door Mauricio Payne, Security Analyst bij Secura

Compromittering van Azure-cloud via gevoelige API-rechten

Onlangs hebben onderzoekers bij Cloudbrothers een interessante nieuwe manier gevonden om van een on-premise omgeving naar een Azure-omgeving te pivoteren en Global Admin-rechten te verkrijgen. In deze blog geven we u een demonstratie en uitleg van deze aanval. Daarnaast zullen er enkele mitigerende stappen worden opgenomen om u te helpen deze aanval te detecteren en ertegen te beschermen.

Demonstratie van het aanvalsplan

Onderzoekers bij Cloudbrothers ontdekten dat een aanvaller die in staat is geweest om het AAD Sync-account dat door de AD Connect-server wordt gebruikt te compromitteren, hun privileges kan escaleren naar Global Admin door applicaties met gevoelige rechten te exploiteren.

Dit is mogelijk omdat het AAD Sync-account zowel de ‘microsoft.directory/applications/owners/update’ als de ‘microsoft.directory/servicePrincipals/owners/update’ rechten heeft. Hierdoor kan het de eigenaren van geregistreerde applicaties bijwerken.

Bovendien kan dit account met behulp van de ‘microsoft.directory/servicePrincipals/credentials/update’ rechten direct inloggegevens aan deze applicaties toevoegen zonder zichzelf eerst als eigenaar te moeten toevoegen.

Deze applicaties kunnen vervolgens worden gebruikt om privileges te escaleren als ze de juiste rechten hebben.

In deze blog zullen we ons richten op twee van deze gevoelige rechten (‘RoleManagement.ReadWrite.Directory’ en ‘AppRoleAssignment.ReadWrite.All’) en demonstreren we het aanvalsplan waar een aanvaller doorheen zou moeten gaan, waarbij elke stap wordt beschreven.

Image in image block

Compromising Azure cloud

VOORDAT WE BEGINNEN

Voordat we beginnen, is het belangrijk om enkele aannames te bespreken die zijn gemaakt om deze aanval uit te kunnen voeren.

De eerste aanname is dat er een applicatie is geregistreerd op Azure die een van de twee eerder genoemde gevoelige rechten bevat.

De tweede aanname is dat u erin bent geslaagd om de server waarop AD Connect draait volledig te compromitteren en dat u in staat bent geweest om de inloggegevens voor het AAD Sync-account te dumpen. Het dumpen van de inloggegevens kan op verschillende manieren worden gedaan, bijvoorbeeld met behulp van de AADInternals PowerShell-module. Het gebruik van de Get-AADIntSyncCredentials op de AD Connect-server retourneert de inloggegevens voor de AAD Sync-gebruiker:

Image in image block

The AD Connect server returns the credentials for the AAD Sync user

Zodra deze inloggegevens zijn vastgelegd, kunnen we overgaan tot de eigenlijke hoofdaanval. De eerste stap is om te authenticeren bij de tenant als de AAD Sync-gebruiker:

Image in image block

Authenticate to the tenant as the AAD Sync user

Image in image block

Response containing JWT

Uitgerust met dit JWT-token kunnen we nu oproepen doen naar de Microsoft Graph API en een lijst krijgen van alle geregistreerde applicaties op de Tenant. Dit JWT-token kan worden opgeslagen in een PowerShell-variabele die kan worden gebruikt als een authenticatieheader:

$AuthHeader = @{Authorization = "Bearer <JWT>"}

Door dit te doen kunnen we vervolgens een verzoek maken aan het beta/applications-eindpunt met behulp van PowerShell:

Invoke-RestMethod -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/applications/"

De afbeelding hieronder toont de respons voor het verzoek dat is gemaakt aan het beta/applications-eindpunt, dat alle geregistreerde applicaties bevat.

Image in image block

Response for the request made to the beta/applications endpoint

Looking through this response we see a lot of information regarding the different applications. However, what is important to us in this attack is the “appID” field. These Id’s should be saved into a list as they are required for the next step of the attack. In this step we will use the appID to make a request the the Graph API and query which service principals belong to that application.

Below we can see the response of such a request which contains the ID of the service principal belonging the the application with appID 8c3ffdc3-fe9d-47a2-9bbc-3bc49e486c43. This request can be done through PowerShell with the following command:

Invoke-RestMethod -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/servicePrincipals/?`$filter=(appid eq '<appID>')"

Image in image block

Response with ID of service principal

Zodra we de ID van deze serviceprincipals hebben, kunnen we zoeken naar de aan hen toegewezen rechten. Specifiek zoeken we naar een recht met een appRoleID van "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8", wat overeenkomt met de RoleManagement.ReadWrite.Directory-rol, of het appRoleID van "06b708a9-e830-4db3-a914-8e69da51d44f", wat overeenkomt met de AppRoleAssignment.ReadWrite.All-rol.

ROLEMANAGEMENT.READWRITE.DIRECTORY

De RoleManagement.ReadWrite.Directory-rol geeft de applicatie de toestemming om extra privileges aan zichzelf, andere applicaties of elke gebruiker te verlenen. Door het volgende verzoek te doen, kunnen we zien welke rechten zijn toegewezen aan de serviceprincipal met id: "9e666f83-8520-4c65-a8e2-e929194839ea".

Invoke-RestMethod -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/servicePrincipals/<ServicePrincipalID>/appRoleAssignments"

In de afbeelding hieronder zien we de respons op het bovenstaande verzoek. Kijkend naar de respons zien we het eerder genoemde appRoleId, waardoor deze applicatie kwetsbaar is voor deze aanval.

Image in image block

Response containing appRoleID

Zodra we een applicatie hebben gevonden die deze rol ingesteld heeft, kunnen we onze gebruiker (in dit geval de AAD Sync-gebruiker) toevoegen als eigenaar van deze serviceprincipal. In PowerShell zou het verzoek er als volgt uitzien:

$Reference = @{ "@odata.id" = "https://graph.microsoft.com/beta/directoryObjects/" + <AAD Sync userID> } | ConvertTo-Json

Invoke-RestMethod -Method Post -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/servicePrincipals/<ServicePrincipalToTakeover>/owners/`$ref" - Body $Reference -ContentType "application/json" | Out-Null

De respons op dit verzoek zou er als volgt uitzien:

Image in image block

Response when adding user as owner

De volgende stap is om een nieuwe secret toe te voegen aan de serviceprincipal, die we later zullen gebruiken om te authenticeren bij de tenant als deze kwetsbare applicatie. Er wordt een POST-verzoek gedaan aan de Graph API, die automatisch een veilig wachtwoord instelt en dit retourneert in de "secretText"-parameter. Dit wordt gedaan met het volgende PowerShell-commando:

Invoke-RestMethod -Method Post -Headers $AuthHeader -Uri "https://graph.microsoft.com/beta/servicePrincipals/" -Body $Reference -ContentType "application/json"

Zoals hieronder te zien is, retourneert de API de secretText:

Image in image block

Response containing newly added secret

Door de appID van de kwetsbare applicatie te gebruiken als de "Client_Id" en het nieuw toegevoegde geheim als de "Client_Secret", kunnen we authenticeren bij de tenant als deze serviceprincipal en een nieuw JWT-token ontvangen.

Image in image block

API request authenticating as service principal

APPROLEASSIGNMENT.READWRITE.ALL

De AppRoleAssignment.ReadWrite.All-rol staat de applicatie toe om extra privileges aan zichzelf toe te kennen. Dit betekent dat we de RoleManagement.ReadWrite.Directory-rol aan de applicatie kunnen toekennen en Global Admin-rechten kunnen verkrijgen. Hieronder is een afbeelding te zien waarin we een kwetsbare applicatie met deze rol identificeren:

Image in image block

Zodra we deze applicatie hebben geïdentificeerd, kunnen we er een geheim aan toevoegen dat we kunnen gebruiken om te authenticeren als de applicatie bij de Azure-tenant:

Image in image block

Zoals eerder gezien wordt het wachtwoord geretourneerd als de "secretText"-parameter, die we in combinatie met de appID zullen gebruiken om te authenticeren bij de tenant:

Image in image block

Dit retourneert een JWT-token dat, wanneer gedecodeerd, zoals we kunnen zien alleen de "AppRoleAssignment.ReadWrite.All"-rol bevat:

Image in image block

Door dit JWT-token te gebruiken als het nieuwe autorisatietoken, kunnen we de vereiste rol toevoegen aan de applicatie. Om dit te doen, moeten we de appRoleID van de rol die we willen toevoegen, de principalId en de resourceId kennen. Het verzoek om de RoleManagement.ReadWrite.Directory-rol toe te voegen kan worden gedaan met de volgende PowerShell-commando's:

$params = @{
principalId = <servicePrincipalId>
resourceId = <resourceId>
appRoleId = "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8"
} | ConvertTo-Json

Invoke-RestMethod -Method POST -Headers $AppAuthHeader -Uri "https://graph.microsoft.com/v1.0/servicePrincipals/ <servicePrincipalId>/appRoleAssignments" - Body $params -ContentType "application/json"

Image in image block

Response to adding this role

Nu kunnen we opnieuw authenticeren als de applicatie met hetzelfde wachtwoord dat we eerder hebben toegevoegd. Bij het bekijken van het nieuw gegenereerde JWT-token kunnen we zien dat onze nieuwe rol met succes is toegepast:

Image in image block

Dit kan ook worden gecontroleerd op het Azure-portaal door de applicatie te bezoeken:

Image in image block

GEBRUIKER TOEVOEGEN ALS GLOBAL ADMIN

Met dit nieuwe JWT kunnen we verzoeken doen als de serviceprincipal. Omdat het de RoleManagement.ReadWrite.Directory-rol heeft, stelt het ons in staat om een gebruiker de rol van Global Admin toe te wijzen. In PowerShell wordt dit gedaan door de AppAuthHeader-variabele bij te werken naar het nieuwe JWT-token en de volgende commando's uit te voeren:

$Reference = @{ "@odata.id" = "https://graph.microsoft.com/beta/directoryObjects/" + <UserIDToMakeGlobalAdmin> } | ConvertTo-Json

Invoke-RestMethod -Method Post -Headers $AppAuthHeader -Uri "https://graph.microsoft.com/beta/directoryRoles/roleTemplateId=62e90394-69f5-4237-9190- 012177145e10/members/`$ref" -Body $Reference -ContentType "application/json"

Als we op het Azure-portaal kijken, kunnen we zien dat onze gebruiker nu deel uitmaakt van de Global Administrators:

Image in image block

MITIGATIES

Als het gaat om manieren om deze aanval te mitigeren, is er geen eenduidig antwoord. Er zijn echter bepaalde acties die kunnen worden ondernomen om het slagingspercentage van deze aanval te verminderen.

De eerste en meest voor de hand liggende is het beperken van het gebruik van gevoelige rollen zoals RoleManagement.ReadWrite.Directory. In sommige gevallen zijn deze rollen vereist; in deze scenario's is het het beste om deze applicaties nauwlettend te volgen en geautomatiseerde reacties klaar te hebben in het geval van afwijkend gedrag.

Daarnaast zou het gebruik van voorwaardelijke toegang de kans op succes van deze aanval via internet verminderen. Dit zou bijvoorbeeld kunnen worden gedaan door alleen aanmeldingen voor het AAD Sync-account vanaf uw on-premises toe te staan. Eventuele onregelmatigheden hier zouden dan kunnen worden gebruikt om een waarschuwing te activeren en u op de hoogte te stellen van een mogelijk kwaadaardige inlogpoging. Echter, zoals in dit voorbeeld te zien is, kan een aanvaller die de AD Connect-server heeft gecompromitteerd deze voorwaardelijke toegangsbeleid omzeilen door de aanval uit te voeren vanaf de AD Connect-server.

Verder moeten er beveiligingsmaatregelen worden getroffen op de AD Connect-server om te monitoren en het soort acties dat op de server kan worden uitgevoerd te verminderen. Een voorbeeld hiervan zou kunnen zijn om het gebruik van tools zoals AADInternals te blokkeren.

De kern van deze mitigaties is dat er geen enkele oplossing is voor deze aanval. In plaats daarvan zouden er meerdere lagen van verdediging moeten zijn die een aanvaller hopelijk stoppen voordat ze zelfs maar toegang krijgen tot de AD Connect-server.

Voor meer informatie over deze aanval, bekijk:

https://cloudbrothers.info/en/prem-global-admin-password-reset/
https://cloudbrothers.info/en/azure-attack-paths/#api-permissions
https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48

Over de auteur

Mauricio Payne

Mauricio Payne is Security Analyst bij Secura. Hij heeft ICT & Software gestudeerd en zich gespecialiseerd in Cybersecurity aan de Fontys Hogescholen in Eindhoven. Sinds zijn afstuderen werkt hij bij Secura, waar hij zich specialiseert in webapplicatie- en cloud-assessments.

Quote by

Meer Informatie

Heeft u vragen over dit artikel of wilt u meer informatie over hoe Secura u kan helpen uw cyberweerbaarheid te verhogen? Vul het formulier in en we nemen binnen één werkdag contact met u op.

USP

Gerelateerde Diensten

Cloud Pentesting

Article image

Ontdek meer over onze Cloud Pentesting Service en beveilig uw cloud.

Cloud Security Training

Article image

Leer meer over Cloud Security met onze gespecialiseerde Cloud Security Training.

OVER SECURA

Secura is een toonaangevend bedrijf op het gebied van cyberbeveiliging. Onze klanten variëren van overheid en zorg tot financiën en industrie. Secura biedt technische diensten aan, zoals vulnerability assessments, penetratietesten en Red Teaming. We bieden ook certificering voor IoT en industriële omgevingen, evenals audits, forensische diensten en awarenesstrainingen.

Ons doel is om uw cyberweerbaarheid te vergroten. Wij zijn een Bureau Veritas-bedrijf. Bureau Veritas (BV) is een beursgenoteerde onderneming die gespecialiseerd is in testen, inspecteren en certificeren. BV is opgericht in 1828, heeft ruim 80.000 medewerkers en is actief in 140 landen. Secura is de hoeksteen van de cyberbeveiligingsstrategie van Bureau Veritas.