kerberos协议与域内攻击手法分析

目录

随缘更,随缘补,与时俱进

NTLM与kerberos认证体系

本地认证

本地认证是今天讲的这些认证方式之中最简单的一个。

当我们开机登录输入密码的时候,系统会将我们输入的明文密码加密成NTLM hash,此时再同sam文件里的值进行对比,如果相同,则登录成功。NTLM hash的前身是LM hash

SAM文件中所储存的是密码的hash值

我们上面说的sam文件是指:

1
C:\Windows\System32\config\SAM

总结一下,就是用户注销、重启后,操作系统会显示输入框,接收输入后,首先判断输入的用户名是否存在,如果存在将密码交给lsass进程,这个进程中可能会存一份明文密码,将明文密码加密成NTLM Hash,对比SAM数据库中的hash进行验证。

NTLM hash 的产生:

1
明文->hex编码->Unicode编码->MD4

python实现:

1
2
3
import hashlib,binascii
hash = hashlib.new('md4', "password".encode('utf-16le')).digest()
print binascii.hexlify(hash)

或者也可以直接用ntlm库

windows 网络认证

  • 在内网渗透中,经常会遇到工作组环境,而工作组环境是一个逻辑上的网络环境(局域网工作区),因为在工作组中并不存在一个信托机构,所以隶属于工作组的机器之间是无法建立一个完美的信任机制的,只能点对点进行认证
  • 假如在一个工作组中有a,b两个机器,a想远程访问b上的文件,那么这个时候a机器的操纵者则需要将一个存在于b机器上的账户凭证发送给b机器,经过认证后才能访问。
  • 最常见的服务:445端口的smb服务
  • smb协议:一个用于进行共享文件资源的一个协议

NTLM(NT LAN Manager)协议

  • 早期smb协议在网络上传输明文口令,后来出现LAN Manager Challenge/Response 验证机制,简称LM,由于他的不安全性,微软在后面的更新中提出了windowsNT挑战/响应验证机制,称之为NTLM。发展到现在已经有了更新的NTLM V2以及Kerberos验证体系。
  • smb协议本身只提供了资源相关的共享服务,在认证方面,采用的是NTLM协议,可以类比我们远程访问windows的共享文件夹时,在认证我们身份的方面,也是采用的NTLM协议,在windows的好多服务的”认证层”上,使用的都是我们的NTLM协议。当然如果是在域内,认证方面会采用kerberos协议进行认证

挑战(challenge)/响应(response)机制

主要分为质询->协商->验证三个阶段

第一步协商

简单来说就是客户端主要在这一步向服务端确认协议的版本,是NTLM v1还是NTLM v2还是其他的比如LM协议。

第二步质询

第二步质询完整过程:

  1. 客户端向服务端发送用户信息(包含用户名)请求
  2. 服务器接受到请求,生成一个16位的随机数,被称之为”challenge”,并在本机sam文件上查找登录名对应的密码的NTLM Hash,并用这个NTLM Hash 加密challenge,生成challenge1后,将challenge发送回客户端(这里的challenge1呢其实就叫做Net NTLM Hash,这个在ntlm中继攻击中提到过,可以去看下那篇文章)
  3. 客户端接受到challenge后,会将用户输入的密码进行NTLM hash,并使用NTLM hash加密 challenge, 生成Response,然后将Response发送至服务端。(这里的Response,本质上也可以说是Net NTLM Hash)
  4. 服务器端收到客户端的Response后,对比challenge与Response是否相等,若相等,则认证通过

第三步验证

这一步其实就是上面质询过程中的第4点,为了更方便理解,所以没有拆分

总结

这里有一个总结的图示:

NTLM v1与NTLM v2的差别

  • NTLM v1与NTLM v2最大的差别就是challenge与加密算法不同
  • challenge:NTLM v1的challenge有8位,NTLM v2的challenge有16位
  • Net-NTLM hash:NTLM v1的主要加密算法是DES,NTLM v2的主要加密算法是HMAC-MD5

域认证体系-kerberos认证

(注:下面所有流程图中的ticket代表ST)

  • kerbroes是一种网络认证协议,其目标设计是通过密钥系统为客户机/服务器应用程序提供强大的认证服务。该认证过程的实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求网络上所有主机的物理安全,并假定网络上传送的数据包,可以被任意的读取修改。在以上情况下,kerberos作为一种可信任的第三方服务,是通过传统的密码技术(如共享密钥),执行认证服务的

域认证所参与的三个角色

  • client(客户端)
  • server(服务端)
  • KDC(域控上的一个服务)

域认证所参与的角色(KDC上又细分的一些服务)

  • AD(account database):储存所有client的白名单,只有存在于白名单的client才能顺利申请到TGT
  • AS(Authentication Service):为client生成TGT的服务
  • TGS(Ticket Granting Service):为client生成某个服务的ticket。生成ST的地方

域认证流程——粗略流程

  1. client向kerberos服务(就是我们的域控上的一个服务)请求,希望获得访问server的权限。kerberos服务得到了这个消息,首先判断client是否是可信赖的(就是判断是否是此域内的机器),也就是白名单黑名单的说法。这就是AS服务完成的工作,通过在AD中存储黑名单和白名单来区分client。成功后AS返回TGT给客户端。(AS_REQ与AS_REP)
  2. client得到TGT后,继续向kerberos服务请求,希望获得访问server的权限。kerberos服务得到了这个消息,这时通过client消息中的TGT,判断出了client拥有这个权限,于是给了client访问服务端的权限并返回了ST。(TGS_REQ与TGS_REP)
  3. client得到ST后,终于可以访问server。这个ST只是针对这个server,其他server需要向TGS申请。(AP_REQ与AP_REP)

域认证流程深入剖析—第一步:TGT的获取 (AS_REQ与AS_REP)

  1. 首先我们的客户端会向域控上的kdc服务的AS发送我们客户端的一些信息,比如用户名,主机名等。
  2. 下一步我们的kdc服务上的AS就会进行判断这个主机、用户名等是否在我们的域里面,如果存在,那么我们kdc上的AS就会生成一个session key,这个session key是一串随机字符。
  3. 域用户的密码的NTLM hash是可以域控上查到的,然后就会使用这个客户端用户对应的NTLM hash来加密我们的session key,并将加密后的值返回发送给客户端。
  4. 然后域控这里下一步会使用KDC服务对应的用户的NTLM hash,对session key和一些客户端的信息再进行加密,最后加密出的结果也就是我们常说的TGT,并将他连同3中加密出的值一同返回发送给客户端

我们再来用两张图详细的剖析下上面所说的”客户端发送”与”KDC返回”这样的两个过程:

发送:

返回:

大家可以看到这里的TGT的有效性是有时间限制的

域认证流程深入剖析—第二步:获取ST (TGS_REQ与TGS_REP)

  1. 我们的客户端接收到了一个密文和一个TGT
  2. 第一个密文是KDC用我们客户端的用户的密码的NTLM hash加密session key产生的,因为这个客户端的用户的密码的NTLM hash不仅在域控上存在,在我们客户端本机也是存在的,所以的客户端就会使用这个客户端的用户的密码的NTLM hash来对密文进行解密,从而得到session key。
  3. 下一步我们的客户端就会向KDC上的TGS服务发送TGT,以及用session key加密的当前客户端的一些信息和时间戳,然后还有一些客户端的信息和要访问的服务端的信息这三块内容
  4. 当我们客户端向KDC发送以后,KDC的TGS服务就会开始进行认证,它首先会使用KDC服务对应的用户的NTLM hash去解密TGT得到session key,再通过session key去解密客户端包装加密的信息,得到客户端的一些信息和时间戳,然后会比较这个时间戳和当前的时间戳是不是间隔的太久了,如果间隔超过一定时间则需要他重新从头开始验证,然后他还会通过接收到的这个客户端的信息和服务端的信息来判断当前客户端是否有权限去访问这个服务端
  5. 当KDC上的TGS认证通过以后呢,他又会随机生成一串字符,叫做server session key,这个server session key其实就是用于客户端和服务端进行通信时的密钥。然后TGS会使用session key来加密这个server session key并将这个密文返回给客户端。
  6. TGS还会提取客户端的所在的域的域名,客户端的用户信息,server session key,到期时间等,来做成ST
  7. 此时TGS还会提取接收到的要访问的服务端的一些信息,并使用服务器端对应的计算机名对应的NTLM hash来加密ST,并将这个密文也返回给客户端

流程图:

ST的组成:

域认证流程深入剖析—第三步:client通过ST访问server (AP_REQ与AP_REP)

  1. 客户端通过session key解密得到server session key,并使用server session key来加密客户端的信息和时间戳,并连同ST一同发给服务端
  2. 因为服务端这台机器上是存着自己的用户hash的,所以我们可以使用Server hash解密得到ST,并得到ST里的end time,用他来判断得到ST是否已经过期,还会得到ST里的server session key,然后会使用这个server session key来解密1步骤的密文,得到客户端的信息和时间戳,然后他会去校验这个客户端信息和ticket里的客户端信息是否相等,还会验证这个时间戳是否大于某个时间。

简易流程图:

PAC

在黄金/白银票据的构造分析中,开启PAC可以防止白银票据的攻击。

那么PAC是什么呢?

我们都知道黄金票价的构造原理就是:掌握KRBTGT用户密码之后可以通过签发一张高权限用户的TGT票据,再利用这个TGT向KDC获取域内服务的ticket来实现对域的控制。那么这里的“高权限用户”是通过什么来判断的呢,答案就是PAC。

PAC在我们域认证中出现的节点是在哪的呢?

主要是两个节点

  1. 当我们的客户端第一次向KDC去请求TGT的时候,我们返回的TGT票据中就包含了PAC。(AS_REP)
  2. 就是最后我们的客户端拿着ST去与服务端通信的时候,如果一切验证顺利,那么最后我们的服务端就会将解密出来的PAC发送给KDC去进行认证,KDC解密PAC。获取Client的sid,以及所在的组,再根据该服务的ACL,判断Client是否有访问服务的权限。防止白银票据其实主要也是这一步。 (AP_REP)

总结
kerberos认证流程的本质上就是不停交换密钥,然后采用对称加密算法验证时间戳和身份,来完成的一个安全认证

白银票据与黄金票据构造分析

**(下面所说的Server hash指的是服务端机器用户的NTLM hash)**我们的白银票据和黄金票据主要是用来做权限维持的

白银票据

白银票据的特点:

  1. 不需要与DKC进行交互
  2. 需要服务端的计算机机器账户ntlm hash
  3. 只能针对一台机器

在我们那个认证协议分析的文章中介绍了整个基于kerberos协议认证的流程,其中说到了ST,而我们所说的白银票据其实就是我们伪造的ST。

在上面也讲了,ST的构成:
ticket=Server hash(Server session key+Client info+End Time)

根据我们讲协议那篇文章可知,当客户端与服务端进程认证时,客户端会使用server session key来加密客户端的信息和时间戳,并连同ST一同发给服务端,然后服务端会使用Server hash解密ST,得到ST里的end time,server session key等,所以在未发送ST之前,服务端是不知道Server Session Key是什么的,所以我们只要知道Server hash就可以伪造一个不经过KDC认证的ST,这也就是我们白银票据的原理。

在构造的时候,我们可以自定义一个Server session key并使用它加密客户端的信息和时间戳并伪造一个ST一同发送给服务端。

白银票据-mimikatz伪造演示

导出Server hash:

1
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit" > log.txt

伪造票据:

在另外的机器上执行:

1
mimikatz.exe "kerberos::golden /domain:<域名> /sid:<域SID> /target:<目标服务器主机名> /service:<服务类型> /rc4:<NTLM Hash> /user:<用户名> /ptt" exit
1
2
3
4
5
6
/domain:域名
/sid:SID值
/target: 服务端计算机名
/service: 需要指定相关的服务名
/rc4: 服务端的计算机机器账户ntlm hash
/user: 要伪造的用户名,任意填写

成功:

补充:

因为ST 生成时指定了相关的服务名,所以因此只能用来访问相对应的服务。还有一些其他的服务:

1
2
3
4
5
6
7
8
服务名称                              同时需要的服务
WMI HOST、RPCSS
PowerShell Remoting HOST、HTTP
WinRM HOST、HTTP
Scheduled Tasks HOST
Windows File Share CIFS
LDAP LDAP
Windows Remote Server RPCSS、LDAP、CIFS

白银票据防御
开启PAC

黄金票据

黄金票据特点:

  1. 需要与DC通信
  2. 需要krbtgt用户的hash

这里的krbtgt用户的hash指的就是上面的KDC Hash:

黄金票据实际上指的就是我们伪造的那些TGT,在我们知道KDC Hash以后,就可以利用构造出来的TGT去申请各种服务的,拿到ST以后就可以访问目标服务器。

我们在讲协议认证的那篇博客中,讲了TGT的构成:使用KDC hash 加密(session key ,客户端信息,客户端到期时间)后的密文

  • 在我们上篇文章讲到了,在获取ST的时候,客户端会拿着得到的TGT以及用session key加密的当前客户端的一些信息和时间戳,然后还有一些客户端的信息和要访问的服务端的信息这三块内容去获取ST。
  • 然后在服务端接受后它首先会使用KDC服务对应的用户的NTLM hash去解密TGT得到session key,再通过session key去解密客户端包装加密的信息,得到客户端的一些信息和时间戳,然后会比较这个时间戳和当前的时间戳是不是间隔的太久了,如果间隔超过一定时间则需要他重新从头开始验证,然后他还会通过接收到的这个客户端的信息和服务端的信息来判断当前客户端是否有权限去访问这个服务端。

所以黄金票据的原理就是伪造获取ST时发送的TGT和用session key加密的密文等”,而这些在我们知道KDC Hash以后,是都可以完成的,伪造成功以后通过DC的认证拿到ST就可以访问目标服务器。(伪造的时候,session key 我们自己定义一串字符就好)

伪造票据:

抓取域内hash:

1
域控执行:lsadump::lsa /patch

在另外的机器上执行:

1
mimikatz.exe "kerberos::golden /domain:<域名> /sid:<域SID> /rc4:<KRBTGT NTLM Hash> /user:<用户名> /ptt" exit
1
2
3
4
/domain:域名
/sid:SID值
/rc4: 域控的krbtgt账户ntlm hash
/user: 要伪造的用户名,任意填写

成功:

ticket总结

NTLM_smb 中继攻击

NTLM中继

其实简单来说,ntlm中继攻击就是一种中间人攻击

Windows系统域名解析顺序

  1. 本地hosts文件(%Systemroot%\System32\drivers\etc\hosts)
  2. DNS缓存/DNS服务器
  3. 链路本地多播名称解析(LLMNR)和NetBIOS名称服务(NBNS)

当1,2步请求失败时,Windows系统就会通过LLMNR和NetBIOS名称服务在本地进行名称解析。这时,客户端就会将未经认证的UDP广播到网络中,询问它是否为本地系统的名称。这时我们监听网段的请求,就可以对信息进行捕捉,我们可以监听到的大多都是Net-NTLM hash,他并不是我们明文的直接hash值,所以我们不可以利用它直接进行横向攻击。

smb中继

smb中继攻击是基于ntml中继攻击的一种,因为SMB的认证是可以基于NTLM协议或者kerberos协议

对于SMB协议,客户端在连接服务端时,默认先使用本机的用户名和密码hash尝试登录,所以可以模拟SMB服务器从而截获Net-NTLM hash,进行破解明文,或进行中继

演示

环境:
kali:10.10.10.160
域控:10.10.10.10
pc1:10.10.10.201
pc2:10.10.10.80

利用LLMNR和NetBIOS截取Net-NTLM Hash

使用responder监听同域内中所有主机的广播请求:

pc1上输入个错误的地址,让其通过LLMNR和NetBIOS进行名称解析:

得到hash:

利用smb 中继进行攻击

再说smb攻击之前,先介绍一下SMB签名
SMB签名是一种服务器与客户端协商以使用继承的会话密钥对所有传入的数据包进行数字签名的配置。这样的话,即使NTLM会话还是可能被Relay,服务器也不会被利用,因为攻击者缺少会话密钥。在Active
Directory 网络中只有域名控制器默认开启SMB签名,其他的所有服务器或工作组默认不受保护。所以只有被攻击的目标机器SMB签名关闭的时候,才会攻击成功

探测一波,可以看到与前面说的比较符合,只有域控默认会开启smb签名:

可以关掉:

1
reg add HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters /v RequireSecuritySignature /t REG_DWORD /d 0 /f

利用responder+MultiRelay.py获取shell:

修改下Responder.conf :

开启responder与MultiRelay.py,填好要攻击的目标pc2的ip:

其他机器上随便传一个smb流量:

攻击成功:

利用 smbrelayx.py 获取shell:

原理: 伪造一个我们恶意的SMB服务器,当内网中有机器访问这个我们精心构造好的SMB服务器时, smbrelayx.py 将抓到Client1 的 hash ,然后 smbrelayx.py 用抓取到的 Client1 的 hash 重 放给 Client2

指定要攻击的机器ip:

在其他机器上传一个smb的流量:

命令执行成功:

MS14-068 漏洞分析—不安全的PAC

前言

这是一个危害较高的漏洞:只需要一个域内的普通用户的账户密码,便可拿到域控的权限

漏洞原因简述

**利用伪造的高权限的PAC来获取一个带有高权限PAC的TGT。
**(关于pac是什么上面也已经解释过了)

在我们的AS_REQ 请求中如果include-pac被置为 true,那么我们的 AS 会在返回的 TGT 中加入 PAC信息,如果我们在 AS_REQ 数据包中,将include-pac被置为 false,那么 AS_REP 返回的 TGT 中就不会包含 PAC
信息。在TGT中没有PAC信息后,我们就可以使用域用户去伪造”恶意”的PAC放入TGS_REQ中,KDC解密PAC后会再次加密到一个新的TGT中并返回给域用户(注意这里KDC返回的是一个TGT并不是一个ticket),此时的TGT中已经携带了“恶意”PAC,也就达到漏洞利用的目的。

详细原因

  1. KDC机构对PAC进行验证时,对于PAC尾部的签名算法,理上规定必须是带有Key的签名算法才可以,但实际上却允许任意签名算法,所以只要我们客户端去随便指定一个方便验证通过的签名算法,那么KDC服务器就会使用我们指定的算法来进行签名验证。比如说我们可以规定使用md5算法,将 md5(内容) 来作为签名,这样当KDC接收以后,发现我们在数据包中规定了使用md5算法,那么KDC就会将我们的内容进行md5后与我们的签名进行比对。如此一来我们可以对内容进行伪装。‘
  2. PAC没有被放在TGT中,而是放在了TGS_REQ数据包的其它地方。但KDC还是能够正确解析出放在其它地方的PAC信息。KDC会使用subkey,将PAC信息解密并利用我们客户端设定的签名算法验证签名
  3. KDC 验证 (缺少 PAC 的 TGT) 与(不在 TGT 中的 PAC) 这两个成功后,那么会去把 PAC 中的 User SID、Group SID 取出来,重新使用进行签名,签名算法和密钥与设置 inclue-pac 标志位为 TRUE 时一模一样。将新产生的 PAC 加入到解密后的 TGT 中,再重新加密制作全新的 TGT 发送给 Client。(注意这里KDC返回的是一个TGT并不是一个ST)

