Skip to content

Replace mssql_cbt with mssql_epa for full Extended Protection enforcement check#1209

Open
NoahDSJP wants to merge 1 commit intoPennyw0rth:mainfrom
NoahDSJP:merge-mssql-cbt-into-mssql-epa
Open

Replace mssql_cbt with mssql_epa for full Extended Protection enforcement check#1209
NoahDSJP wants to merge 1 commit intoPennyw0rth:mainfrom
NoahDSJP:merge-mssql-cbt-into-mssql-epa

Conversation

@NoahDSJP
Copy link
Copy Markdown

@NoahDSJP NoahDSJP commented Apr 19, 2026

Description

This PR description and any comments are written by me in Japanese
and translated to English using a translation tool (Google Translation).

This PR is a continuation of #1206.

Following @Dfte's suggestion to merge mssql_cbt and mssql_epa into a single module (and using mssql_epa as the name).

The purpose of this PR is to remove mssql_cbt and add the mssql_epa module, which performs more comprehensive EPA checks.

mssql_cbt only detects whether CBT is required.
mssql_epa is more comprehensive, distinguishing between three EPA enforcement levels (Off/Allowed/Required) and also covering SPN-based paths that apply when mandatory encryption is disabled. This cannot be checked with mssql_cbt.

mssql_epa functionality:

  • If Force Encryption is set to On, it tests the EPA setting by sending a fake Channel Binding Token (CBT) and empty CBT.
  • If Force Encryption is set to Off, it tests the EPA setting by sending a fake SPN and an empty SPN.

Detect EPA enforcement:

  • Off — server does not validate CBT/SPN (NTLM relay possible)
  • Allowed — validated only when client provides CBT/SPN (partial protection)
  • Required — server enforces CBT/SPN (NTLM relay blocked)

The tool this module is based on:
https://github.com/NoahDSJP/mssql_epa_check

Notes

  • mssql_epa uses NTLM authentication, so it will be skipped if run with --local-auth or Kerberos authentication.
  • Because NetExec's MSSQL protocol invokes modules only after a successful MSSQL login, this module currently requires an account that can log in to MSSQL. However, the underlying technique operates purely at the NTLM authentication layer to verify EPA settings, so EPA can be verified with any domain user's authentication information. In the future, if a mechanism for handling "modules that do not require MSSQL login" is added to the NetExec framework, this limitation can be resolved.

Wiki updates will be submitted separately to https://github.com/Pennyw0rth/NetExec-Wiki

AI Assistance Disclosure

Developed using Claude Code (Anthropic, Opus 4.7).
All code has been manually reviewed and tested by me.

Type of change

  • 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)
  • This PR was created with the assistance of AI (list what type of assistance, tool(s)/model(s) in the description)

Setup guide for the review

  • Client: Linux, Python 3.10+, NetExec from main
  • Target: Windows Server with MSSQL Server, AD-joined
  • Force Encryption/Extended Protection can be toggled in SQL Server Configuration Manager
  • No additional software required, no GPO changes required

Reproduce:

nxc mssql <target> -u <user> -p <password> -d <domain> -M mssql_epa

Expected output (one of):

  • Extended Protection: Off - NTLM relay POSSIBLE (Vulnerable) (red)
  • Extended Protection: Allowed - ... (Partially Vulnerable) (yellow)
  • Extended Protection: Required - CBT enforced, ... (Secure) (green)
  • Extended Protection: Required - SPN enforced, ... (Secure) (green)

Screenshots (if appropriate):

  • Force Encryption : No / Extended Protection : Off
2026-04-20_08h15_39
  • Force Encryption : No / Extended Protection : Allowed
2026-04-20_08h20_43
  • Force Encryption : No / Extended Protection : Required
2026-04-20_08h22_08
  • Force Encryption : Yes / Extended Protection : Off
2026-04-20_08h23_29
  • Force Encryption : Yes / Extended Protection : Allowed
2026-04-20_08h24_33
  • Force Encryption : Yes / Extended Protection : Required
2026-04-20_08h25_45

Checklist:

  • I have ran Ruff against my changes (poetry: poetry run ruff check ., 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)
  • 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 linked relevant sources that describes the added technique (blog posts, documentation, etc)
  • I have performed a self-review of my own code (not an AI review)
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (PR here: https://github.com/Pennyw0rth/NetExec-Wiki)

@NeffIsBack NeffIsBack added the enhancement New feature or request label Apr 20, 2026
@NeffIsBack
Copy link
Copy Markdown
Member

Thanks for the PR!

@Dfte
Copy link
Copy Markdown
Contributor

Dfte commented Apr 29, 2026

Alright thanks for the PR! So here is the thing:

  • You mention that it only works with NTLM althought it should be the same for Kerberos. It cannot work on local auth for obvious reason.
  • You mention it is possible to enumerate these settings without authenticating ? If this is the case then we should remove the module and add these as default checks in the host_enum_function in mssql.py.

Let me know :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants