PowerShell Profile abuse (MITRE ATT&CK T1546.013) is a Windows technique for persistence and privilege escalation. A PowerShell profile, profile.ps1, is a script that runs when PowerShell starts. It is meant as a logon script to customize the user environment.
How attackers use it
PowerShell supports several profiles, depending on the user and the host program. The PowerShell console, the ISE and Visual Studio Code can each have their own, and an administrator can set up a profile that applies to all users and hosts on the computer.
MITRE explains that an adversary can edit these profiles to add commands, functions, modules and drives. The modified script then runs each time a user opens a PowerShell session, unless PowerShell is launched with the -NoProfile flag.
Privilege escalation is possible when a higher privileged account, such as a domain administrator, loads and runs a profile that an attacker has written to.
How to detect it
MITRE's strategy links file events to process starts:
- Creation or modification of files in known profile locations.
- PowerShell launches afterward that do not use
-NoProfile. - Profile scripts that load unusual modules or launch external programs, especially in elevated contexts.
Script block logging in PowerShell can help show what a profile did, though MITRE's strategy is file and process centered.
How to reduce the risk
- Sign and enforce. Allow only signed PowerShell scripts, and sign profiles so changes break the signature.
- Lock the files. Make profiles immutable and changeable only by certain administrators.
- Avoid profiles where not needed. Run remote and automated scripts with the NoProfile flag so local profiles do not execute.
Check your own environment
In PowerShell, read-only:
$PROFILE | Select-Object *
Test-Path $PROFILE.AllUsersAllHosts
Get-Item $PROFILE.AllUsersAllHosts, $PROFILE.CurrentUserAllHosts -ErrorAction SilentlyContinue | Select-Object FullName, LastWriteTime
The first shows the profile paths for the current host. The others show whether the broadest profiles exist and when they last changed. A profile that nobody on the team created is the finding.
Quick check
What flag stops a profile from running?
NoProfile. Using it for automated and remote script runs prevents local profiles from executing.