Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix to solve DNS resolution fail when different DNs sufix #196

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

helviojunior
Copy link

@helviojunior helviojunior commented Aug 21, 2024

I faced some issue when using a BloodHound in a environment with a different DNS sufix.

Error sample 1

bloodhound-python -c All -ns 192.168.30.230 -d alunos.sec4us.local -u 'aluno.0' -p '...'
INFO: Found AD domain: alunos.sec4us.local
Traceback (most recent call last):
  File "/usr/local/bin/bloodhound-python", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/bloodhound/__init__.py", line 308, in main
    ad.dns_resolve(domain=args.domain, options=args)
  File "/usr/local/lib/python3.11/dist-packages/bloodhound/ad/domain.py", line 720, in dns_resolve
    q = self.dnsresolver.query(query.replace('pdc','gc'), 'SRV', tcp=self.dns_tcp)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/dns/resolver.py", line 1262, in query
    return self.resolve(
           ^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/dns/resolver.py", line 1204, in resolve
    timeout = self._compute_timeout(start, lifetime, resolution.errors)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/dns/resolver.py", line 988, in _compute_timeout
    raise LifetimeTimeout(timeout=duration, errors=errors)
dns.resolver.LifetimeTimeout: The resolution lifetime expired after 3.103 seconds: Server 192.168.30.230 UDP port 53 answered The DNS operation timed out.

Error sample 2

bloodhound-python -c All -ns 192.168.30.230 -d alunos.sec4us.local -u 'aluno.0' -p '...' --disable-autogc --dns-timeout 50
INFO: Found AD domain: alunos.sec4us.local
Traceback (most recent call last):
  File "/usr/local/bin/bloodhound-python", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/bloodhound/__init__.py", line 308, in main
    ad.dns_resolve(domain=args.domain, options=args)
  File "/usr/local/lib/python3.11/dist-packages/bloodhound/ad/domain.py", line 720, in dns_resolve
    q = self.dnsresolver.query(query.replace('pdc','gc'), 'SRV', tcp=self.dns_tcp)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/dns/resolver.py", line 1262, in query
    return self.resolve(
           ^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/dns/resolver.py", line 1201, in resolve
    (nameserver, port, tcp, backoff) = resolution.next_nameserver()
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/dns/resolver.py", line 704, in next_nameserver
    raise NoNameservers(request=self.request, errors=self.errors)
dns.resolver.NoNameservers: All nameservers failed to answer the query _ldap._tcp.gc._msdcs.alunos.sec4us.local.labpentestbrasil.com.br. IN SRV: Server 192.168.30.230 UDP port 53 answered SERVFAIL

This second error show me what is the issue

Looking at my DNS config

ccat /etc/resolv.conf
───────┬────────────────────────────────
       │ File: /etc/resolv.conf
───────┼────────────────────────────────
    1  │ # Generated by NetworkManager
    2  │ search labpentestbrasil.com.br
    3  │ nameserver 192.168.30.1
───────┴────────────────────────────────

Solution PoC

To test i just put the "." at the end of the domain

bloodhound-python -c All -ns 192.168.30.230 -d alunos.sec4us.local. -u 'aluno.0' -p '...'
INFO: Found AD domain: alunos.sec4us.local
WARNING: Could not find a global catalog server, assuming the primary DC has this role
If this gives errors, either specify a hostname with -gc or disable gc resolution with --disable-autogc
INFO: Getting TGT for user
WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: [Errno Connection error (dc02.alunos.sec4us.local:88)] [Errno 113] No route to host
INFO: Connecting to LDAP server: dc02.alunos.sec4us.local
INFO: Found 1 domains
INFO: Found 2 domains in the forest
INFO: Found 5 computers
INFO: Connecting to LDAP server: dc02.alunos.sec4us.local
INFO: Connecting to GC LDAP server: dc02.alunos.sec4us.local
INFO: Found 132 users
INFO: Found 75 groups
INFO: Found 2 gpos
INFO: Found 16 ous
INFO: Found 19 containers
INFO: Found 1 trusts
...

Solution

Add the following code to force "." at the end

args.domain = f'{args.domain.rstrip(" .")}.'

Final test

ccat /usr/local/lib/python3.11/dist-packages/bloodhound/__init__.py -l 285:310
─────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
     │ File: /usr/local/lib/python3.11/dist-packages/bloodhound/__init__.py
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 ... │
 285 │     elif args.hashes is not None and args.username is not None:
 286 │         logging.debug('Authentication: NT hash')
 287 │         lm, nt = args.hashes.split(":")
 288 │         auth = ADAuthentication(lm_hash=lm, nt_hash=nt, username=args.username, domain=args.domain, auth_method=args.auth_method)
 289 │     elif args.aesKey is not None and args.username is not None:
 290 │         logging.debug('Authentication: Kerberos AES')
 291 │         auth = ADAuthentication(username=args.username, domain=args.domain, aeskey=args.aesKey, auth_method=args.auth_method)
 292 │     else:
 293 │         if not args.kerberos:
 294 │             parser.print_help()
 295 │             sys.exit(1)
 296 │         else:
 297 │             auth = ADAuthentication(username=args.username, password=args.password, domain=args.domain, auth_method=args.auth_method)
 298 │
 299 │     # Put "." at the end to prevent DNS resolution error
 300 │     args.domain = f'{args.domain.rstrip(" .")}.'
 301 │
 302 │     ad = AD(auth=auth, domain=args.domain, nameserver=args.nameserver, dns_tcp=args.dns_tcp, dns_timeout=args.dns_timeout, use_ldaps=args.use_ldaps)
 303 │
 304 │     # Resolve collection methods
 305 │     collect = resolve_collection_methods(args.collectionmethod)
 306 │     if not collect:
 307 │         return
 308 │     logging.debug('Resolved collection methods: %s', ', '.join(list(collect)))
 309 │
 310 │     logging.debug('Using DNS to retrieve domain information')
 ... │
─────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
bloodhound-python -c All -ns 192.168.30.230 -d alunos.sec4us.local -u 'aluno.0' -p '...'
INFO: Found AD domain: alunos.sec4us.local
WARNING: Could not find a global catalog server, assuming the primary DC has this role
If this gives errors, either specify a hostname with -gc or disable gc resolution with --disable-autogc
INFO: Getting TGT for user
WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: [Errno Connection error (dc02.alunos.sec4us.local:88)] [Errno 113] No route to host
INFO: Connecting to LDAP server: dc02.alunos.sec4us.local
INFO: Found 1 domains
INFO: Found 2 domains in the forest
INFO: Found 5 computers
INFO: Connecting to LDAP server: dc02.alunos.sec4us.local
INFO: Connecting to GC LDAP server: dc02.alunos.sec4us.local
INFO: Found 132 users
INFO: Found 75 groups
INFO: Found 2 gpos
INFO: Found 16 ous
INFO: Found 19 containers
INFO: Found 1 trusts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant