Safeguard
Supply Chain Security•

RDP and VNC Explained: How Remote Desktop Works and How to Secure It

RDP and VNC let you see and control a remote desktop. Learn how each works on the wire, where they are weak, and how to lock down NLA, TLS and exposure.

Safeguard Security Team
42 min read

RDP (Remote Desktop Protocol) and VNC are the two protocols most people use to see and control another computer's desktop over a network. RDP is Microsoft's protocol, specified in the MS-RDPBCGR open specification and listening on TCP port 3389 by default; VNC runs the Remote Framebuffer protocol (RFB, RFC 6143) on TCP port 5900. Both are safe enough only when you put authentication in front of the session, encrypt it, and keep the listener off the open internet.

The two were built on very different ideas. RDP is a rich, stateful protocol that negotiates capabilities, sends drawing instructions and carries side channels for drives, printers, clipboard and audio. RFB ships rectangles of pixels and sends back keystrokes, and its own specification says it offers no protection against anyone watching or tampering with the stream. This post covers both on the wire, how they authenticate, the weakness classes that keep showing up, and the official commands to check your own machines.

Key takeaways

  • RDP is specified by Microsoft in [MS-RDPBCGR] (Basic Connectivity and Graphics Remoting). The current published revision is 62.0, dated 9 March 2026. IANA registers port 3389 for both TCP and UDP under the service name ms-wbt-server.
  • VNC uses the Remote Framebuffer protocol, documented in RFC 6143 (March 2011, Informational). IANA registers port 5900 for the service name rfb. RFB has three published versions: 3.3, 3.7 and 3.8.
  • RDP's security has three generations: the original Standard RDP Security (RC4 encryption with an MD5 and SHA-1 based MAC), Enhanced RDP Security over TLS, and CredSSP, which is what makes Network Level Authentication (NLA) possible.
  • NLA authenticates the user before the server builds a desktop session. CISA's 2019 BlueKeep alert (AA19-168A) called enabling NLA an effective mitigation for that pre-authentication flaw, because exploitation needed an unauthenticated session.
  • VNC Authentication is weak by design. RFC 6143 says the DES based challenge and response is "known to be cryptographically weak" and recommends running sessions over IPsec or SSH.
  • Neither protocol belongs directly on the internet. Put RDP behind a gateway or VPN, keep VNC bound to localhost and reach it through an SSH tunnel, and turn off clipboard and drive redirection you do not need.

What RDP and VNC are for, the layer and the standards

Both protocols solve the same problem: a person sits at one machine and wants to use the graphical desktop of another as if they were in front of it. Both run at the application layer over TCP, and both are client and server protocols where the machine being controlled is the server.

RDP and MS-RDPBCGR

Microsoft describes RDP as a protocol "designed to facilitate user interaction with a remote computer system by transferring graphics display information from the remote computer to the user and transporting input commands from the user to the remote computer, where the input commands are replayed on the remote computer." The same overview adds that RDP also provides "an extensible transport mechanism" so that components on the client and server can talk to each other inside the session. That extensibility is the virtual channel system, and it is central to both RDP's usefulness and its attack surface.

The defining document is [MS-RDPBCGR]: Remote Desktop Protocol: Basic Connectivity and Graphics Remoting, published in the Microsoft Open Specifications library. It is a vendor specification, not an IETF standard, and Microsoft revises it often. The page lists revision 62.0 published on 9 March 2026, and revision 61.0 from 7 April 2025 before it. Many related documents extend it, including MS-CSSP for credential delegation, MS-RDPELE for licensing and MS-RDPEMT for multitransport over UDP.

RDP is built on older ITU-T conferencing standards: X.224 connection and data PDUs, Multipoint Communication Service (MCS) channels and Generic Conference Control (GCC) settings blocks, which is why its early handshake looks so layered.

Ports come from the IANA Service Name and Transport Protocol Port Number Registry: ms-wbt-server is registered on 3389 for both TCP and UDP. Microsoft Learn confirms that Remote Desktop listens on port 3389 by default and that the port number lives in the registry, where an administrator can change it.

VNC and RFC 6143

RFC 6143, "The Remote Framebuffer Protocol," was published in March 2011 by T. Richardson and J. Levine. It is an Informational RFC, not a standards track document, and it does not obsolete or update any earlier RFC. Its purpose is to describe the protocol "as actually implemented," so that new implementations can interoperate with old ones. The RFC states plainly that "RFB is the protocol used in VNC."

RFB works at the framebuffer level, so it can serve X11, Windows or macOS alike. The RFC calls it a "thin client" protocol, and the client is stateless: reconnect from any viewer and the desktop is where you left it.

IANA registers rfb on port 5900 for TCP and UDP, with RFC 6143 as the reference. RFC 6143 adds that a host running several RFB servers typically puts server N on port 5900 plus N, that some servers offer a small HTTP server on port 5800 for a browser based viewer, and that in "reverse" connections the viewer listens on port 5500 and the server dials out. It also warns that 5900 is the only port IANA assigned for RFB.

How the two designs differ

The core design difference is what crosses the wire.

AspectRDP (MS-RDPBCGR)VNC (RFB, RFC 6143)
Owner and documentMicrosoft Open Specifications, revised frequentlyIETF Informational RFC 6143, March 2011
Default portTCP 3389, plus UDP 3389 for multitransportTCP 5900 (5900 plus N for display N)
What the server sendsDrawing orders, bitmaps, cached glyphs, pointer updates, negotiated by capability setsRectangles of pixels in a chosen encoding, only when the client asks
Session modelA logon session per user; the server can host manyShares one existing framebuffer; any viewer sees the same screen
Side channelsUp to 31 static virtual channels plus dynamic channels for clipboard, drives, printers, audio, smart cardsClipboard text only in the base protocol
Built in securityNegotiated: Standard RDP Security, TLS, CredSSP (NLA), RDSTLS, RDS AAD AuthNone, or a DES based password check; stronger types are extensions
Authentication timingWith NLA, before the server creates a sessionAfter the TCP connection, inside the RFB handshake

RDP's client and server agree on drawing primitives, caches and colour depths, and the server sends instructions the client renders. RFB is built around a single primitive, "put a rectangle of pixel data at a given x,y position," and its updates are "demand-driven by the client": the server sends nothing until asked, so a slow client simply asks less often.

How RDP works on the wire

The RDP connection sequence, phase by phase

MS-RDPBCGR section 1.3.1.1 breaks a connection into ten phases. Almost every message is strictly sequential.

  1. Connection Initiation. The client sends a Class 0 X.224 Connection Request PDU. Attached to it is an RDP Negotiation Request listing the security protocols the client supports. The server answers with an X.224 Connection Confirm carrying its choice, or a Negotiation Failure.
  2. Basic Settings Exchange. The client sends an MCS Connect Initial PDU containing a GCC Conference Create Request, and the server replies with an MCS Connect Response. These carry concatenated blocks of settings such as core data, security data and network data, including the list of requested virtual channels.
  3. Channel Connection. The client sends MCS Erect Domain Request and Attach User Request PDUs, receives a User Channel ID, then joins the user channel, the I/O channel and every static virtual channel with Channel Join Requests.
  4. RDP Security Commencement. Only under Standard RDP Security: the client sends a Security Exchange PDU containing a 32 byte random number encrypted with the server's public key. Both sides derive session keys from the two random values.
  5. Secure Settings Exchange. The client sends the Client Info PDU, which can carry the username, password and an auto reconnect cookie.
  6. Optional Connect Time Auto Detection. The two sides measure round trip time and bandwidth.
  7. Licensing. The server and client exchange licensing PDUs, specified in MS-RDPELE.
  8. Optional Multitransport Bootstrapping. The server can start side connections over RDP-UDP, TLS and DTLS as described in MS-RDPEMT.
  9. Capabilities Exchange. The server sends a Demand Active PDU listing its capabilities; the client answers with Confirm Active.
  10. Connection Finalization. Synchronize, Control (Cooperate and Request or Granted Control), optional Persistent Key List, and Font List and Font Map PDUs close out the setup. After the Font List arrives, the server can start sending graphics.

Here is the same flow as a sequence, with the security enhanced path (TLS or CredSSP) that modern deployments use:

Client                                            Server (TCP 3389)
  | X.224 Connection Request + RDP_NEG_REQ           |
  |   requestedProtocols = SSL | HYBRID | HYBRID_EX   |
  |------------------------------------------------->|
  |        X.224 Connection Confirm + RDP_NEG_RSP     |
  |        selectedProtocol = HYBRID_EX              |
  |<-------------------------------------------------|
  | TLS handshake (server certificate)               |
  |<================================================>|
  | CredSSP inside TLS: SPNEGO (Kerberos or NTLM),   |
  | public key binding, then delegated credentials   |
  |<================================================>|
  |        Early User Authorization Result PDU        |
  |<-------------------------------------------------|
  | MCS Connect Initial (GCC: core, security, net)   |
  |   client core data replays serverSelectedProtocol|
  |------------------------------------------------->|
  |        MCS Connect Response (replays requested)   |
  |<-------------------------------------------------|
  | Erect Domain, Attach User, Channel Joins          |
  |<------------------------------------------------>|
  | Client Info PDU                                   |
  |------------------------------------------------->|
  |        Licensing, Demand Active                   |
  |<-------------------------------------------------|
  | Confirm Active, Synchronize, Control, Font List   |
  |------------------------------------------------->|
  |        Synchronize, Control, Font Map, graphics   |
  |<-------------------------------------------------|

Teardown is covered in section 1.3.1.4, which describes separate disconnection sequences for a user disconnecting on the client, a user ending the session on the server, and an administrator ending it on the server. Section 1.3.1.5 adds automatic reconnection, which uses the auto reconnect cookie that the server issued earlier.

The negotiation request, field by field

The RDP Negotiation Request (RDP_NEG_REQ, MS-RDPBCGR section 2.2.1.1.1) is the first security decision in every connection, so it is worth reading closely. It is 8 bytes long.

FieldSizeMeaning
type1 byteMust be 0x01 (TYPE_RDP_NEG_REQ)
flags1 byte0x01 RESTRICTED_ADMIN_MODE_REQUIRED; 0x02 REDIRECTED_AUTHENTICATION_MODE_REQUIRED (Remote Credential Guard); 0x08 CORRELATION_INFO_PRESENT
length2 bytesMust be 0x0008
requestedProtocols4 bytesBit flags for the security protocols the client supports

The requestedProtocols values are where the security layers show up:

FlagValueSecurity protocol
PROTOCOL_RDP0x00000000Standard RDP Security (section 5.3)
PROTOCOL_SSL0x00000001TLS (section 5.4.5.1)
PROTOCOL_HYBRID0x00000002CredSSP; the SSL flag should also be set because TLS is a subset of CredSSP
PROTOCOL_RDSTLS0x00000004RDSTLS (section 5.4.5.3)
PROTOCOL_HYBRID_EX0x00000008CredSSP plus the Early User Authorization Result PDU
PROTOCOL_RDSAAD0x00000010RDS AAD Auth Security (section 5.4.5.4)

Notice that PROTOCOL_RDP is zero. A client that sets no bits is asking for the oldest, weakest layer. The negotiation itself travels in the clear, before any encryption exists. MS-RDPBCGR section 5.4.2.1 handles that by having both sides replay the negotiation after the secure channel is up: the client repeats the server's chosen protocol in its Client Core Data, and the server repeats the client's requested protocols in its Server Core Data, "This step ensures that no tampering has taken place." That replay is the protocol's built in defence against someone on the path rewriting the request to force a weaker layer.

Virtual channels: where RDP's features and risks live

Static virtual channels, described in MS-RDPBCGR section 1.3.3, "allow lossless communication between client and server components over the main RDP data connection." The data is "application-specific and opaque to RDP," and a maximum of 31 static virtual channels can be created at connection time. The list is requested during the Basic Settings Exchange and joined during Channel Connection. Each channel is an independent stream, chunked according to the Virtual Channel Capability Set.

This is how RDP carries clipboard, drive mapping, printers, audio and smart cards. Every channel is a path for data between two machines that may sit in different trust zones, which is useful for work and equally useful to a compromised server or client.

RDP versions and the client core data

RDP has gone through many client versions. The Client Core Data structure (TS_UD_CS_CORE, section 2.2.1.3.2) carries a 32 bit version field, and the specification lists the values: 0x00080001 for RDP 4.0 clients, 0x00080004 for RDP 5.0 through 8.1 clients, then one value per release from 0x00080005 (RDP 10.0) to 0x00080011 (RDP 10.12). Section 1.7 warns that this field "does not accurately reflect the version of RDP being used" by 5.0 through 8.1 clients, because they all advertise minor version 4, and that the client build number is implementation dependent. In other words, you cannot reliably fingerprint a client's security posture from its advertised version; you have to look at which security protocols it negotiates.

How VNC (RFB) works on the wire

The RFB handshake

RFC 6143 section 7.1 defines a short handshake in three parts, followed by initialisation. The server speaks first.

Viewer (client)                                   VNC server (TCP 5900)
  |                ProtocolVersion "RFB 003.008\n"  |
  |<-------------------------------------------------|
  | ProtocolVersion "RFB 003.008\n"                  |
  |------------------------------------------------->|
  |        number-of-security-types, list (e.g. 1,2) |
  |<-------------------------------------------------|
  | chosen security-type (1 byte)                    |
  |------------------------------------------------->|
  |   (type 2 only) 16 byte random challenge          |
  |<-------------------------------------------------|
  | (type 2 only) 16 byte DES response               |
  |------------------------------------------------->|
  |                SecurityResult: 0 OK or 1 failed   |
  |<-------------------------------------------------|
  | ClientInit: shared-flag                           |
  |------------------------------------------------->|
  |  ServerInit: width, height, pixel format, name    |
  |<-------------------------------------------------|
  | SetPixelFormat, SetEncodings,                     |
  | FramebufferUpdateRequest, KeyEvent, PointerEvent  |
  |------------------------------------------------->|
  |  FramebufferUpdate (rectangles), Bell, CutText    |
  |<-------------------------------------------------|

The ProtocolVersion message is 12 ASCII bytes, "RFB 003.008" plus a newline; the client must not request a higher version than the server offers. In 3.8 the server lists its security types and the client picks one byte; a count of zero means failure with a reason string. SecurityResult is a 32 bit status, 0 for OK and 1 for failed. ClientInit carries a shared flag (keep other viewers connected or take exclusive control), and ServerInit returns the framebuffer size, pixel format and desktop name.

After that, the protocol is asynchronous. RFC 6143 lists six client to server message types (SetPixelFormat 0, SetEncodings 2, FramebufferUpdateRequest 3, KeyEvent 4, PointerEvent 5, ClientCutText 6) and four server to client types (FramebufferUpdate 0, SetColorMapEntries 1, Bell 2, ServerCutText 3).

Security types

RFC 6143 defines only three values: 0 Invalid, 1 None and 2 VNC Authentication. Its IANA section creates the "Remote Framebuffer Security Types" registry and records historic assignments beyond those three, including 18 TLS and 19 VeNCrypt, plus ranges held by individual implementations. The RFC notes that "other security types exist but are not publicly documented," and that after the security phase, communication may continue "over an encrypted or otherwise altered channel" if both ends agree on an extended type.

VNC Authentication works like this, per section 7.2.2: the server sends a random 16 byte challenge, and the client encrypts it with DES using the user's password as the key. The password is truncated to eight characters or padded with null bytes. The client sends back the 16 byte result. The RFC itself says this "is known to be cryptographically weak and is not intended for use on untrusted networks."

FramebufferUpdate layout

The main server message is simple. A FramebufferUpdate has a 4 byte header and then a run of rectangles:

BytesTypeField
1U8 [0]message-type
1paddingpadding
2U16number-of-rectangles
2U16x-position (per rectangle)
2U16y-position
2U16width
2U16height
4S32encoding-type

Encodings include Raw, CopyRect, RRE, Hextile, TRLE and ZRLE, and pseudo encodings such as Cursor and DesktopSize let a client announce support for extensions. A server simply ignores encodings it does not understand, which is how RFB has grown without bumping its version number.

Versions and history

RDP security layers: three generations

Standard RDP Security (MS-RDPBCGR section 5.3) is the original, built in scheme. The server sends a proprietary or X.509 certificate and a 32 byte random value; the client encrypts its own random with the server's public key; both derive session keys. Section 5.3.6.1 describes the non FIPS data path: a MAC built from SHA-1 and MD5 is computed over the plaintext, truncated to 8 bytes, and the data is encrypted with RC4. A FIPS mode uses different algorithms. Standard RDP Security supports four encryption levels configured on the server: Low, Client Compatible, High and FIPS Compliant. At Low, only client to server data is encrypted; server to client traffic, which includes everything drawn on screen, is not. Microsoft's own policy documentation for the encryption level setting says that "native RDP encryption (as opposed to SSL encryption) isn't recommended."

Enhanced RDP Security (section 5.4) hands all encryption, integrity checking and server authentication to an external security protocol. The specification lists TLS 1.0, 1.1, 1.2 and 1.3, CredSSP, RDSTLS and RDS AAD Auth. Section 5.4.5.1 says TLS "was added to RDP to enable authentication of the remote computer's identity, hence mitigating man-in-the-middle attacks on RDP traffic." The section states the benefit directly: developers no longer need to "manually implement protocol security mechanisms" and can rely on proven libraries.

CredSSP and NLA. Section 5.4 continues: "Another key benefit of Enhanced RDP Security is that it enables the use of Network Level Authentication (NLA) when using CredSSP as the External Security Protocol." That is the third generation, and it is the one to require today.

Two later additions matter for modern environments. RDSTLS is used in server redirection scenarios inside Remote Desktop Services farms, and RDS AAD Auth lets a client authenticate to a Microsoft Entra ID joined host. The negotiation flags for Restricted Admin mode and Remote Credential Guard were also added to the request so that a client can insist on credential free logon.

What CredSSP and NLA actually do

MS-CSSP (current revision 21.0, 23 April 2024) describes CredSSP as a protocol that "enables an application to securely delegate a user's credentials from a client to a target server." The flow, from the MS-CSSP overview:

  1. CredSSP first runs a TLS handshake. The client is anonymous at this point.
  2. Inside TLS, it uses SPNEGO to mutually authenticate client and server with Kerberos or NTLM.
  3. It binds the two layers: the client encrypts a hash of the server's TLS public key with the SPNEGO session key, and the server proves it saw the same key. This defeats a relay that terminates TLS in the middle.
  4. Finally the client sends the user's credentials, encrypted under the SPNEGO key.

MS-RDPBCGR section 5.4.5.2 calls it "essentially the amalgamation of TLS with Kerberos and NT LAN Manager (NTLM)." If you want a refresher on the Kerberos part, our post on how Kerberos authentication works covers RFC 4120.

Network Level Authentication is the user facing name for this. Microsoft Learn says it requires "that the user be authenticated to the RD Session Host server before a session is created," which uses fewer server resources and reduces denial of service risk. It needs Remote Desktop Connection 6.0 or later on the client.

The MS-CSSP security considerations add an important nuance. CredSSP's purpose is "to delegate a user's clear text password or pin" to the server, so "it is important to make certain that the server receiving the credentials does not fall under an attacker's control." Authentication of the server is not the same as trusting it with your password. The section also says "a major revision has been applied to the protocol in version 5 for improved security" and that implementers should "support version 5 or higher only."

RFB 3.3 to 3.8

RFC 6143 section 6 says RFB "has evolved through three published versions: 3.3, 3.7, and 3.8," with 3.8 as the version the RFC primarily documents. Appendix A explains that all the differences are in the handshake; once ClientInit and ServerInit are exchanged, the three are identical.

  • 3.3: the server alone decides the security type and sends it as a 32 bit word. Only values 0, 1 or 2 are allowed. With type 1 (None), the server skips SecurityResult. If VNC Authentication fails, the server sends no reason string before closing.
  • 3.7: introduces the two way negotiation where the server lists types and the client picks, but with type None the server still skips SecurityResult.
  • 3.8: always sends SecurityResult and always includes a reason string on failure.

Because private extensions once shipped under made up versions, the RFC says "any unknown 3.x version" must be treated as 3.3, and that "future evolution of RFB will use 4.x version numbers." The 3.3 fallback matters for security because it lets the server dictate a weak security type without negotiation.

Security properties and weakness classes, as concepts

What each protocol guarantees

PropertyRDP with NLA (CredSSP over TLS)RDP with Standard RDP SecurityVNC with VNC AuthenticationVNC over SSH or TLS
ConfidentialityYes, TLSRC4, and at Low level server to client is unencryptedNone; RFC 6143 says no protection against observationYes, from the tunnel or TLS type
IntegrityYes, TLSTruncated MAC over RC4NoneYes
Server authenticationTLS certificate, plus Kerberos mutual auth where usedServer key, weakly validatedNoneSSH host key or TLS certificate
User authentication timingBefore a session or logon screen existsAfter the session startsInside the handshake, password onlyTunnel login first, then VNC
Replay protectionFrom TLSLimitedFresh challenge per connection, but weak cipherFrom the tunnel

RFC 6143 section 9 is short and blunt: RFB "provides no security beyond the optional and cryptographically weak password check" and "provides no protection against observation of or tampering with the data stream. It has typically been used on secure physical or virtual networks."

Internet exposed listeners

The most common failure is not a protocol flaw at all: a listener on 3389 or 5900 reachable from anywhere. Any service that accepts unauthenticated connections exposes the code that parses those first messages. For RDP without NLA, that includes everything up to the logon screen. For VNC, it includes the RFB handshake and, if a server offers type None, the desktop itself.

BlueKeep shows why this matters. CVE-2019-0708, published on 16 May 2019, is described in its CVE record as a remote code execution flaw in Remote Desktop Services that an unauthenticated attacker can trigger by connecting over RDP. CISA's alert AA19-168A (17 June 2019) noted that exploitation "must occur before authentication" and called the flaw "wormable." Its mitigations included patching, upgrading end of life systems, enabling NLA because exploitation "requires an unauthenticated session," and blocking TCP 3389 at the perimeter, while warning that blocking the port does not stop unauthenticated sessions from inside the network. The lesson generalises: pre authentication code is the most exposed code in any remote access stack, and NLA plus network restriction shrinks it.

Our post on reviewing security groups that open SSH and RDP to the world covers the cloud side of finding these listeners.

Brute force and password spraying

An exposed RDP listener with NLA still accepts password attempts, each of which reaches your authentication service. VNC is weaker: at most eight password characters and no username. TigerVNC's Xvnc documents a UseBlacklist setting, on by default, that temporarily rejects a host after BlacklistThreshold (default 5) failures, but that is an implementation feature, not part of RFB.

Credential exposure and relay

CredSSP sends the user's real credentials to the server so that the server can log the user on and act as them. That gives single sign on inside the session, and it also means that a compromised server receives a reusable credential. Microsoft's Remote Credential Guard documentation lists the consequences of a plain Remote Desktop session: credentials are "sent to and stored on the remote host," they "aren't protected from attackers on the remote host," and an attacker "can use credentials after disconnection."

The two mitigations differ:

OptionCredentials sent to hostSingle sign on to other systemsPass the hash protectionAccess granted by
Standard Remote DesktopYesYesNoRemote Desktop Users group
Remote Credential GuardNo; Kerberos requests are redirected back to the clientYes, during the sessionYesRemote Desktop Users group
Restricted Admin modeNo; the session uses the host's own identityNoYesAdministrators group on the host

Remote Credential Guard supports Kerberos only and, per Microsoft Learn, does not allow fallback to NTLM "because it would expose credentials to risk." Both modes depend on the remote host allowing delegation of nonexportable credentials.

Relay is the related concept: if a client will authenticate to whatever answers on the other end, an attacker in the middle can try to forward that authentication somewhere else. CredSSP's public key binding is designed to stop relaying the RDP authentication across a man in the middle TLS session. It only helps if the client actually validates the server certificate or uses Kerberos with a real service identity. A client that clicks through certificate warnings, or a server still presenting the default self signed certificate (Win32_TSGeneralSetting reports this as SSLCertificateSHA1HashType 1, "Default self-signed"), undermines it.

Downgrade

RDP negotiates its security layer in the clear, and PROTOCOL_RDP is the all zeros value. If a server still accepts Standard RDP Security and a client still offers it, a path attacker has a reason to try to make both sides settle on the weakest option. The replay of negotiation values inside the secure channel is the specified defence, and the operational defence is simpler: configure the server to refuse anything except NLA, so there is nothing weaker to fall back to.

RFB has the same shape at the protocol level. Under 3.8 the server lists its supported types and the client picks one, so a server that lists None or VNC Authentication alongside a TLS type gives both an attacker and a careless client the option of the weak one. Under 3.3, the server dictates. The fix is to offer only strong types on the server.

