4 认证与会话
上文阐述了 NTLM 中继的基本原理,接下来出现的问题是,在中继 NTLM 身份验证后,如何在目标服务器上执行具体地操作?
要回答这个问题,必须首先澄清一个基本的事实。当客户端向服务器进行身份验证以执行某些操作时,必须区分两件事:
- 身份验证(Authentication),允许服务器验证客户端是它声称的身份。
- 会话(Session),在此期间客户端将能够执行操作。
如果客户端通过了正确的身份验证,那么它将能够访问服务器提供的资源,例如网络共享、对 LDAP 目录的访问、HTTP 服务器或 SQL 数据库等等。
为了管理这两个步骤,所使用的协议必须能够封装身份验证,从而交换 NTLM 消息。
如果所有协议都集成 NTLM 技术细节,是不符合软件工程中的解耦思想的。因此,微软提供了一个接口来处理身份验证,并且专门开发了包来处理不同类型的身份验证。
4.1 SSPI & NTLNSSP
SSPI 接口(Security Support Provider Interface) 是 Microsoft 提出的用于标准化身份验证的接口,不同的协议都可以使用这个接口来处理不同类型的身份验证过程。在 NTLM 认证中,使用的是 NTLMSSP
(NTLM 安全支持提供程序)。
SSPI 接口提供了几个函数,包括 AcquireCredentialsHandle
、 InitializeSecurityContext
和 AcceptSecurityContext
。在 NTLM 身份验证期间,客户端和服务器都会使用到这些函数。简述这些步骤:
- 客户端调用
AcquireCredentialsHandle
获得对用户凭据的间接访问。 - 客户端然后调用
InitializeSecurityContext
,该函数在第一次调用时将创建类型为NEGOTIATE
的 type 1 消息。对于研发来说,这条消息是什么并不重要,重要的是将它发送到服务器。 - 服务器在收到消息时调用
AcceptSecurityContext
函数。 这个函数然后将创建类型为Challange
的 type 2 数据。 - 收到此消息时,客户端将再次调用
InitializeSecurityContext
,但这次将CHALLENGE
作为参数传递。NTLMSSP
负责通过加密Challenge
来计算响应的内容,并生成最后的AUTHENTICATE
消息。 - 服务器收到该消息后,也会再次调用
AcceptSecurityContext
,自动进行鉴权验证。
这意味着这 5 个步骤完全独立于客户端的类型或服务器的类型。 无论使用何种协议,只要该协议具有允许这种不透明结构,以一种或另一种方式从客户端交换到服务器的内容,它们就可以工作。
因此,协议通过将 NTLMSSP
、 Kerberos
或其他身份验证结构放入特定字段,如果客户端或服务器看到该字段中有数据,它只会将其传递给 InitializeSecurityContext
或 AcceptSecurityContext
。
应用层(HTTP、SMB、SQL 等)完全独立于身份验证层(NTLM、Kerberos 等)。 因此,认证层和应用层都需要安全措施。
通过 SMB 和 HTTP 的两个示例帮助读者更好地理解。其它协议也十分相似。
4.2 HTTP & NTLM
一个 HTTP 的基本请求:
GET /index.html HTTP/1.1
Host: www.geekby.site
User-Agent: Mozilla/5.0
Accept: text/html
Accept-Language: zh-cn
此示例中的必需元素是 HTTP 动词 ( GET )、请求页面的路径 ( /index.html )、协议版本 ( HTTP/1.1 ) 或主机标头 ( Host: beta.hackndo.com )。
但是可以还添加其它的 HTTP 头。最好的情况是,服务器知道这些标头会存在,并且知道如何处理。最坏的情况是直接忽略。
正是 HTTP 的此项特性,能够将 NTLM 的相关信息从客户端传输到服务器。即在客户端添加 Authorization
的 HTTP 头,在服务端添加一个 WWW-Authenticate
的头。如果客户端尝试访问需要身份验证的网站,服务器将通过添加 WWW-Authenticate
标头来响应,内容包含其支持的不同身份验证机制。如对于 NTLM,返回: WWW-Authenticate: NTLM
。
客户端知道需要 NTLM 身份验证,将发送 Authorization
头中的第一条消息,并 base64 编码(因为该消息仅包含不可打印的字符)。 服务器将在 WWW-Authenticate
填充 Challenge
,客户端将计算响应并将其放到 Authorization
头中。如果认证成功,服务器通常会返回 200 返回码。
> GET /index.html HTTP/1.1
> Host: www.geekby.site
> User-Agent: Mozilla/5.0
> Accept: text/html
> Accept-Language: en
< HTTP/1.1 401 Unauthorized
< WWW-Authenticate: NTLM
< Content type: text/html
< Content-Length: 0
> GET /index.html HTTP/1.1
> Host: www.geekby.site
> User-Agent: Mozilla/5.0
> Accept: text/html
> Accept-Language: zh-ch
=> Authorization: NTLM <NEGOTIATE in base64>
< HTTP/1.1 401 Unauthorized
=> WWW-Authenticate: NTLM <CHALLENGE in base64>
< Content type: text/html
< Content-Length: 0
> GET /index.html HTTP/1.1
> Host: www.geekby.site
> User-Agent: Mozilla/5.0
> Accept: text/html
> Accept-Language: zh-cn
=> Authorization: NTLM <RESPONSE in base64>
< HTTP/1,200 OKAY.
< WWW-Authenticate: NTLM
< Content type: text/html
< Content-Length: 0
< Connection: close
只要 TCP 会话处于打开状态,身份验证就会有效。然而,一旦会话关闭,服务器将不再拥有客户端的安全上下文,并且必须进行新的身份验证。由于 Microsoft 的 SSO(单点登录)机制,整个过程对用户是透明的。
4.3 SMB & NTLM
再举一个 SMB 协议的例子。SMB 协议,通常用于访问网络共享。
SMB 协议通过使用命令来工作( Microsoft 定义的相关文档 ),例如,有 SMB_COM_OPEN
、 SMB_COM_CLOSE
或 SMB_COM_READ
,用于打开、关闭或读取文件的命令。
SMB 还有一个专门用于配置 SMB 会话的命令, SMB_COM_SESSION_SETUP_ANDX
。 此命令中有两个字段专用于 NTLM 认证的字段。
- LM/LMv2 认证:OEMPassword
- NTLM/NTLMv2 认证:UnicodePassword
下图是一个 SMB 数据包的样例,其中包含服务器对身份验证的响应。
这两个示例表明 NTLM 的内容与协议无关。它可以包含在任何支持它的协议中。
然后,将 身份验证部分
与 应用程序会话部分
做区分。会话部分是通过客户端身份验证后使用的协议进行的交换的延续,例如通过 HTTP 浏览网站,使用 SMB 访问网络共享上的文件。
由于认证和会话过程彼此的信息是独立的,这意味着中间人很可能会通过 HTTP 接收身份验证,并将其中继到服务器但使用 SMB,称为跨协议中继。
考虑到所有这些因素,下一章节将重点介绍已经各种存在风险的点,以及用于解决这些问题所引入的安全机制。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论