Last year, hackthebox let me test something I have always found fascinating – and scary: You can impersonate any user in a Windows Active Directory Forest if you have control over the certificate templates of an AD-integrated Windows Public Key Infrastructure: Add extended key usages for smartcard logon to the template, enroll for the certificate, import it onto a smartcard, and run Windows tools capable of the /smartcard option on a domain member computer.
Apart from the PKI configuration, the most interesting part of this exercise was to configure the test environment properly for all the communication that happens when a Windows client tries to find its Domain Controller for the first time. The 2019 write-up was so long already, so that part was maybe not given its proper attention, hence this new post!
The box to be attacked: A Windows Domain Controller with all necessary ports accessible, with the notable exception of Kerberos TCP 88 (So this can be extrapolated to any DC not directly accessible from the attack box.)
To logon to this DC and get a Kerberos ticket, you need a helper tool to route this inaccessible traffic to an attack box. You could use the routing feature in a meterpreter shell in combination with metasploit’s socks proxy, or upload a tool such as chisel.
In any case, a box of yours will proxy / forward the traffic and your Kerberos tools connect to 127.0.0.1 or whatever local IP you use.
When I saw my potential Windows domain member query for names like _kerberos._tcp.dc._msdcs.HTB.LOCAL in my first failed tests, I remembered: net use or runas do not let you specify a Domain Controller. In order to locate its proper Domain Controller and Kerberos Distribution Center, a Windows client rely on a bunch of special DNS Locator records. The Windows client’s Netlogon service tries to find its nearest DC by asking for SRV records:
Each domain controller in a domain will register its host name with the SRV record, so the client’s query results will be a list of domain controller host names. The client also retrieves the associated A records, providing the client with the IP address of every domain controller in the domain. The client then sends an LDAP search query, via the User Datagram Protocol (UDP), to each domain controller. Each domain controller then responds, indicating that it is operational. The Netlogon service caches all of this information so that finding a domain controller in the future won’t require a repeat of this initial process. Instead, the service can simply refer to its cache to find another domain controller. …
If you proxy / forward traffic from the DC, your client would need to accept 127.0.0.1 as its legit DC. The client needs to query a true DNS server for SRV records, /etc/hosts will not do. But just ‘proxying’ DNS is not sufficient: The DNS replies (from the true DC) to the locator queries will point to the true IP address of the DC (10.10.10.103 for hackthebox ‘Sizzle’ ).
One solution without playing with DNS might be to hardcode entries in the client’s cache – some registry keys if I vaguely recall my Active Directory troubleshooting days :-) I did not test this as you might have to re-configure on reboot etc., so I but went for:
The Linux box was the actual attack box that exposed the missing Kerberos port (using metasploit’s routing). The Windows victim box has a hosts file that associates the Linux box’s IP with the DC’s fully qualified name. BTW I also tested the ancient concept of an LMHOSTS for domain location – but this does not fully work anymore in the age of Kerberos.
I forwarded these TCP ports
Example commands for forwarding:
proxychains socat TCP-LISTEN:88,fork TCP:10.10.10.103:88 & proxychains socat UDP-LISTEN:389,fork,reuseaddr UDP:10.10.10.103:389 &
Only DNS was not forwarded, and the Windows box also uses the Linux box as its primary DNS server. So even if you manage to find a proxychains equivalent on Windows (I could not – at least not one that would also proxy Kerberos) it is a good idea to separate the attack box – also maintaining the VPN connection! – from the Windows domain member. Or you let your test lab DNS server run a conditional forwarder for the domain of the attacked DC, forwarding DNS queries for the interesting domain (htb.local) to the Linux box.
As a simple fake DNS server I used dnsmasq – making it the authoritative server for the domain and hosting these SRV records (from dnsmasq.conf)
... srv-host=_ldap._tcp.HTB.LOCAL,sizzle.htb.local,389 srv-host=_ldap._tcp.Default-First-Site-Name._sites.HTB.LOCAL,sizzle.htb.local,389 srv-host=_ldap._tcp.dc._msdcs.htb.local,sizzle.htb.local,389 srv-host=_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs.HTB.LOCAL,sizzle.htb.local,389 srv-host=_ldap._tcp.pdc._msdcs.HTB.LOCAL,sizzle.htb.local,389 srv-host=_ldap._tcp.gc._msdcs.HTB.LOCAL,sizzle.htb.local,3268 srv-host=_ldap._tcp.Default-First-Site-Name._sites.gc._msdcs.HTB.LOCAL,sizzle.htb.local,3268 srv-host=_gc._tcp.HTB.LOCAL,sizzle.htb.local,3268 srv-host=_gc._tcp.Default-First-Site-Name._sites.HTB.LOCAL,sizzle.htb.local,3268 srv-host=_kerberos._tcp.HTB.LOCAL,sizzle.htb.local,88 srv-host=_kerberos._udp.HTB.LOCAL,sizzle.htb.local,88 srv-host=_kerberos._tcp.Default-First-Site-Name._sites.HTB.LOCAL,sizzle.htb.local,88 srv-host=_kerberos._tcp.dc._msdcs.HTB.LOCAL,sizzle.htb.local,88 srv-host=_kpasswd._tcp.HTB.LOCAL,sizzle.htb.local,464
These are not all possible records, but they were sufficient for:
- Joining a machine to the domain using the Windows GUI tools (as the unprivileged user).
- Running sessions as the Administrator successfully on the Windows box:
runas /smartcard cmd
net use \\sizzle.htb.local\c$ /smartcard
For all the details and the PKI stuff, see the old post.
However, I have been thinking that there should be a simpler way to use this certificate template misconfiguration – and by this I do not mean hardcoding cached Netlogon DNS replies!
What if one could use the same principles – but using only software and ideally only a single box … and only Linux? :-)
This might not yet have been the end of this ‘series’! ;-)