Clipboard and drive redirection

Redirection channels are a design feature, but they turn a remote desktop into a two way data path. Microsoft's policy documentation confirms that, by default, "an RD Session Host server maps client drives automatically upon connection," and that if clipboard restriction is not configured, "users can copy arbitrary contents from client to server if clipboard redirection is enabled." In a jump host or privileged access workstation design, that path can carry files and secrets across a boundary you meant to keep closed, in either direction. A compromised server can read a mapped client drive; a compromised client can paste into a privileged session.

VNC has a smaller version of the same issue: ClientCutText and ServerCutText synchronise text clipboards, and implementations add their own controls. TigerVNC's Xvnc, for example, documents AcceptCutText and SendCutText (both on by default) and MaxCutText, which limits clipboard updates to 262144 bytes by default.

Weak VNC authentication and no transport security

This is a design property, not a bug. With DES, an eight character key, no server authentication and no session encryption, anyone on the path can watch the screen and keystrokes, and a captured challenge and response allows offline password guessing. RFC 6143's answer is IPsec, SSH or an extended security type that encrypts the stream.

Implementation bugs

Both protocols parse complex attacker supplied data (capability sets, channel PDUs, bitmap codecs, pixel encodings), and clients are exposed too, because a malicious server sends the graphics the client decodes. Track RDP and VNC libraries embedded in your products, such as open source FreeRDP or LibVNCServer, like any other parser dependency.

Secure configuration, with defender side check commands

Only run these commands against systems you own or are authorised to administer or test. Every command below comes from the official documentation cited with it.

1. Find out whether RDP is listening, and on which port

Microsoft Learn gives the PowerShell command to read the configured listening port from the registry (Change Remote Desktop listening port):

Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -name 'PortNumber'

Then confirm what is actually listening with Get-NetTCPConnection, whose documented parameters include -LocalPort and -State, with Listen among the accepted state values (Get-NetTCPConnection):

Get-NetTCPConnection -LocalPort 3389 -State Listen

Microsoft documents how to change the port, but a moved listener is found by any scanner. Treat the port as inventory, not protection.

2. Check NLA, the security layer and the certificate

The Win32_TSGeneralSetting WMI class in the Root\CIMv2\TerminalServices namespace exposes the settings for each RDP listener, including UserAuthenticationRequired (1 means NLA is enforced), SecurityLayer, MinEncryptionLevel, SSLCertificateSHA1HashType and the PolicySource properties that tell you whether a value came from the server, from Group Policy or from the default (Win32_TSGeneralSetting class). Query it with Get-CimInstance, using its documented -Namespace, -ClassName and -Filter parameters (Get-CimInstance):

Get-CimInstance -Namespace root/CIMV2/TerminalServices -ClassName Win32_TSGeneralSetting -Filter "TerminalName='RDP-Tcp'" |
  Select-Object TerminalName, UserAuthenticationRequired, SecurityLayer, MinEncryptionLevel, SSLCertificateSHA1HashType, PolicySourceUserAuthenticationRequired, PolicySourceSecurityLayer

What to look for:

  • UserAuthenticationRequired should be 1.
  • SecurityLayer should not be the native "RDP Security Layer." Note that the Microsoft page lists different numeric values for this setting in its method and property sections, so read the value alongside the page and your Group Policy rather than from memory.
  • SSLCertificateSHA1HashType of 1 means the listener is using the default self signed certificate. Values 2 (Group Policy enforced) or 3 (custom) mean someone has deployed a certificate clients can validate.
  • PolicySource values of 1 mean Group Policy is setting the value, so changes must be made in policy, not locally.

3. Enforce NLA and modern security through Group Policy

Microsoft Learn names the policy path for NLA: Computer Configuration, Administrative Templates, Windows Components, Remote Desktop Services, Remote Desktop Session Host, Security, "Require user authentication for remote connections by using Network Level Authentication." Enable it so the setting cannot drift on individual servers.

In the same Security folder, the Remote Desktop Services policy set includes "Require secure RPC communication," which makes the RPC interface used to administer Remote Desktop Services accept only authenticated and encrypted requests. The client connection encryption level policy only affects native RDP encryption; Microsoft's documentation states that native RDP encryption "isn't recommended," so the right goal is to not use it at all rather than to tune it.

4. Turn off redirection you do not need

Under Remote Desktop Session Host, Device and Resource Redirection, Microsoft documents:

  • Do not allow drive redirection. When enabled, client drive redirection is blocked, and so is clipboard file copy redirection on the Windows versions the page lists.
  • Restrict clipboard transfer from client to server and Restrict clipboard transfer from server to client. These let you block transfers entirely or allow only plain text, text and images, and so on. If both computer and user policies are set, the stricter one applies.

For jump hosts and administrative servers, the safe default is no drive redirection and plain text clipboard at most, with exceptions granted per group.

5. Protect credentials on administrative connections

