Skip to content

sectroyer/rdp-sec-check-py

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 

Repository files navigation

rdp-sec-check-py

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.

Key features

  • 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

Overview

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

Requirements

Python 3.6 or newer. No third-party packages required.

python3 rdp-sec-check.py --help

Usage

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]

Options

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.

SOCKS proxy (--socks)

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.

Examples

Scan a single host

$ python3 rdp-sec-check.py 192.168.1.1

Scan a single host on a non-standard port

$ python3 rdp-sec-check.py 192.168.1.1:3390

Scan from a file with logging

$ python3 rdp-sec-check.py --file hosts.txt --outfile rdp.log

Scan with custom timeout and retries

$ python3 rdp-sec-check.py --timeout 15 --retries 3 192.168.1.1

Scan through a SOCKS5 proxy (no auth)

$ python3 rdp-sec-check.py --socks 127.0.0.1:1080 192.168.1.1

Scan through an authenticated SOCKS5 proxy

$ python3 rdp-sec-check.py --socks socks5://user:pass@10.0.0.1:1080 --file hosts.txt

Scan through a SOCKS4a proxy (remote DNS)

$ python3 rdp-sec-check.py --socks socks4a://proxy.example.com:1080 192.168.1.1

Example output: A well-configured Windows 2008 RDP service

$ 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

Example output: A misconfigured host (issues with descriptions)

$ 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.

Security issues reference

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.

License

GNU General Public License v2 — see source file for full license text.

References

About

Modern python reimplementation of rdp-sec-check

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages