翻译:shan66
稿费:300RMB(不服你也来投稿啊!
)
投稿办法:发送邮件至linwei#360.cn,或上岸网页版在线投稿

简介
系统管理员每天都会利用远程桌面协议(RDP)登录到远程Windows打算机。最常见的环境是,人们利用它在关键做事器上实行某些管理任务,这些做事器包括具有高度特权帐户的域掌握器等,它们的上岸凭据都是通过RDP传输的。因此,确保RDP配置的安全性是至关主要的。
但是根据我们的不雅观察,由于配置缺点,Active Directory环境中的系统管理员会定期显示(并忽略)证书警告,如下所示:
图1:SSL证书警告
如果您的环境中常常碰着这样的警告的话,您将无法识别真正的中间人(MitM)攻击。
本文旨在帮您认识到负责对待证书警告以及如何安全地配置Windows环境有多么的主要。目标受众是系统管理员、渗透测试职员和安全爱好者。虽然对下列主题的理解没有硬性哀求,但我仍旧鼓励您进一步深入学习一下:
公钥密码术以及对称密码术(RSA和RC4)
SSL
x509证书
TCP
Python
十六进制数和二进制代码
我们将演示MitM是如何嗅探您的凭据的,如果您欠妥心的话是很随意马虎中招的。这些都不是特殊新的技能,例如Cain [2]便是用来干这个的。然而,Cain不仅“年代久远”,代码封闭,而且还只适用于Windows系统。我们想要剖析RDP的所有细节和内部事情机制,并尽可能地仿照真实的攻击环境。
不用说,本文先容的技能不得用于在未经授权的情形下访问不属于您的任何系统。它们只能在系统所有者完备赞许的情形下用于教诲目的。否则,你很可能违反法律,当然,详细还取决于你的统领权。
对付心急的读者,可以通过参考资料[1]中的链接下载相应的源代码。
协议剖析
让我们启动Wireshark,看看当我们通过RDP连接到做事器时会发生什么:
图2:Wireshark中的RDP会话的开头部分内容
正如我们所看到的,客户端首先提出了用于RDP会话的安全协议。这里有三个协议:
标准RDP安全性协议
增强型RDP安全或TLS安全性协议
CredSSP协议
在本例中,客户端能够利用前两个协议。把稳,标准的RDP安全性协议总是可用的,不须要由客户端指出。TLS或增强的RDP安全性协议,只是将标准RDP安全性协议封装到加密的TLS隧道内而已。顺便说一下,在本文中术语SSL和TLS可是可以互换的。
CredSSP协议虽然也利用TLS隧道,但它不是在受保护的隧道中传输密码,而是利用NTLM或Kerberos进行身份验证。该协议也称为网络级认证(NLA)。
早期的用户身份验证有一个特点,那便是许可做事器可以在用户提交任何凭据(用户名除外)之前谢绝访问,例如,如果用户没有必要的远程访问权限。
在上面的Wireshark会话中,我们可以看到,SSL握手是在客户端和做事器已赞许利用增强的RDP安全性协议之后实行的。为此,我们右键单击磋商数据包后的第一个数据包,并将TCP数据流作为SSL解码:
图3:SSL握手的开头部分内容
因此,如果我们想要对一个RDP连接进行中间人攻击的话,不能直策应用SSL代理,由于代理还须要知道RDP。它须要知道何时启动SSL握手,这类似于SMTP或FTP中的StartTLS。我们选择Python来实现这样的代理。为此,我们只需创建受害者客户端连接到的做事器套接字,以及连接到实际做事器的客户端套接字。我们在这些套接字之间转发数据,并在必要时将它们封装到SSL套接字中。当然,我们将密切关注干系数据并根据须要进行修正。
当然,首先要修正的便是客户端提出的协议。客户端可能想见告做事器它可以实行CredSSP协议,但我们将在相应数据到达做事器的半路年夜将协议变动为标准RDP安全性协议。在默认配置中,做事器会很乐意利用这个协议的。
利用Python打造用于RDP的MitM代理
我们的Python脚本的主循环大致如下所示:
函数run()打开套接字,处理协议的协商并启用SSL(如有必要)。
之后,数据就可以在两个套接字之间转发了。如果设置了调试标志,dump_data()函数会将数据作为hexdump打印到屏幕。而parse_rdp()会从数据中提取相应的信息,tamper_data()函数可用于对其进行修正。
密码学根本知识
由于我们须要借助RSA来搞定标准RDP安全协议,以是我们先来理解一下RSA的根本知识。如果您熟习这方面的知识的话,可以跳过此部分。
在RSA中,加密、解密和署名纯粹便是数学运算,并且都是针对整数的运算。
请记住,所有这些操作都是在有限群上完成的[3]。
当天生RSA密钥对时,您须要找到两个大质数p和q。你得到他们的乘积,n = pq(这称为模数),打算φ(n)=(p - 1)(q - 1)(欧拉常数函数),并选择一个与φ(n) 互质的整数e。然后,您须要找到知足
1e•d≡1 modφ(n)
的数字d。
数字d便是私钥,而e和n则组成公钥。当然,理论上d可以利用n和e求出,但φ(n)却很难打算,除非你知道p和q。这便是为什么RSA的安全性在很大程度上取决于大数分解的难度。到目前为止,没有人知道如何有效地进行大数分解——除非你有一台可以事情的量子打算机[4,5]。
为了加密m,我们只需求其e次幂,然后模n:
1c≡me mod n
为了对密文c进行解密,我们可以利用私钥指数d进行下列运算:
1m≡cd mod n
实际上,这是加密运算的逆运算。当然,这里涉及许多数学知识,过于深入的内容我就不先容了。
署名与解密相同。你只需在的哈希值上实行相同的运算即可。
如果m或c大于256位的话,这些运算的开销将非常大,以是常日只利用RSA来加密对称密钥。然后,通过利用刚天生的密钥通过对称密码(常日为AES)算法来加密实际的。
攻陷标准RDP安全协议
实在,攻破这个协议难度并不太大,由于它的设计本身就存在很大隐患,下面我会详细加以讲解。
标准RDP安全协议的运行机制是:
客户声明打算利用标准RDP安全协议。
做事器赞许并将自己的RSA公钥与“Server Random”一起发送到客户端。公钥以及其他信息(例如主机名等)的凑集称为“证书”。
利用终端做事私钥对证书进行署名,以确保真实性。
客户端通过利用终端做事公钥验证证书。如果验证成功,它就利用做事器的公钥来加密“Client Random”,并将其发送给做事器。
做事器利用自己的私钥解密Client Random。
做事器和客户端从Server Random和Client Random中求出会话密钥[6]。这些密钥用于对会话的别的部分进行对称加密。
请把稳,所有这些都因此纯文本形式发送的,而不是在SSL隧道内发送的。原则上讲这没有什么问题,微软只是试图实现自己的SSL加密技能。然而,加密技能是可没想象的那么随意马虎[7],按一样平常规律,你始终该当依赖已建立的办理方案,由于它们都是经由韶光磨练过得,而不是实现自己的办理方案。因此,微软在这里犯了一个根本性的缺点——我实在想不通他们为什么要这样做。
你能创造这里的缺点吗?客户端是如何获取终端做事公钥的?答案是:它是预装的。这意味着它在所有系统上利用相同的密钥。这意味着私钥也都是一样的!
以是,它可以从任何Windows安装上面提取到。事实上,我们乃至不须要这样做,由于现在微软已经决定正式发布它,这样一来,我们可以直接从microsoft.com网站上找到它们[8]。
在导出会话密钥后,可以利用多个安全级别[9]进行对称加密:无、40位RC4、56位RC4、128位RC4或3DES(称为FIPS)。默认值为128位RC4(“High”)。但是如果我们能够窃听密钥的话,那么加密的强度就无所谓了。
以是我们的操持是很明显的:当创造做事器的公钥时,我们快速天生相同大小的自己的RSA密钥对,并用它覆盖原始密钥。当然,我们须要利用终端做事私钥天生我们的公钥的署名,并用它更换原始署名。然后,在客户端成功验证我们的假公钥之后,我们吸收其Client Random。我们利用我们的私钥对它进行解密,将其写下来以便利用做事器的公钥重新加密它。仅此而已!
这样一来,我们就可以被动地读取客户端和做事器之间的加密流量了。
唯一的寻衅是精确解析RDP数据包。这才是我们感兴趣的:
我高亮显示了代表公钥的干系字节。在其前面的两个字节的内容因此小端字节顺序(0x011c)表示的公钥长度。正如我们之前谈论的那样,公钥由模数和公钥指数组成。有关此数据构造的详细信息,请阅读RDP的干系规范[10]。
让我们来看看我们感兴趣的信息。下面是模数:
这里我们可以看到模数n、公钥指数e和私钥指数d。它们是利用大端字节顺序的十六进制数字表示的。我们实际上须要一个2048位的密钥,而不是512位的,但道理您该当清楚了。
假造署名很随意马虎。我们取证书的前六个字段的MD5哈希值,根据规范添加一些常量[11],然后用终端做事密钥[8]的私有部分进行加密。详细可以利用下列Python代码来完成:
我们须要拦截的下一个是包含加密的Client Random的。它看起来如下所示:
我们只须要利用做事器的公钥重新加密它,并在通报它之提高行相应的更换即可。
不幸的是,事情还没有结束。我们现在知道了秘密的Client Random,但不知道什么缘故原由,微软并没有纯挚用它作为对称密钥。有一个精心制作程序[6]可以导出客户真个加密密钥、做事器的加密密钥和署名密钥。
在导出会话密钥之后,我们可以初始化RC4流的s-box。由于RDP对付来自做事器的利用单独的密钥,而不是来自客户真个,因此我们须要两个s-box。s-box是一个256字节的数组,会根据密钥按照某种特定的办法进行重排。然后,s盒就会产生伪随机数流,用来与数据流进行异或处理。这个过程可以用下列Python代码完成:
正如你所看到的那样,协议哀求密钥对4096个数据包加密后进行更新。但是这里我不打算实现这一点,由于我只是对凭据安全性的观点证明感兴趣,以是不想弄那么繁芜。不过,如果读者学有余力的话,可以自行补上!
现在,我们已经万事俱备,足以读取所有的流量了。我们对含有键盘输入事宜(即按键和按键开释)信息的数据包特殊感兴趣。我从规范[12]理解到,可以包含多个数据包,并有慢路径包(从0x03开始)和快路径包(第一个字节可被四整除)。
键盘输入事宜[13]由两个字节组成,例如:
这意味着“S”键(0x1F)已被开释(由于第一个字节是0x01)。
当然,这里的解析事情处理的不是很到位,由于有时鼠标移动事宜会被识别为键盘事宜。此外,scancode须要转换为虚拟键代码,这取决于键盘类型和键盘布局。这样做彷佛有点繁芜,以是我没有这样做,而是直接采取了参考资料[14]中的方法。对付观点验证来说,这已经足够好了。
让我们试验一下。连接到我们的虚假RDP做事器后,我们收到警告说无法验证做事器的真实性:
图4:无法验证做事器的身份...
把稳到了吗?这不是SSL的警告。但是无论如何,我们现在已经可以看到按键了(见图5)。
顺便说一下,这正是Cain所做的事情。
攻陷增强型RDP安全协议
对我来说,降级到标准RDP安全协议是无法令人满意的。如果我是一个攻击者,我会只管即便让攻击看起来不那么不显眼。在上面的环境中,受害人会把稳到一个与平常不同的警告,并且在连接已经建立之后还必须输入其凭据。
当我利用Cain通过MitM办法攻击RDP连接时,假如没有看到相同的SSL警告的话,我会很不爽的。由于如果这个MitM工具会导致显示完备不同的警告的话,那么我就很难向客户阐明为什么必须负责对待SSL警告,特殊是当他们利用了未履历证的自署名证书的时候。
图5:以明文显示的键盘输入事宜。密码是Secr3t!
因此,让我们考试测验将连接降级为增强型RDP安全协议。为此,我们须要自己的自署名SSL证书,不过这可以由openssl天生:
我们须要在精确的韶光将我们的Python TCP套接字封装到SSL套接字中,这对付我们来说不成问题。我之前说过,标准的RDP协议利用了SSL隧道,但做事器总是选择“None”作为其加密级别。这切实其实太好了,由于可以安全地假设SSL封装器能确保数据的真实性和完全性。在SSL之上利用RC4是没有必要的,由于这便是在资源摧残浪费蹂躏。提取击键的事情办法与前一节完备相同。
唯一多出来的安全功能便是做事器会对原始协议协商要求进行确认。
在建立SSL连接后,做事器会对客户端说:“顺便说一下,你见告我这些是你能够处理的安全协议。”用二进制表示的话,它看起来像这样:
然后,客户端可以将该值与最初在第一个要求中发送的值进行比较,如果不匹配,则终止连接。显然,这时已经太晚了。我们作为中间人,可以通过用其原始值(在这种情形下为0x03)更换相应字节(在偏移量为0x4C处的高亮显示字节)来隐蔽来自客户真个伪协商要求。
之后,我们可以毫无阻碍的侦听统统流量了。好了,连续努力。
如预期的那样,受害者这里看到的是SSL警告。但这事仍旧不足圆满。由于在建立RDP连接之前,没有提示我们输入凭据,而是直接显示了Windows登录屏幕。与NLA不同,认证是在会话内部进行的。同样,这仍旧有别于范例的管理事情流程,很随意马虎被精明的用户觉察到。
打破CredSSP协议
好吧,我承认:这里我们没有直接攻陷CredSSP协议。但我们会找到一种方法来绕过它。
首先,让我们看看如果我们不降落连接的安全等级的话,会发生什么。这时,发送到做事器的干系如下所示:
我高亮显示了客户端质询和NTLM的应答,两者是彼此相邻的。做事器质询位于做事器的上一条中。
我们在这里看到的是NTLM身份验证[15]。这是一种质询-应答技能,个中客户端会将做事器质询(类似于Server Random)、客户端质询以及用户密码的哈希值以及一些其他值映射为加密哈希值。这个值称为“NTLM应答”,然后将其传输到做事器。
这个值的打算细节对我们来说并不主要。我们唯一须要知道的是,它不能用于重放攻击或用于哈希值通报攻击。但它可能会遭受密码预测攻击!
底层的哈希算法是HMAC-MD5,这是一个相称差劲的哈希算法(以是我们可以每秒预测大量值),但它仍旧利用了salt(用来对付彩虹表)。
我们现在可以考试测验用Hashcat [17]或者John Ripper [18]来破解它。John的哈希格式为[16]:
虽然不是很空想,但是总比什么都没有强。不过,实际上我们可以做得更好。
我们须要问自己的问题是:做事器是如何验证NTLM应答的?它会咨询域掌握器。那么,如果域掌握器不可用呢? 它会说“算了,让我们利用增强型RDP安全协议吧,不用NLA了”,客户端也会百依百顺。但是有趣的是:由于客户端已经缓存了用户的密码,以是它会直接传输它,而不是将用户勾引至Windows登录屏幕!
这正是我们想要的。这样除了SSL警告之外,就没有任何可疑的东西引起受害者的把稳了。
以是,我们要做的事情是:当客户端发送它的NTLM应答后,我们将做事器的相应更换为:
我没有找到与此有关的文档,但它的确是无法联系域掌握器时的做事器相应。客户端将返回到增强型RDP安全协议,并显示SSL警告,同时将SSL隧道内的密码传输到做事器。
请把稳,我们没有收到SSL警告。根据规范[19],客户端将SSL证书的指纹发送到利用由CredSSP协议协商的密钥加密的做事器。
如果它与做事器证书的指纹不匹配,那么会话将会被终止。这便是为什么纵然受害者供应禁绝确的凭据也不要紧的缘故原由—— 我们可以看到(禁绝确的)密码。
但是,如果密码精确,我们将不雅观察到一个TLS内部缺点。
我想出的办理方法是直接修改NTLM应答。我对Python脚本进行了相应的修正,通过变动NTLM应答让NTLM身份验证总是失落败。不过,受害者是不会把稳到这一点的,由于正如我们刚才看到的,我们可以将连接降级到TLS,这样会重新传输凭据。
但是,还有一件事须要把稳。如果客户端会显斧正在考试测验连接一台加入域的打算机,那么它就不会利用NTLM,而是利用Kerberos,这意味着它将在建立RDP连接之前与域掌握器联系以要求相应的ticket。这是一件好事,由于Kerberos的ticket对攻击者而言,要比没有“盐化”的NTLM应答更加微不足道。但是,如果攻击者处于MitM位置,那么他就可以阻挡针对Kerberos做事的所有要求。如果客户端无法联系Kerberos做事,那会发生什么呢?实际上,它会退回到NTLM。
将这种攻击技能武器化
到目前为止,我们一贯在实验室环境下进行的。以是,受害者在RDP客户端中输入的不是我们的IP,而是他们自己的做事器的IP或主机名。有多种方法可以让我们成为中间人,但在这里我们将利用ARP欺骗。这种方法并不难,过一下子就给出一个观点证明式的演示。由于这种攻击是在网络协议的第二层进行的,以是哀求我们必须与受害者在同一个子网中。
在我们欺骗ARP回答并启用IPv4流量转发后,受害者和网关之间的所有通信都将通过我们的打算机。由于仍旧不知道受害者输入的IP地址,以是仍旧无法运行我们的Python脚本。
首先,我们创建一个iptables规则,丢弃受害者用于RDP做事器的SYN数据包:
图6:左侧:受害者看到的域掌握器的RDP会话。右侧:攻击者看到的明文密码。
建议
那么,作为系统管理员你可能想知道,该当采纳哪些行动来保护自己网络的安全。
首先,如果做事器的身份不能被验证,即如果SSL证书没有被可信证书颁发机构(CA)署名,则谢绝RDP连接是绝对关键的。您必须利用企业CA来签署所有做事器证书。如果无法验证证书,则客户端必须通过GPO [22]配置为禁止连接:
在做事器端是否实行CredSSP(NLA)的问题是非常棘手的。为了便于记录,这也可以作为组策略[20]推出:
我们已经看到,客户端会缓存用户的凭据,以便在NLA不可用的情形下方便地重新传输它们——我们知道,这些凭据就位于内存中。因此,它们可能被具有SYSTEM权限的攻击者读取,例如利用Mimikatz [24]等。这是一个令人难以置信的常见网络攻击环境:攻陷一台机器,利用Mimikatz提取登任命户的明文凭据,并通过横向运动攻击其他帐户,直到找到域管理员密码为止。这便是为什么你只能在域掌握器上利用你的个人域管理员帐户,而不应该在其他地方利用的缘故原由。
但是如果利用RDP远程进入域掌握器则会在事情站上留下高权限帐户的痕迹,这是一个严重的问题。此外,如果您逼迫实行NLA,在启用“用户必须不才次登录时变动密码”选项后,那么只能利用终端做事器的用户会被锁定。我们知道,NLA的唯一优点是更轻便,可以减轻谢绝做事攻击的影响,由于它占用较少的资源,并且可以保护RDP免受基于网络的攻击,如MS12-020 [25]。这便是为什么目前我们正在谈论是否建议禁用RDA的NLA的缘故原由。
如果您希望避免利用NLA,请将组策略“哀求为远程连接利用特定安全层”设置为SSL [20]。
为了进一步增加RDP连接的安全性,您可以采纳的另一项方法是,除了用户凭据之外,为用户验证添加其他验证因子。目前有许多干系的第三方产品,至少在保护关键系统如域掌握器的时候,您可以考虑这一方法。
如果你的Linux机器是通过RDP连接到Windows终端做事器的话,我须要提醒的是,盛行的RDP客户端rdesktop不支持NLA,并且根本不对SSL证书进行验证。以是我建议利用xfreerdp,至少它会验证SSL证书。
末了,鼓励大家对您的同事和用户不断重申:不要轻视SSL警告,无论是在RDP或HTTPS或其他任何情形下。作为管理员,您有任务确保您的客户端系统在受信赖的CA列表中含有您的根CA。这样,这些警告就属于非常,须要立时关照IT部门。
如果您有任何其他问题或见地,请随时与我们联系。
图7:一个关键的GPO设置:为客户端配置做事器验证
参考资料
[1] Vollmer, A., Github.com: Seth (2017), https://github.com/SySS-Research/Seth (Cited onpage 2.)
[2] Montoro M., Cain & Abel (2014), http://www.oxid.it/cain.html (Cited on page 2.)
[3] Wikipedia contributors, Finite group, https://en.wikipedia.org/w/index.php?title=Finite_group&oldid=768290355 (accessed March 8, 2017) (Cited on page 5.)
[4] Wikipedia contributors, Shor’s algorithm (accessed March 8, 2017), https://en.wikipedia.org/w/index.php?title=Shor%27s_algorithm&oldid=767553912 (Cited on page 5.)
[5] Shor, P. W., Polynomial-Time Algorithms for Prime Factorization and Discrete Logarithms on a QuantumComputer (1995), https://arxiv.org/abs/quant-ph/9508027v2 (Cited on page 5.)
[6] Microsoft Developer Network, [MS-RDPBCGR]: Non-FIPS (2017), https://msdn.microsoft.com/en-us/library/cc240785.aspx (Cited on pages 6 and 9.)
[7] Schneier, B., Why Cryptography Is Harder Than It Looks (1997), https://www.schneier.com/essays/archives/1997/01/why_cryptography_is.html (Cited on page 6.)
[8] Microsoft Developer Network, [MS-RDPBCGR]: Terminal Services Signing Key (2017), https://msdn.microsoft.com/en-us/library/cc240776.aspx (Cited on pages 6 and 8.)
[9] Microsoft Developer Network, [MS-RDPBCGR]: Encrypting and Decrypting the I/O Data Stream (2017),https://msdn.microsoft.com/en-us/library/cc240787.aspx (Cited on page 6.)
[10] Microsoft Developer Network, [MS-RDPBCGR]: Server Security Data (TS_UD_SC_SEC1) (2017), https://msdn.microsoft.com/en-us/library/cc240518.aspx (Cited on page 7.)
[11] Microsoft Developer Network, [MS-RDPBCGR]: Signing a Proprietary Certificate (2017), https://msdn.microsoft.com/en-us/library/cc240778.aspx (Cited on page 8.)
[12] Microsoft Developer Network, [MS-RDPBCGR]: Client Input Event PDU Data (TS_INPUT_PDU_DATA)(2017), https://msdn.microsoft.com/en-us/library/cc746160.aspx (Cited on page 10.)
[13] Microsoft Developer Network, [MS-RDPBCGR]: Keyboard Event (TS_KEYBOARD_EVENT) (2017), https://msdn.microsoft.com/en-us/library/cc240584.aspx (Cited on page 11.)
[14] Brouwer, A., Keyboard Scancodes (2009), https://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html#ss10.6 (Cited on page 11.)
[15] Microsoft Developer Network, Microsoft NTLM (2017), https://msdn.microsoft.com/en-us/library/aa378749%28VS.85%29.aspx (Cited on page 14.)
[16] Weeks, M., Attacking Windows Fallback Authentication (2015), https://www.root9b.com/sites/default/files/whitepapers/R9B_blog_003_whitepaper_01.pdf (Cited on page 14.)
[17] Hashcat, https://hashcat.net/hashcat/ (Cited on page 14.)
[18] John The Ripper, http://www.openwall.com/john/ (Cited on page 14.)
[19] Microsoft Developer Network, [MS-CSSP]: TSRequest (2017), https://msdn.microsoft.com/enus/library/cc226780.aspx (Cited on page 15.)
[20] Microsoft Technet, Security (2017), https://technet.microsoft.com/en-us/library/cc771869(v=ws.10).aspx(Cited on page 18.)
[21] Microsoft Technet, Network Security: Restrict NTLM: NTLM authentication in this domain (2017), https://technet.microsoft.com/en-us/library/jj852241(v=ws.11).aspx (Not cited.)
[22] Microsoft Technet, Remote Desktop Connection Client (2017), https://technet.microsoft.com/en-us/library/cc753945(v=ws.10).aspx (Cited on page 18.)
[23] Vollmer, A., Github.com: clone-cert.sh (2017), https://github.com/SySS-Research/clonecert (Cited on page 16.)
[24] Delpy, B., Github.com: mimikatz (2017), https://github.com/gentilkiwi/mimikatz (Cited onpage 18.)
[25] Microsoft Technet, Security Bulletin MS12-020 (2012), https://technet.microsoft.com/enus/library/security/ms12-020.aspx (Cited on page 18.)