Time Sync — Clock Skew (Kerberos & AD)

Ctrl+F: Clock skew too great · KRB_AP_ERR_SKEW · timedatectl set-ntp false · ntpdate · date -u -s · manual clock

Why time sync matters

Kerberos rejects tickets when client and KDC (Domain Controller) clocks differ by more than 5 minutes (default MaxClockSkew).

Symptoms when time is wrong:

KRB_AP_ERR_SKEW
Clock skew too great
Preauthentication failed
Kerberos SessionError: KRB_AP_ERR_SKEW(37)

Correct username/password but auth still fails → sync time first and verify Kerberos Setup - krb5.conf before Kerberoast, Impacket Kerberos scripts, Rubeus, kinit, kpasswd, or Certipy & Certify.

Password must change (NT_STATUS_PASSWORD_MUST_CHANGE) → Change password AD - NT_STATUS_PASSWORD_MUST_CHANGE

OSCP rule: Before any Kerberos/AD attack from Kali, verify time against the DC.


📌 1) Check Current Time

Linux (Kali)

date
timedatectl status
timedatectl show-timesync --all

Windows

date /t
time /t
w32tm /query /status
w32tm /query /source
net time /domain

📌 2) Sync Kali → Domain Controller (Most Common)

Use the DC IP or hostname as NTP source.

Turn off auto NTP first. Kali’s systemd-timesyncd syncs to internet time by default. If you skip this, ntpdate to the DC may work briefly, then the clock drifts back and Kerberos fails again.

Standard sequence (use everywhere):

# 1. Disable automatic NTP (internet sync)
sudo timedatectl set-ntp false
 
# 2. Sync to domain controller
sudo ntpdate -s DC_IP
 
# 3. Verify
date

Replace DC_IP with the domain controller IP (e.g. 10.10.10.10).

Fix the clock (OSCP lab workflow)

When Kerberos fails with clock skew or auth works on Windows but not from Kali — run this sequence:

1. Disable automatic time sync (stops Kali from pulling internet time and undoing your fix):

sudo timedatectl set-ntp false

2. Sync to the domain controller — hostname or IP:

sudo ntpdate -u tombwatcher.htb

If name resolution is unreliable, use the DC IP:

sudo ntpdate -u 10.129.232.167

-u uses an unprivileged UDP port (>1024) — useful when you cannot bind to port 123. -s (slew) is also fine: sudo ntpdate -s 10.129.232.167

3. Verify the offset is small (query only — does not change time):

sudo ntpdate -q 10.129.232.167

The reported offset should be close to zero (milliseconds or a small fraction of a second) — not thousands of seconds. If skew is still large, re-run step 2 or set time manually (see below).

date

Re-enable internet NTP after the lab (optional):

sudo timedatectl set-ntp true

ntpdate (quick one-shot — OSCP favorite)

# Install if missing
sudo apt install ntpdate
 
# Always disable auto NTP first, then sync to DC
sudo timedatectl set-ntp false
sudo ntpdate -s 10.10.10.10
sudo ntpdate -s dc.corp.local
date
 
# Query only — don't set
ntpdate -q 10.10.10.10
 
# Verbose
sudo ntpdate -v 10.10.10.10
FlagDescription
-sSet time via adjtime (slew) — preferred
-bSet time abruptly (step)
-qQuery only
-uUnprivileged mode (port > 1024)
-vVerbose

systemd-timesyncd (Kali default)

Kali uses this for internet NTP. Disable it before ntpdate to the DC:

sudo timedatectl set-ntp false
timedatectl status          # NTP service: inactive
 
sudo ntpdate -s DC_IP
date

To point timesyncd at the DC permanently instead of one-shot ntpdate, edit /etc/systemd/timesyncd.conf:

# [Time]
# NTP=10.10.10.10
# FallbackNTP=
sudo systemctl restart systemd-timesyncd
sudo timedatectl set-ntp true
timedatectl status

Do not leave set-ntp true with pool.ntp.org and expect manual ntpdate to stick — turn auto NTP off first.

chrony (if installed)

Stop chrony before manual sync to DC:

sudo systemctl stop chronyd
sudo ntpdate -s DC_IP
date

Manual set — when DC won’t respond to NTP (HTB / blocked UDP 123)

If ntpdate fails (no server suitable, timeout, or HTB machine ignores NTP), set Kali clock to match the DC manually.

1. Get DC time from any source:

# SMB / enum — note timestamp in output
crackmapexec smb DC_IP -u guest -p ''
enum4linux -a DC_IP
 
# From a Windows shell on domain box
date /t & time /t
w32tm /query /status
 
# From web response headers
curl -I http://DC_IP

2. Disable auto NTP (so your manual set sticks):

sudo timedatectl set-ntp false

3. Set Kali to DC time (UTC) — use -u so timezone doesn’t skew Kerberos:

