Windows认证机制学习笔记(实时更新)
2024-11-07 16:18:23

Windows认证机制学习

了解和学习一下windows间的认证,用来维持权限和提权。

一般分为三种:

  • 网络认证
  • Kerberos域认证
  • Windows Access Token认证

从这三个方面入手学习,但在正式学习之前,要补充下windows本地认证

0x00 本地认证

其实在我们用户开机输入完密码之后进行登录,系统会读取我们机器上的%SystemRoot%\system32\config\sam​文件(一般SystemRoot为C://windows​),进行比对。这个sam文件它里面的密文不是明文,而是密码的hash值,这里的hash有着具体的类别:LM-Hash,NTLM-Hash,下面具体解析一下它们两者不同和联系。

LM Hash

LM出现的版本要比NTLM早,全名LAN Manager,唯一和NTLM的区别就在于他们所采用的加密算法不同。认证机制都是挑战/响应这一套的认证模式。

具体的LM加密算法简略的记一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
将所有小写字母转换为大写字母
• >123ABC // 未达到7个字符
• 将密码转化为16进制,分两组,填充为14个字符,空余位使用0x00字符填补
• >31323341424300000000000000
• 将密码分割为两组7个字节的块
• >31323341424300 00000000000000 // 16进制
• 将每组转化为比特流,不足56Bit则在左边加0
• >31323341424300 ->(转换为二进制) 110001001100100011001101000001010000100100001100000000-> (补 足56Bit) 00110001001100100011001101000001010000100100001100000000
• 将比特流按照7比特一组,分出8组,末尾加0

由于后者都为0,结果可想而知,那就都是0;
• 将每组比特流转换为16进制作为被加密的值,使用DES加密,字符串 “KGS!@#$%”为Key(0x4B47532140232425),得到8个结果 ,每个 结果转换为16进制。
• -> 00110000100110001000110001101000000101000001001000001100 00000000
• ->30988C6814120C00 -> DES(30988C6814120C00) -> 48-D7-EB-91- 2F-5E-69-7C
• 由于我们的密码不超过7字节,所以后面的一半是固定的:
• AA-D3-B4-35-B5-14-04-EE
• 连接两个DES加密字符串。这是LM哈希。
48-D7-EB-91-2F-5E-69-7C-AA-D3-B4-35-B5-14-04-EE

这很明显有两个缺点,一个就是如果后面56bit全为0的话,说明密码小于7位,然后是DES加密的密钥为”KGS!@#$%”,结果算出来结合第一个条件,后面的一半结果是固定。加上本身的密钥就是固定的,所以是存在很大的爆破空间的。

NTLM Hash

全名NT LAN Manager

虽然LM比NTLM早出现,但是现在windows计算机大部分都是NTLM的Hash认证机制。NTLM本身是一种认证协议,他认证的根本途径就是这个Hash。比如我们刚才提到的本地认证机制,其实就是用户输入的密码经过Hash算法算出来这段NTLM Hash和sam文件里面的Hash进行比较,匹配就让你进去。而NTLM和LM本质没有什么不同,他们的认证机制还是那么一套,只是加密算法的不同,也就是算出来的hash不同。这个hash其实就是根据用户的密码以及LM或者NTLM算法算出来的。

具体的NTLM Hash算法可以举个例子,假设管理员用户的密码为admin:

1
2
3
4
admin  -> hex(16进制编码) = 61646d696e
61646d696e -> Unicode = 610064006d0069006e00
610064006d0069006e00 -> MD4 = 209c6174da490caeb422f3fa5a7ae634

此时的209c6174da490caeb422f3fa5a7ae634就是一段NTLM Hash

两种Hash在进行本地认证的时候,默认采用如下过程:

1
winlogon.exe -> 用户输入 -> lsass.exe -> 认证

winlogon.exe是用来管理用户登录和登出的,相当于就是弹个登录框和登出框,然后接收用户的输入,并将其送给lsass.exe(windows本地安全策略和登录策略)进程,将该密文密码加密成NTLM Hash和SAM文件中的hash进行对比和认证。

而实际上lsass.exe内存中就存有密码,平常所说的抓密码就是抓lsass内存中的密码。

0x01 网络认证

内网渗透一般会遇到两种环境,一个是工作组,一个是域。工作的话没有一个大的管理机构,仅凭工作组中各台机器单对单的进行认证,而这个认证就是LM,NTLM,以及之后要学的kerberos,虽然kerberos用于域管理的环境中,但是他们三者都算是网络认证。

NTLM具体认证机制

单按照概念来说,其实就是一句话:接受挑战!(NTLM只支持windows)

Chanllnge/Reponse

三个步骤:1.协商 2.质询 3.认证。1和3其实都没什么好讲的,1是为了协商双端的协议版本,3是将2中质询的结果和进行进一步验证。整个NTLM认证核心是其中质询的步骤。

质询具体步骤

  1. 客户端向服务器首先发起一个挑战的请求,其中包含自己的用户名
  2. 服务器接收到这个请求之后,开始在本地进行一个16位随机数的生成(暂时叫做Challenge1) ,这个生成的随机数本身不是密文,他只是一个媒介。之后服务端就会利用客户端发送过来的用户名在本地对应的NTLM hash对这个随机数进行加密(生成的叫做Chanllenge2),此时该随机数会暂存于本地内存。之后服务端将Chanllenge1返回给客户端。
  3. 客户端接收到Chanllnge1,开始利用本地自己输入的密码算出来的NTLM Hash对这个Chanllnge1进行同样的加密生成一段密文(结果称为Client-Response)。将该Response发送过服务端。

质询的过程就完毕了,之后就是认证,很简单比较这两者的区别。然后还有一个概念,这个经由服务端本地NTLM Hash加密生成的Challenge2在整个认证过程中还叫做Net-NTLM Hash。但其实本质上Client-Response也叫做Net-NTLM Hash。只要是经过两端NTLM Hash综合加密的密文,都叫做这个。

NLTM V2

和V1的区别在哪?实际上我们上面说的Challenge是16位的,说的就是NTLM V2,V1只有8位。然后其实看完上面的内容肯定还有会疑问,经由NTLM Hash加密的这个Net NTLM Hash具体的加密算法是什么?V1是传统的DES加密,V2是HMAC-MD5算法(就是平常口中说的MD5)。

PTH(Pass the HASH)

其实只要对上面的NTLM认证的过程理解,就能够发现一个问题。服务器本地认证的东西是算出来的这个Net NTLM HASH。这就给我们的攻击提供了另一种可能,只要能够获取到这个Net NTLM Hash,或者我们只要获取服务端上存于内存(SAMhash或者system注册表hash)的NTLM Hash,就能够完成质询这一段过程。

实战一下:

首先上个shell,dump出服务端的sam.hive和system.hive,然后下下来。这个hive文件本身是数据库文件,那前缀加一个sam,其实就是存储sam的存储的文件,以及system的存储文件。reg save就是对注册表操作中某一个部分的内容保存在文件的指令。然后sam文件在注册表中的位置是hklm\sam,system同理。这条命令的简单意思就是将注册表中hklm下的sam和system文件内容全部dump到c:\programdata目录下。

1
reg save hklm\sam c:\programdata\sam.hive && reg save hklm\system c:\programdata\system.hive

从被攻击机上拿下来之后,可以考虑直接上mimikatz解,也可以拿到自己本机解

本机用mimikatz解一下:

1
mimikatz "log" "lsadump::sam /sam:sam.hive /system:system.hive"  "exit"

image

这个时候就得到了服务端内存的NTLM hash了,接下来两种选择,一种是用MD5解密解一下,或者可以直接进行PTH了。(当然前提是服务端开启了NTLM认证,既然拿到了shell又想尝试的话,其实可以拿命令开一下)

这么做其实就是初步拿到shell之后进一步内网渗透的一个小过程,虽然抓的是已经获取到shell的机器的NTLM Hash,但是我们还是可以进一步通过这个NTLM Hash进行下一步的移动和权限维持。

Kerberos 域认证

上面所提到的认证机制都是存在于结构或者说小型的网络环境下的认证机制,而域是windows给大型企业管理资产服务提供一种方式。如果要搭建一个域环境,就必须安装一个活动目录服务。

0X02 Active Directory(活动目录)

基本介绍

从上到下,Active Directory存储的内容是有关的网络对象的信息,具有管理员权限的用户能够完全访问和使用这些网络对象的信息。相关权限的用户也能够使用对应的信息。

那么什么是网络对象呢?如果按照比较浅显的认知来说,网络对象其实就是一个公司里面所有的网络设备,包括PC,服务器,打印机等等,但是在AD中,网络对象有着很明确的定义,包括:用户,用户组,域,组织单位等等,将多个PC或者多个网络设备看作一个理论集合的概念,也算作网络单位。

AD的主要作用包括服务器以及客户端的管理,用户个人使用服务,资源管理(主要包括打印机以及文件共享这类公共网络对象服务),桌面配置用于PC上统一管理,应用程序(包括各种OA,HR系统等)等。其实可以说掌握了AD就能够掌握当前域中所有设备了。

本身网络设备之间是可以互相访问的,这些在域控环境下的网络设备如果要相互访问,认证的协议就是kerberos协议。

kerberos介绍

kerberos认证的三个主体部分:

  • client
  • server
  • KDC(Key Distribution Center)=DC (Domain Controller)

Client和server不必多说,KDC是什么?首先从翻译上就能看出来,是一个域中管理机构,实际上和Active Directionary的作用差不多,都叫域控制器。要讲清楚KDC的作用,得留到Kerberos的认证流程中才能体现,这里先提几个基本概念。

  • 票据(Ticket):这个是网络对象能够互相访问的凭证

  • TGT(Ticket Granting Ticket):用来向KDC申请获取Ticket的入场券,是一种临时凭证。

  • KDC本身的功能实现是由三部分组成:

    • Authentication Service(AS):用来给Client生成初版TGT的,就是TGT检测Client的用户名在AD中是白名单,这个时候就让AS生成TGT发送给请求的Client端。
    • Ticket Granting Service(TGS):主要是为了给Client生成某一个server的TGT,因为一个TGT只能去访问一个Server,那么对应的其他server的TGT就需要TGS来生成。
    • account database(AD):存储着所有的Client白名单。这个注意和Active Directionary区分一下。AD可以说是包含在ActiveDirectory中,两者发挥作用的时候其实统称AD即可
  • krbtgt账户:是系统在创建域时自动生成的一个帐号,其作用是密钥分发中心的服务账号,其密码是系统随机生成的,无法登录主机。主要作用是生成TGT的时候用到的,后面会提到。

Kerberos认证机制流程

  • AS-REQ: Client端向KDC发送一段请求信息,这段信息包括自己的用户名以及用Clienthash加密过的一段时间戳信息。然后KDC交由AS去根据用户名在AD中查找该Client端是否在白名单,并在本地提取出对应NTLM HASH
  • AS-REP: KDC此时随机生成一段字符串,叫做Sessionkey,然后利用用户名的NTLM Hash进行加密,此时这一段经过加密的随机字符串就是Client之后能够和TGS服务通信的一段凭证。之后KDC再利用krbtgt账户的NTLM HASH对sessionkey和Client的一些信息(Client的SID以及用户Client所在的组)进行加密,生成TGT。此时,KDC端已经生成了两份加密内容,一个是AS内容,也就是初步通过Clienthash生成的TGS访问凭证。一个是TGT内容,是通过krbtgt账户HASH加密随机字符串sessionkey和Client信息生成的。这两个东西全部返回给Client。其中TGT的到期时间是8个小时。

这第一段检验其实目的就是一个,验证Client是个好人,并且关键性验证是Client在AD的白名单中。作用主体是AS。所以是不太好操作的。

当Client经过了初步认证之后,下一步就是开始正式向KDC提出访问对应Server的请求了,上一步结尾Client拿到了TGT,以及用它自己NTLM HASH加密的SessionKEY密文。可以想象,TGT由于是KDC通过krbtgt用户的HASH加密过来的,所以这一段信息即使中间人获取到了,在不得知krbtgt账户的情况下,想要爆破出来还是有点难度的。默认情况下,TGT相当于KDC的一个官方凭证,有这个TGT你才能跟我提要求。

一图流回顾一下:

image

image

下面开始看Client如何向KDC提要求

  • TGS-REQ: Client端开始拿着刚才获得的TGT以及通过AS传输过来的加密seessionkey,解密之后用它来加密自身客户端信息和想要去请求的Server端的信息,时间戳这三个部分生成的内容,发送给KDC
  • TGS-REP: KDC接收到数据之后,会首先解密TGT,从TGT中提取sessionKEY,这个sessionkey是通过KDC中的krbtgt账户的hash加密过来的,然后用sessionkey去解密Client发送过来的加密时间戳和自身其他信息以及请求的Server端信息,初步检验该Client是否授信。验证通过之后,KDC会新生成一个Server Session KEY,然后从AD中找到Server的NTLM hash,对三个部分:SeverSessionkey+CLient信息+ENDTIME进行综合加密,该密文被称为Ticket。也是最后Client用来访问Server端的凭证了。

稍微回顾一下此时的情况,Client最后接收到ServerSessionkey以及Ticket,此时这个sessionkey就是一段随机字符串,真正有用这段Ticket,但他本身是通过AD中查找比对用Server的HASH加密过来的,所以加密内容也没什么用。中间获取到这段信息也很难得到有效信息。

一图流回顾:

image

image

之后Client终于可以去找Server了

  • AP-REQ: Client拿着KDC返回过来的Ticket以及用serverSession加密过的客户端信息和时间戳密文,发送给Server端
  • AP-REP: 由于这段Ticket的加密部分是由Server端的NTLM HASH加密过来的,客户端如果没有AD权限的话还是很难得到这段HASH的。Server端通过它自己本地内存中的NTLM HASH对其进行解密之后得到Client端信息以及ServerSessionkey和时间戳,对比时间段和key之后,认证Client的身份。之后就可以愉快的玩耍了

这里有一个致命的问题,假设,攻击机通过某种途径拿到了TGT,然后就可以向KDC申请TGS,这里的指定的Server端可以是任何一个网络对象,包括域控服务器!这个过程利用被记为了MS14068。

白银票据

检验成功之后,客户端本地内存会一直存着这段Ticket。但是这里验证会有一个问题,Server一开始并不知道ServerSessionkey是什么,它只是把Ticket的内容解密之后认定某个部分是ServerSessionKey。然后就是解决时间戳的问题。这个也好解决,因为Ticket中存储的END TIME,这个可以伪造。我们只需要微调一下通过ServerSessionKey加密的客户端信息+时间戳的内容,就能够满足时间时间长度正确。

综上,实现白银票据的条件只有一个:获取到存储在对应Server的NTLM Hash即可。然后其实理解一下白银票据,它本身是针对于Client最后去访问Server这个过程,前面的AS-REQ和AS-REP的过程实际上都是在获取TGT的过程,也就是说白银票据绕过了从AD中进行白名单匹配的这一个过程,感觉不算是漏洞,算是它本身的一种机制。

而且防御起来也容易,直接开启PAC(Privileged Attribute Certificate),将这一部分的授权验证交给kerberos服务,由kerberos服务来检验票据是否有效。

开启方式如下:

通过注册表

1
HKEY_LOCAL_MACHINE\SYSTEM \ CurrentControlSet\Control\Lsa\Kerberos\Parameters

ValidateKdcPacSignature​ 值设为 1

这个时候Server的认证过程就不一样了,并且引入了一种全新的认证方式,这种方式就叫做PAC

PAC认证

在我们上面提到的kerberos认证过程中,PAC被塞进了一开始的AS认证中,也就是Client初次向KDC发送AS-REQ,这个时候KDC会调用AS去DC中查找白名单,如果确实当前Client存于白名单,那么就会用krbtgt账户的NLTM HASH对sessionkey+clientinfo+endtime进行加密,如果开启了PAC认证,那么此时还会新增一条一起加密,整体的加密结构如下:

image

PAC包含用户的权限、组成员身份、特权信息等。这些信息都是从ActiveDirectory中获取到的,属于

之后就是一样的流程,Client拿这段TGT向KDC申请TGS。KDC开始根据krbtgt账户的NLTM HASH对TGT进行解密,只要这一步解密没问题了,其实KDC就能够把TGS发给Client。所以实际上只要我们能够拿到krbtgt账户的HASH,就理论上实现了访问任何服务。

之后Client拿着这段TGS去访问Server,Server拿自己hash解密完之后,拿到PAC,再去问KDC这个Client有没有权限访问我,然后再交给域控去解密PAC,获取到用户所在的组和SID,再据此判断用户是否有访问该server的权限。

这么一看其实PAC就是加了一层双层保险,并且全流程下来,Client都看不见PAC(没有KDC账户krbtgt的前提下)。PAC的制作也是KDC通过查找AD中存储的Client的相关信息才得到的,这一点也是Client无法得到的。不过拿到了域控之后啥都好说。

黄金票据

很明显,从名字上就能看出来,著名语言艺术家OTTO曾经说过,白银这个位置是最尴尬的,上不去下不来的这个段位,卡在这了。那黄金票据的攻击可行性就远远要比白银票据多多了。但是条件也更苛刻。

其实黄金票据的原理就是TGT本身的加密规则是知道的,并且加密的密钥就是KDC Hash,只要我们拿到了这个KDC的hash,就能够实现单一Client向KDC请求任意Server,只要将TGT本身需要的内容和信息通过这个Hash加密,然后按照TGS-REQ的格式发送即可。

总共有如下两个条件:

  • 需要和DC,也就是域控服务器进行访问
  • 需要获取到KDC hash

总结

这些内容应该放到实战中或者自己练习的时候去验证,但是我个人现在只能先把这些理论的东西理解一遍,然后按照自己的思路记录。之后会实时更新以及重新修订一些内容。这篇就相当于动态笔记分享了,希望能够帮助到其他师傅。
参考:https://payloads.online/archivers/2018-11-30/1/#0x00-%E6%9C%AC%E5%9C%B0%E8%AE%A4%E8%AF%81
https://daiker.gitbook.io/windows-protocol