Python port of rdp-sec-check originally written in Perl by Mark Lowe (Portcullis / Cisco CX Security Labs). Python port by Michał Majchrowicz — Copyright (C) 2026 Michał Majchrowicz.
This version requires no external dependencies (pure Python 3 stdlib) and adds SOCKS proxy support.
- Support for targets file
- Support for saving the tool output to a specified logfile
- Control over the connection and response timeouts
- Control over the number of retries when timeouts occur
- SOCKS4 / SOCKS4a / SOCKS5 proxy support (with optional username/password authentication)
- Per-issue remediation descriptions printed after the security-issue summary
- No external dependencies — pure Python 3, no CPAN or pip required
rdp-sec-check is a script to enumerate the different security settings of a Remote Desktop service (AKA Terminal Services).
It does not require authentication, only network connectivity to TCP port 3389.
It can determine many (though not quite all) of the security settings from the RDP-Tcp Properties | General tab:
- Check which security layers are supported by the service: Standard RDP Security, TLSv1.0, CredSSP
- For Standard RDP Security it detects the level of encryption supported: 40-bit, 56-bit, 128-bit, FIPS
The following potential security issues are flagged if present:
- The service supports Standard RDP Security – this is known to be vulnerable to an active "Man-In-The-Middle" attack
- The service supports weak encryption (40-bit or 56-bit)
- The service does not mandate Network Level Authentication (NLA) — NLA can help to prevent certain types of Denial of Service attack
- The service supports FIPS encryption but doesn't mandate it – may only be interesting for jurisdictions where FIPS is required
Python 3.6 or newer. No third-party packages required.
python3 rdp-sec-check.py --help
usage: rdp-sec-check.py [-h] [--file hosts.txt] [--outfile out.log]
[--timeout sec] [--retries times]
[--socks [socks4://|socks4a://|socks5://][user:pass@]host:port]
[--verbose] [--debug]
[host]
| Option | Description |
|---|---|
host |
Target host, optionally with port (host:port). Default port: 3389. |
--file hosts.txt |
Read targets from file, one host or host:port per line. |
--outfile out.log |
Write output to a logfile in addition to stdout. |
--timeout sec |
Socket receive timeout in seconds (default: 10). |
--retries times |
Number of retries after a timeout (default: 2). |
--socks ... |
Route all connections through a SOCKS proxy (see below). |
--verbose |
Print extra diagnostic information during scanning. |
--debug |
Print raw packet bytes and low-level connection details. |
The --socks argument accepts a proxy URL in the following formats:
host:port # SOCKS5, no auth (default)
socks5://host:port # SOCKS5, no auth
socks5://user:pass@host:port # SOCKS5 with username/password
socks4://host:port # SOCKS4 (requires resolvable target IP)
socks4a://host:port # SOCKS4a (proxy resolves hostname)
socks4a://user@host:port # SOCKS4a with user ID
[::1]:1080 # IPv6 proxy address
Protocol notes:
- SOCKS5 — full RFC 1928/1929 support; resolves target hostnames at the proxy (
ATYP 0x03) when a hostname is given, otherwise sends IPv4/IPv6 address directly. - SOCKS4a — sends the hostname to the proxy for remote resolution (target IP is not needed locally).
- SOCKS4 — requires the target to be an IP address or locally resolvable hostname; hostname is resolved on the client side before the CONNECT request.
$ python3 rdp-sec-check.py 192.168.1.1
$ python3 rdp-sec-check.py 192.168.1.1:3390
$ python3 rdp-sec-check.py --file hosts.txt --outfile rdp.log
$ python3 rdp-sec-check.py --timeout 15 --retries 3 192.168.1.1
$ python3 rdp-sec-check.py --socks 127.0.0.1:1080 192.168.1.1
$ python3 rdp-sec-check.py --socks socks5://user:pass@10.0.0.1:1080 --file hosts.txt
$ python3 rdp-sec-check.py --socks socks4a://proxy.example.com:1080 192.168.1.1
$ python3 rdp-sec-check.py 10.0.0.21
Starting rdp-sec-check v0.9-beta ( https://github.com/sectroyer/rdp-sec-check-py ) at Tue May 6 11:00:00 2026
Target: 10.0.0.21
IP: 10.0.0.21
Port: 3389
[+] Checking supported protocols
[-] Checking if RDP Security (PROTOCOL_RDP) is supported...Not supported - HYBRID_REQUIRED_BY_SERVER
[-] Checking if TLS Security (PROTOCOL_SSL) is supported...Not supported - HYBRID_REQUIRED_BY_SERVER
[-] Checking if CredSSP Security (PROTOCOL_HYBRID) is supported [uses NLA]...Supported
[+] Checking RDP Security Layer
[-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_NONE...Not supported
[-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_40BIT...Not supported
[-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_128BIT...Not supported
[-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_56BIT...Not supported
[-] Checking RDP Security Layer with encryption ENCRYPTION_METHOD_FIPS...Not supported
[+] Summary of protocol support
[-] 10.0.0.21:3389 supports PROTOCOL_RDP : FALSE
[-] 10.0.0.21:3389 supports PROTOCOL_HYBRID: TRUE
[-] 10.0.0.21:3389 supports PROTOCOL_SSL : FALSE
[+] Summary of RDP encryption support
[-] 10.0.0.21:3389 supports ENCRYPTION_METHOD_NONE : FALSE
[-] 10.0.0.21:3389 supports ENCRYPTION_METHOD_40BIT : FALSE
[-] 10.0.0.21:3389 supports ENCRYPTION_METHOD_128BIT : FALSE
[-] 10.0.0.21:3389 supports ENCRYPTION_METHOD_56BIT : FALSE
[-] 10.0.0.21:3389 supports ENCRYPTION_METHOD_FIPS : FALSE
[+] Summary of security issues
rdp-sec-check v0.9-beta completed at Tue May 6 11:00:01 2026
$ python3 rdp-sec-check.py 10.150.2.150
...
[+] Summary of security issues
[-] 10.150.2.150:3389 has issue NLA_SUPPORTED_BUT_NOT_MANDATED_DOS
NLA (Network Level Authentication) is supported but not required. Without mandatory NLA,
unauthenticated connections can consume server resources, enabling Denial-of-Service attacks.
Fix: Enforce NLA in Group Policy: Computer Configuration > Administrative Templates >
Windows Components > Remote Desktop Services > Require NLA.
[-] 10.150.2.150:3389 has issue SSL_SUPPORTED_BUT_NOT_MANDATED_MITM
TLS/SSL is supported but not mandated. The server still accepts legacy Standard RDP Security,
which is vulnerable to Man-in-the-Middle attacks due to weak RSA key exchange.
Fix: Set Security Layer to SSL (TLS) or Negotiate and disable Standard RDP Security.
[-] 10.150.2.150:3389 has issue FIPS_SUPPORTED_BUT_NOT_MANDATED
The server supports FIPS-compliant encryption but does not require it.
Fix: Enable FIPS via Group Policy if FIPS compliance is required in your environment.
| Issue | Severity | Description |
|---|---|---|
NLA_NOT_SUPPORTED_DOS |
High | NLA is not supported at all; unauthenticated resource exhaustion (DoS) is possible. |
NLA_SUPPORTED_BUT_NOT_MANDATED_DOS |
Medium | NLA is available but not enforced, allowing pre-auth DoS. |
ONLY_RDP_SUPPORTED_MITM |
High | Only legacy Standard RDP Security is available — susceptible to MitM attacks. |
SSL_SUPPORTED_BUT_NOT_MANDATED_MITM |
Medium | TLS is available but not required; server still accepts insecure RDP Security. |
FIPS_SUPPORTED_BUT_NOT_MANDATED |
Low/Info | FIPS encryption is offered but not mandated. |
WEAK_RDP_ENCRYPTION_SUPPORTED |
Medium | Server supports 40-bit or 56-bit weak encryption. |
WEAK_RDP_ENCRYPTION_SUPPORTED_MITM |
High | Only weak encryption is available and no TLS, enabling MitM + weak crypto. |
GNU General Public License v2 — see source file for full license text.
- Original Perl tool: https://github.com/CiscoCXSecurity/rdp-sec-check
- Python port: https://github.com/sectroyer/rdp-sec-check-py
- Portcullis Labs write-up: https://labs.portcullis.co.uk/tools/rdp-sec-check/