sudo date -u -s "2026-07-07 23:37:42"

Or with timedatectl:

sudo timedatectl set-time "2026-07-07 23:37:42"

4. Verify — must be within 5 minutes of DC:

date -u

Then retry Kerberos (impacket-getTGT, GetNPUsers, etc.).

HTB tip: When the lab DC doesn’t answer NTP, manual date -u -s is the reliable fix — copy the exact UTC time from the target or DC.

Manual set (generic last resort)

If NTP blocked and you only have a rough time from logs:

# From SMB (impacket or rpcclient often shows DC time in logs)
# Or ask in shell on Windows box: date /t & time /t
 
sudo timedatectl set-ntp false
sudo date -u -s "2026-03-15 14:30:00"
# or: sudo timedatectl set-time "2026-03-15 14:30:00"

📌 3) Sync Through VPN / Pivot

When DC is on internal network only:

# After Chisel/SSH pivot — sync to internal DC IP
sudo timedatectl set-ntp false
sudo ntpdate -s 172.16.0.10
date

See Tunneling, Chisel.


📌 4) Windows — Domain Time Sync

Domain-joined machines sync to DC automatically via Windows Time Service.

Check status

w32tm /query /status
w32tm /query /peers
w32tm /query /configuration
net time /domain
net time \\DC01.corp.local

Force resync to domain

w32tm /resync
w32tm /resync /force
 
REM Sync to specific DC
w32tm /config /manualpeerlist:10.10.10.10 /syncfromflags:manual /reliable:yes /update
w32tm /resync /force

Legacy — set time from DC

net time \\DC01 /set /y
net time /domain /set /y

PowerShell

w32tm /query /status
Get-Date
Set-Date -Date "2026-03-15 14:30:00"   # Admin only — last resort

📌 5) Before Kerberos Attacks (Checklist)

Run on Kali before:

# krb5 + hosts — see [[Kerberos Setup - krb5.conf]]
cat domain.krb5 | sudo tee /etc/krb5.conf
 
date
sudo timedatectl set-ntp false
sudo ntpdate -s DC_IP
date

Then proceed:

impacket-GetNPUsers corp.local/ -dc-ip DC_IP -no-pass -usersfile users.txt
impacket-GetUserSPNs corp.local/user:pass -dc-ip DC_IP -request
impacket-getTGT corp.local/user:pass -dc-ip DC_IP
export KRB5CCNAME=user.ccache
impacket-wmiexec -k -no-pass corp.local/user@TARGET -dc-ip DC_IP

Rubeus from Windows shell on domain-joined host usually inherits correct time — attacks from Linux need explicit sync.


📌 6) Troubleshooting

ProblemFix
Clock skew too great / KRB_AP_ERR_SKEWsudo timedatectl set-ntp falsesudo ntpdate -u DC_IPsudo ntpdate -q DC_IP
Time syncs then drifts backAuto NTP still on — run timedatectl set-ntp false first
ntpdate: no server suitableDC ignores NTP (common HTB) — sudo timedatectl set-ntp false then sudo date -u -s "YYYY-MM-DD HH:MM:SS" from DC time
UDP 123 blockedManual date -u -s from DC time
VPN time driftRe-sync after long session
Dual boot / VM suspendAlways re-sync when resuming VM
DC unreachable for NTPGet time via net time \\DC from Windows shell, set manually
Correct time but still failsCheck -dc-ip, DNS, /etc/hosts, Kerberos Setup - krb5.conf, realm case (CORP.LOCAL)

Verify skew is fixed

# Retry lightweight Kerberos request
impacket-GetNPUsers corp.local/ -dc-ip 10.10.10.10 -no-pass -users jsmith 2>&1 | head
kerbrute passwordspray -d corp.local --dc 10.10.10.10 -u user -p pass

📌 7) OSCP Exam Tips

  • Sync immediately when starting AD set — before Kerbrute, AS-REP, Kerberoast
  • DC IP is usually in /etc/hosts or nmap — use that for ntpdate
  • If NTP blocked, note DC time from enum4linux, crackmapexec smb, or SMB session — set manually
  • Re-sync if you pause for lunch and tickets suddenly fail
  • Time zone doesn’t matter — absolute UTC offset must match within 5 minutes

📌 Quick Cheat Sheet

# Kali → DC (always disable auto NTP first)
date
sudo timedatectl set-ntp false
sudo ntpdate -u DC_IP              # or: sudo ntpdate -s DC_IP
sudo ntpdate -q DC_IP              # verify offset ≈ 0
date
 
# Manual fallback — DC won't answer NTP (HTB)
sudo timedatectl set-ntp false
sudo date -u -s "2026-07-07 23:37:42"   # match DC UTC time exactly
date -u
REM Windows domain box
w32tm /query /status
w32tm /resync /force
net time \\DC01 /set /y