在Kerberos出现之前,NTLM被广泛应用于工作组和域环境,是更早的用于对用户进行身份验证的协议。
相比于Kerberos,NTLM的认证原理比较简单,主要通过对比客户端和服务端加密后的数据,判断其是否一致,以确定用户身份。
如果用做菜来比喻,那么被加密的数据就是“原材料”,加密密钥就是“秘方”,原理就是“用不同的秘方做出来的菜味道不一样”。当秘方只有客户端和服务端知道,服务端确定用户身份时,只需要用该秘方和客户端做同一盘菜,对比两盘菜的味道,如果一样,那就是真实的客户端。
目前NTLM有两个版本,分别是NTLMv1和NTLMv2,他们间最主要的区别体现在被加密数据的长度上,也就是“原材料”的种类。在v1版本中数据长度是8位,而v2版本中增加到16位。
v2版本相较于v1安全性更高,在网络中应用较多。因此,本篇文章中,我们将基于NTLMv2的认证原理,详细介绍“客户端登录”、“访问服务器资源”和“域环境下申请服务”这三种情况的认证过程。
客户端登录
回忆我们平常登录电脑的过程,输好密码后就直接跳转到了桌面,整个过程不过一两秒钟。但其实在这短暂的两秒中,电脑内部发生了多重“反应”,从而实现对我们身份的验证。
首先,我们输入的密码会被交给Lsass进程,这个进程对明文密码进行加工,生成唯一的密码哈希。
然后,Lsass进程将从本地内存中,找到该用户账户对应的密码哈希。
最后再比较两者,如果相同,证明该用户的身份是真实的,则允许登录。
这之中有个关键点:原本存在于本地内存中的密码哈希,是从何而来的呢?
原理是这样的,这个值早在用户注册时,就由Lsass存储在系统中了。这样做的目的,就是为了在系统重启时,快速帮助验证用户身份,保障用户数据安全。
访问服务器资源
在开放网络环境下,用户要访问服务器资源,就需要向服务器提交申请。在NTLM认证过程中,服务器接到申请后,除了验证用户身份,还要判断该用户是否有使用资源的权限、自己是否有能力提供服务等。
接下来我们说说这个过程。
同本地账户类似,用户在访问服务器之前,也需要先在服务器中存有自己的账号,以便在身份验证时进行信息对比。
首先用户注册一个账号,该账号密码以哈希形式存储在服务器中,形成只有用户和服务器知道的“秘方”。
用户请求访问服务时,先将自己的用户名提供给服务器,并且附上想要访问的服务内容。
如果该用户确实存在,服务器就会发送一个随机数给客户端,叫用户做“一道菜”来证明自己不是伪冒的,这个随机数就是“原材料“。这时候,伴随着“原材料”一起发送给客户端的,还有它能提供的服务列表。
客户端收到数据后,将随机数取出,用自己的密钥哈希加工,得到色香味唯一的菜肴。然后将“做好的菜”和原料以及自己的用户名放在一起,组成身份验证包,再次发给服务端。
服务端从自己的数据库中找到该用户的“秘方”,使用同样的“原材料”——随机数做菜。然后比较两道菜,如果相同,则认为用户身份真实,就可以响应其请求了。
域环境下申请服务
域环境下申请服务时,NTLM的认证过程和第二种情况基本一样,只是在最后验证用户身份时,并不是由服务器来进行,而是域控。
这是为什么呢?
在AD域安全管理系列科普文章中,我们提到,AD域内所有账户信息都存储在域控上。这说明,域环境下的服务器上并没有用户“秘方”,“秘方”只存在于域控上。
所以服务器接收到身份验证包后,会将它转发给域控,由域控来进行验证。
域控在数据库中找到该用户对应的密码哈希,同样加工该随机数,得到加密后的值。将这个值与客户端加密的值进行比较,最后把结果返回给服务器。
结语
由上可见,无论哪种情况下,NTLM在认证过程中,都没有在网络上单独传递密码,这减少了密码泄露的可能,提高了系统安全性。
但NTLM的认证方式也不是绝对安全的,基于密码哈希的认证方式,让攻击者在不需要获取明文密码的情况下,也能直接传递密码哈希通过认证。有的攻击者甚至将客户端发送给服务器的验证信息截获,用来进行明文爆破或NTLM中继攻击。
为了防范这样的威胁,我们需要选择安全性更高的认证协议或采取专门的安全运营方案。