Skip to content

Conversation

@n3rada
Copy link
Contributor

@n3rada n3rada commented Nov 5, 2025

Description

Currently, username enumeration "like kerbrute" in NetExec requires LDAP access, which needs valid credentials. However, Kerberos AS-REQ requests can enumerate valid usernames without any credentials and without incrementing badPwdCount (resolve issue #195 ), making it interesting for initial reconnaissance, an allow us to get rid of kerbrute lookalikes.

Type of change

Insert an "x" inside the brackets for relevant items (do not delete options)

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Deprecation of feature or functionality
  • This change requires a documentation update
  • This requires a third party update (such as Impacket, Dploot, lsassy, etc)

Setup guide for the review

  • Target: Any Active Directory domain controller (tested on Windows Server 2019/2022, on hercules.htb).
  • NetExec: Latest main branch + this PR.
  • Dependencies: None (uses existing Impacket/Kerberos utilities).

Use the names.withletters trick to create name.a, name.b variants:

awk '/^[[:space:]]*$/ {next} { gsub(/^[ \t]+|[ \t]+$/,""); for(i=97;i<=122;i++) printf "%s.%c\n", $0, i }' /usr/share/seclists/Usernames/Names/names.txt | tee /tmp/names.txt > /dev/null

Screenshots (if appropriate):

Single user check:

netxec-user

Threaded user enumeration (kerbrute):

netxec-enum

Checklist:

Insert an "x" inside the brackets for completed and relevant items (do not delete options)

  • I have ran Ruff against my changes (via poetry: poetry run python -m ruff check . --preview, use --fix to automatically fix what it can)
  • I have added or updated the tests/e2e_commands.txt file if necessary (new modules or features are required to be added to the e2e tests)
  • New and existing e2e tests pass locally with my changes
  • If reliant on changes of third party dependencies, such as Impacket, dploot, lsassy, etc, I have linked the relevant PRs in those projects
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (PR here: Add documentation for Kerberos authentication and user enumeration NetExec-Wiki#77)

Signed-off-by: n3rada <72791564+n3rada@users.noreply.github.com>
Signed-off-by: n3rada <72791564+n3rada@users.noreply.github.com>
Signed-off-by: n3rada <72791564+n3rada@users.noreply.github.com>
@NeffIsBack
Copy link
Member

Thanks for the PR!

However, i don't really see the advantage over the existing Kerberos authentication schemes. Also, Kerberos is an authentication protocol so there is not much you can do besides authenticating.
image

@n3rada
Copy link
Contributor Author

n3rada commented Nov 5, 2025

The new kerberos protocol provides functionality that is fundamentally different from using SMB/LDAP with the -k flag:

netexec smb 10.10.11.91 -d hercules.htb -k -u /tmp/names.txt -p '' --continue-on-success
  1. Attempts full Kerberos authentication via getKerberosTGT() for each username.
  2. Sends AS-REQ with password/credential (with empty password).
  3. Tries to establish an SMB session after getting TGT.
  4. Does increment badPwdCount because it's attempting authentication with credentials.

Result is KDC_ERR_C_PRINCIPAL_UNKNOWN errors for non-existent users, but also triggers account lockout mechanisms! And, output is not work-ready:

Screenshot 2025-11-05 231858
netexec kerberos 10.10.11.91 -u /tmp/names.txt -d hercules.htb
  1. Sends AS-REQ without any preauthentication data (no password).
  2. Only checks if the KDC recognizes the principal.
  3. Does NOT increment badPwdCount, since no credentials are validated.

The goal of this addition is to leverage the pre-authentication phase for enumeration, similar to what tools like kerbrute do. However, instead of relying on an external tool, this functionality is integrated directly into NetExec, because, everyone love using this tool. 🫣

However, if you think the protocol clearly has no chance of succeeding, I could put this in nxc/protocols/ldap.py with --enum-users-kerb, but that would be really confusing and not Single Responsibility Pattern (SRP) friendly, don't you think?

@mpgn
Copy link
Collaborator

mpgn commented Nov 6, 2025

Why not simply improve the smb/ldap kerberos auth when no password is provided by sending AS-REQ without any preauthentication data (no password) ?

@n3rada
Copy link
Contributor Author

n3rada commented Nov 6, 2025

I understand the suggestion and can definitely implement it that way if needed. You all have the final say on merging, that is your call!

For me, this goes against nxc's design principles because you'd end up typing nxc ldap/smb to run a pure Kerberos operation. That's unintuitive and a bad design decision. It creates confusing UX (Least Surprise Principle) where users won't know where to find Kerberos features, and forces us to add messy if-else conditions in the LDAP codebase just to handle Kerberos enumeration. Having a kerberos section keeps the codebase clean.

I will move the code and make it work if that's the decision, but I still believe a dedicated kerberos protocol is the cleaner approach. Let me know how you want to proceed.

@NeffIsBack
Copy link
Member

So in NetExec protocols should be network protocols that has functionality besides authentication. While it is fine to have tools that solely does authentication or information dumping/gathering while using authentication protocols (e.g. DumpNTLMInfo.py from impacket), i don't think it would be the right choice to go that route in NetExec. That would lead to much confusion, because now you have Kerberos authentication in various network protocols, while also having it as an standalone authentication protocol. I would also chose not to implement NTLM as its own protocol just for checking stuff like NTLMv1/host header etc.

Also, adding a whole separate protocol for NetExec for manipulating authentication steps that are already done in other protocols would mean a ton of duplicate code which in return means a ton of maintenance work that would otherwise not be necessary.

Besides, this decision has been made implicitly in the past already, at the point where similar authentication manipulation was implemented, such as kerberoasting, asreproasting, delegation via S4U etc.

This decision has indeed the disadvantage that we will do this authentication manipulation on top of a whole other protocol like SMB or LDAP, but when implemented properly and independently there is not much duplicate code or work that has to be done to utilize it in other protocols (in other words if implemented protocol independent).

@n3rada
Copy link
Contributor Author

n3rada commented Nov 7, 2025

Understood. What are your thoughts, @NeffIsBack?

Do you think this kind of enumeration should be included in Netexec, or should I put it directly in the Impacket examples?

If you think it should be in netexec, where should it go?

@NeffIsBack
Copy link
Member

I think it is still a cool addition!

That could definitely be something that would be a good addition to impacket, getting something merged into impacket is a challenge on its own (no hate to the maintainers, just a fact that is the result of the amount of PRs opened to impacket).

To get this into NetExec it should live in its own file, so it is independent of the protocol, but could live in the protocol folder. I would suggest using SMB due to the existing enumeration functions, but ldap would probably work just as well.

We could either add a separate flag, or just combine it with the --continue-on-success function which is used for user enumeration. Perhaps something like:

def kerberos_login():
    if continue_on_success:
        get_tgt()
    else:
        impacket_kerb_login()

@n3rada
Copy link
Contributor Author

n3rada commented Nov 9, 2025

Thanks for the feedback. I have refactored the code to integrate Kerberos user enumeration directly into the SMB protocol as requested, rather than as a separate protocol.

Batch enumeration
Screenshot 2025-11-09 155508

Single user verification
Screenshot 2025-11-09 155401

However, in my opinion, it remains misleading as it shows 'SMB' and port 445 while actually using pure Kerberos (port 88), but that is our current tradeoff. At least it exists now.

The enumeration is slower than desired due to NetExec's architecture - the framework uses a global semaphore (BoundedSemaphore(1)) in connection.py that serializes all authentication attempts to prevent race conditions. This design means even with --threads 20, enumeration happens sequentially.

While threading at the orchestration level (in netexec.py) could improve speed, I've kept changes minimal and focused on the integration.

@n3rada
Copy link
Contributor Author

n3rada commented Nov 9, 2025

Even though it has a low chance of hatching, I have added it directly to the examples folder: fortra/impacket#2079

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.

3 participants