On the remote hosts, enable "Remote host allows delegation of nonexportable credentials" under Computer Configuration, Administrative Templates, System, Credentials Delegation. Microsoft Learn also documents the equivalent registry value, which you can set from an elevated prompt:

reg.exe add HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v DisableRestrictedAdmin /d 0 /t REG_DWORD

Then connect with Remote Credential Guard from the client:

mstsc.exe /remoteGuard

Or enforce it on clients through the Credentials Delegation policy that Microsoft describes on the same page. Remember the requirements: Kerberos only, no NTLM fallback, and the Remote Desktop Windows application rather than the UWP app.

6. Put RDP behind a gateway, not on the internet

Microsoft's Remote Desktop Services roles documentation describes RD Gateway as granting "users on public networks access to Windows desktops and applications," over HTTPS on TCP 443 and UDP 3391, with a certificate whose name matches the gateway's FQDN; a released service "requires a certificate from a trusted certification authority." That gives you one hardened, logged entry point instead of many hosts listening on 3389. For a single PC, Microsoft Learn suggests a VPN or port forwarding; prefer the VPN.

7. Keep VNC on localhost and reach it through SSH

RFC 6143 recommends IPsec or SSH. With TigerVNC's Xvnc, the documented options are (Xvnc):

  • -localhost: "Only allow connections from the same machine. Useful if you use SSH and want to stop non-SSH connections."
  • -interface: listen on a specific address rather than all interfaces, which is the default.
  • -SecurityTypes: choose the allowed schemes. The documented default is TLSVnc,VncAuth, so the weak plain VNC Authentication is still offered unless you remove it. Valid values include X509 variants that authenticate the server with a certificate.
  • -rfbport: the listening port, which defaults to 5900 plus the display number.

Then connect through an SSH local forward. The OpenSSH ssh(1) manual documents -L [bind_address:]port:host:hostport, which listens locally and forwards each connection "over the secure channel" to the given host and port on the remote side (ssh(1)):

ssh -L 5901:localhost:5901 admin@vnc-host.example.internal

Point the viewer at localhost port 5901 on your own machine. The VNC server never accepts a connection from the network, and the session inherits SSH's encryption, integrity and host key authentication.

8. Confirm what is listening on Linux and macOS hosts

On Linux, the ss(8) manual documents -t (TCP), -l (listening sockets only), -n (numeric, no name resolution) and -p (show processes) (ss(8)):

ss -tlnp

A VNC server bound to localhost shows a local address of 127.0.0.1 or ::1 on port 5900 or 5901. One bound to 0.0.0.0 or an external address is reachable from the network, whatever your intentions were.

9. Log and patch

Patch remote desktop servers and clients like any internet facing service, keep end of life Windows off reachable networks, and track VNC server packages like any other dependency.

When to use RDP, VNC, SSH or a gateway

NeedBest fitSecurity propertiesOperational cost
Full Windows desktop or RemoteApp for staffRDP with NLA, behind RD Gateway or a VPNTLS plus Kerberos or NTLM inside CredSSP; gateway on 443 with a trusted certificateGateway and certificate management; Group Policy baseline
Administrator access to Windows serversRDP with Remote Credential Guard or Restricted Admin, from a hardened admin workstation, through a gatewayCredentials not left on the target; redirection disabledKerberos must work end to end; separate admin workstations
Shared view of an existing screen (support, lab equipment, a Linux desktop)VNC bound to localhost, tunnelled over SSH, or with an X509 TLS security typeEncryption and server authentication come from SSH or TLS, not from RFBSSH keys or certificates to manage; viewer and server must agree on types
Command line administration of Linux or network devicesSSHEncrypted, integrity protected, host key authentication, key based usersLowest; no graphical stack needed
Many users across many hosts, with audit and conditional accessA gateway or broker in front of RDP and SSHOne authenticated, logged entry point; hosts not exposedHighest; worth it at scale
Quick look at a home or lab machineVPN to the network, then RDP or tunnelled VNCSame as above, without exposing a listenerLow once the VPN exists

The pattern: the remote desktop protocol should never be the first thing an unknown internet client talks to; a gateway, VPN or SSH sits in front. For the transport level view of what anyone on the path can still see, our post on what an eavesdropper can see in TCP and UDP is a useful companion, and what TLS is explains the layer that RDP's enhanced security relies on.

Common mistakes

  • Treating a non standard port as protection. Moving RDP off 3389 changes nothing about who can reach it. Scanners check all ports.
  • Leaving NLA off for one legacy client. Microsoft Learn allows disabling it "temporarily"; such exceptions tend to stay. Upgrade the client.
  • Assuming NLA means no credential exposure. NLA authenticates before the session. CredSSP still delegates the user's credentials to the host unless Remote Credential Guard or Restricted Admin is used.
  • Leaving drive and clipboard redirection on for admin sessions. On jump hosts that is a data path across your most important boundary.
  • Enabling VNC with a password and calling it secure. VNC Authentication protects nothing on the wire. The RFC says so.
  • Binding VNC to all interfaces. Many servers default to listening everywhere. Bind to localhost and tunnel.
  • Offering weak RFB security types alongside strong ones. A default list that includes plain VNC Authentication means a client can still pick it.
  • Forgetting UDP. RDP can use UDP 3389 for multitransport, and RD Gateway uses UDP 3391. Firewall reviews that only look at TCP miss half the picture.