通过以上流程我们成功获得了一个高权限的TGT。

漏洞演示

攻击机:mac

域控:win2008 172.16.84.35

域内普通用户:test/1qaz@WSX

攻击工具: goldenPac
(这个工具最方便,有py与exe两种。是 ms14-068 与 psexec 的结合,可以直接获得一个shell回来)

1
2
3
4
5
# goldenPac.py
python3 goldenPac.py walking.com/test:1qaz@WSX@DC.walking.com -dc-ip 172.16.84.35 -target-ip 172.16.84.35 -debug

# goldenPac.exe
goldenPac.exe walking.com/test:1qaz@WSX@DC.walking.com

运行脚本:

成功获得域控的system权限shell:

zerologon漏洞分析

漏洞原因

windows上比较重量级别的一个漏洞。通过该漏洞,攻击者只需能够访问域控的445端口,在无需任何凭据的情况下能拿到域管的权限。

该漏洞的产生来源于Netlogon协议认证的加密模块存在缺陷(微软在进行AES加密运算过程中,使用了AES-CFB8模式并且错误的将IV设置为全零,这使得攻击者在明文、IV等要素可控的情况下,存在较高概率使得产生的密文为全零。),导致攻击者可以在没有凭证的情况情况下通过认证。

该漏洞的最稳定利用是调用netlogon中RPC函数NetrServerPasswordSet2来重置域控机器的机器用户的密码,从而以域控的身份进行Dcsync获取域管权限。从而接管整个域

DCSync

在DCSync技术没有出现之前,我们想要dump服务器的hash,一般都要先入侵到目标服务器上,然后使用例如mimikizi的工具,对hash来dump,DCSync的最大特点,在于不用登陆域服务器,即可远程通过域数据同步复制的方式获得想要的用户口令信息。DCSync 就是通过 Directory Replication Service(DRS) 服务的 GetNCChanges 接口向域控发起数据同步请求。

DCSync利用条件

获得以下任一用户的权限:
· Administrators组内的用户。
· Domain Admins组内的用户。
· Enterprise Admins组内的用户。
· 域控制器的计算机帐户(机器账户)

漏洞利用

第一个参数为目标机器名,第二个为ip

1
工具地址: https://github.com/dirkjanm/CVE-2020-1472

上一步会把域控DC机器的机器用户的密码置为空,即hash为:
31d6cfe0d16ae931b73c59d7e0c089c0

接下来使用空密码就可以进行Dcsync(这里不可以直接登录的,因为机器用户是不可以登录的。但是域控的机器用户有Dcsync特权,我们就可以利用该特权来利用Dcsync进行hash读取,然后用读取的hash进行登录或者横向攻击)

下面的工具原理是模仿一个域控制器,从真实的域控制器中请求数据,例如用户的哈希。

利用机器用户及空密码获取域管administrator用户的hash:

1
proxychains4 secretsdump.py -no-pass de1ay.com/"DC$"@10.10.10.10 -history -just-dc-user administrator
1
工具地址:https://github.com/SecureAuthCorp/impacket

利用得到的域控用户administrator的账户密码,进行横向登录拿下域控:

拿下域控以后,我们要对我们重置的密码进行恢复,要不然会影响系统业务,这里可以用:

1
2
powershell Reset-ComputerMachinePassword

这是微软官方给的一种解决方案。

(好久之前分析过,有空补一下下面的文章。。。)

Nopac分析

PrintNightmare分析

CVE-2025-33073分析

EXCHANGE

ProxyShell

ProxyNotSell

ProxyLogon

CVE-2021-26857

PrivExchange

ADCS

ADCS Relay

ESC系列

CVE-2022-26923

ACL滥用

委派攻击专项

非约束委派攻击

约束委派攻击

基于资源的约束委派(RBCD)

Kerberos Bronze Bit

Azure-AD

Kerberoasting/AS-REP Roasting