FAQ

What port does RDP use?

RDP listens on TCP port 3389 by default, and can also use UDP 3389 for its multitransport connections. IANA registers 3389 for both TCP and UDP under the name ms-wbt-server. RD Gateway uses TCP 443 and UDP 3391.

What port does VNC use?

VNC's RFB protocol uses TCP port 5900, which is the only port IANA assigned to it. A host running several servers typically uses 5900 plus the display number, some servers offer a browser viewer on 5800, and reverse connections use 5500 on the viewer side.

Is RDP encrypted?

Yes, but how depends on the security layer. With NLA, traffic runs inside TLS. The legacy Standard RDP Security layer uses RC4, and at its Low level does not encrypt server to client traffic at all. Configure servers to require NLA so the legacy layer is never used.

Is VNC encrypted?

Not by itself. RFC 6143 says the base protocol provides no protection against observation or tampering. Encryption comes from an extended security type such as a TLS based one, or from running VNC inside SSH or IPsec.

What is Network Level Authentication?

NLA requires the user to authenticate before the Remote Desktop server creates a session or shows a logon screen. It is built on CredSSP, which runs Kerberos or NTLM inside TLS. It needs Remote Desktop Connection 6.0 or later.

RDP vs VNC: which is more secure?

Configured well, RDP has more built in security: TLS, NLA, Kerberos and credential protection modes. VNC's base protocol has almost none and depends on a tunnel or extension. But an exposed, unpatched RDP server is riskier than a VNC server bound to localhost behind SSH. Configuration decides.

Should RDP be exposed to the internet?

No. Put it behind RD Gateway or a VPN. CISA's BlueKeep alert recommended blocking TCP 3389 at the enterprise perimeter and enabling NLA, because pre authentication flaws are reachable by anyone who can connect.

RDP vs SSH: when should I use which?

Use SSH for command line administration and for tunnelling other protocols. Use RDP when you need a full graphical Windows session. They work together: SSH or a gateway in front, RDP behind it.

Where Safeguard fits

Safeguard does not inspect, filter or block RDP or VNC traffic, does not configure Group Policy, and is not a gateway, VPN or firewall. Nothing in the hardening steps above depends on it.

The honest connection is the software: RDP client libraries, VNC servers and web viewers end up inside your products and container images. Safeguard's software composition analysis, generally available, builds a full transitive dependency inventory of those components, and SBOM generation and analysis (generally available, SPDX and CycloneDX) answers "which of our images ship this library at this version" when an advisory lands. Vulnerability management with EPSS and CISA KEV enrichment, generally available, helps you rank a remote desktop library flaw that is being exploited above one that is not, and container scanning, also generally available, covers the images where these servers often hide. Our post on using SBOMs to find affected products fast walks through that workflow.

Fix it without waiting for upstream

The RDP service inside Windows is patched by Microsoft, and nothing here changes that. But a large share of remote desktop code in real environments is open source, packaged into your own builds and images: VNC servers, RDP client libraries and the TLS libraries both depend on. When one of those has a vulnerability, the following applies.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

These demos show dependency and SBOM workflows, not remote desktop monitoring. You can download Safeguard and follow the CLI docs to try them on your own projects.

This demo sets up the Safeguard runner on your own machine, approves it with its device code and then scans from the terminal. Pointed at a container image that bundles a VNC server or an RDP client library, the same scan lists those components and their versions with any known vulnerabilities, so you know what remote desktop code you actually ship.

Click through it at your own pace, or open it full screen.

This demo is a real CLI session: install, open the interactive terminal, ask it to fix the lodash CVE in a repository, and watch it read the finding and advisory, ask before each command, move lodash to 4.17.21, run npm install and npm test with approval, and print a summary without pushing anything. The same approve each step flow applies when the dependency to bump is a remote desktop or TLS library pinned in your manifest.

Click through it at your own pace, or open it full screen.

This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. Once connected, you can ask in plain language which of your projects include a particular VNC or RDP library version, and get the answer from your own scan data rather than from memory.

Click through it at your own pace, or open it full screen.

Quick check

Your RDP server requires NLA. Does that mean the user's password never reaches the server?

No. NLA authenticates the user before a session is created, but CredSSP still delegates the user's credentials to the server so it can log them on. To keep credentials off the host, use Remote Credential Guard (Kerberos only) or Restricted Admin mode.

A VNC server uses VNC Authentication with a strong password. Is the session protected on an untrusted network?

No. RFC 6143 says VNC Authentication is cryptographically weak, and the RFB stream itself has no protection against observation or tampering. Bind the server to localhost and connect through an SSH tunnel, or use a TLS based security type that authenticates the server.

Sources

Last reviewed: 23 October 2026. Microsoft revises its RDP specifications often; check the current revision of MS-RDPBCGR and your Windows version's documentation before relying on a specific default.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.