Post

域渗透学习(二)
Active Directory与Kerberos

AD、Kerberos

域渗透学习(二)
Active Directory与Kerberos

域渗透指的是内网环境下的Windows域体系渗透,在windows的认证体系中,涵盖有用户直接操作计算机登录(本地认证winlogin.exe->lsass.exe)、通过网络连接到工作组中的一台设备(网络认证)、通过域连接到域内的一台设备(域认证)

常言的PTH哈希传递、PTT票据传递、委派攻击等技术,都是基于windows域环境认证技术的攻击行为,这也是为什么在深入学习域渗透前要了解windows认证的原因。

Active Directory

在以攻防为上下文的交流语境中会把AD和域一概而论,造成了AD渗透等于域渗透的混淆。

而在大型内网的场景下,区分这两个概念对攻击路径的规划其实至关重要。

当我们在谈论域渗透时,重心其实在于域内攻击,关注点是域管理员权限

而AD渗透的重心则放大到了跨域/林攻击,目标是控制整个AD的服务实现

为了能够更顺畅的学习AD渗透,这里把AD有关的概念和技术稍作了解


Active Directory是一种目录服务,它是一个技术体系,基于LDAP(轻量级目录访问协议)标准。

它包含了数据库(NTDS.dit)、认证协议(Kerberos/NTLM)、复制机制(Replication)以及名称解析服务(DNS)

其功能实质是提供身份验证、授权和资源审计

域

域是AD的一个逻辑管理单元和安全边界

它是AD架构中的一个容器,用于组织对象(用户、计算机、组)

管理员权限是它的默认边界,域管默认只管理当前域

域树

域具有域名,比如may.com,由一个或多个子域组成域树

域林

由多个域树组成域林

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ffffff', 'edgeLabelBackground':'#ffffff', 'tertiaryColor': '#fcfcfc'}, 'flowchart': { 'nodeSpacing': 80, 'rankSpacing': 80, 'curve': 'basis', 'padding': 20 } } }%%
graph TD
    %% 定义样式
    classDef forest fill:#e3f2fd,stroke:#1565c0,stroke-width:3px,stroke-dasharray: 8 5;
    classDef tree fill:#fffde7,stroke:#fdd835,stroke-width:2px;
    classDef domain fill:#ffffff,stroke:#333,stroke-width:1px,rx:5,ry:5;
    classDef rootDomain fill:#ffccbc,stroke:#d84315,stroke-width:3px,rx:5,ry:5,font-weight:bold;
    classDef infoNode fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px,stroke-dasharray: 2 2;

    %% 最外层:域林 (Forest)
    subgraph Forest_Container ["Active Directory Forest (域林) - 最大的安全边界"]
        direction TB
        
        %% 共享信息节点(独立放置,增加间距)
        ForestInfo["SHARED:<br>Schema Partition & Configuration Partition<br>(共享架构分区与配置分区)"]:::infoNode

        %% 域树 A
        subgraph Tree_A ["Domain Tree A: may.com Namespace"]
            direction TB
            Domain_RootA("may.com<br>(Forest Root Domain)<br>林根域"):::rootDomain
            Domain_ChildA1("ops.may.com<br>(Child Domain)"):::domain
            Domain_ChildA2("dev.may.com<br>(Child Domain)"):::domain
            
            Domain_RootA <==>|父子信任<br>Parent-Child Trust| Domain_ChildA1
            Domain_RootA <==>|父子信任<br>Parent-Child Trust| Domain_ChildA2
        end

        %% 域树 B
        subgraph Tree_B ["Domain Tree B: shell.com Namespace"]
            direction TB
            Domain_RootB("shell.com<br>(Tree Root Domain)<br>树根域"):::domain
            Domain_ChildB1("lab.shell.com<br>(Child Domain)"):::domain
            
            Domain_RootB <==>|父子信任<br>Parent-Child Trust| Domain_ChildB1
        end

        %% 跨树信任
        Domain_RootA -.->|树根信任<br>Tree-Root Trust| Domain_RootB
        
        %% 利用隐藏连接强制布局,将信息框推到右侧而不重叠
        Tree_B ~~~ ForestInfo
    end

    %% 应用样式
    class Forest_Container forest;
    class Tree_A,Tree_B tree;

NTDS.dit

NTDS的全称是NT Directory Services,dit后缀的全称为directory information Tree

它位于域控的%SystemRoot%\NTDS\ntds.dit

它存储了Active Directory中的所有数据,包括架构、配置、域三大分区的数据

其最核心的内容是存储了所有域用户的NTLM Hashes、Kerberos Keys以及历史密码记录

但它被内核级的文件锁保护着,无法直接复制,其数据也是加密的,解密它需要PEK(Password Encryption Key),而PEK被存储在域控的注册表中

LDAP

上文中有描述到AD是一种基于LDAP协议的技术体系,但AD完全不是唯一基于LDAP的东西,LDAP甚至都不是微软开发的。

  • LDAP(Lightweight Directory Access Protocol)是一种通讯协议,它规定了如何查询、搜索、修改目录数据库
  • AD是微软开发的一个目录服务产品,它听得懂LDAP语言,所以可以用LDAP协议去操作AD

LDAP是一个工业标准(IEFT RFC 4511),在非Windows的世界里它同样被广泛使用

LDAP在企业架构中的用途主要围绕集中式查询和集中式认证

  • Linux服务器的统一登录
  • 应用系统的后台认证 如VPN、Jenkins

在AD渗透过程中使用的SharpHound、BloodHound,它的采集器本质上就是在疯狂的发送LDAP查询,它不进行漏洞利用,只是不停地使用合法LDAP语法询问Domain controller

sequenceDiagram
    autonumber
    participant Attacker as 攻击机/肉鸡 (Client)<br>IP: 192.168.1.66
    participant Firewall as 防火墙/流量探针<br>(IDS/ATP/NTA)
    participant DC as 域控制器 (DC)<br>IP: 192.168.1.5<br>Port: 389 (LDAP)

    Note over Attacker, DC: 阶段一:握手与身份绑定
    Attacker->>DC: TCP [SYN]
    DC-->>Attacker: TCP [SYN, ACK]
    Attacker->>DC: TCP [ACK] (连接建立)
    
    Attacker->>DC: LDAP Message: bindRequest (Simple: "DOMAIN\zhangsan")
    DC-->>Attacker: LDAP Message: bindResponse (success)

    Note over Attacker, DC: 阶段二:疯狂的“查户口” (SharpHound Collection)
    
    rect rgb(255, 230, 230)
        note right of Attacker: ⚠️ 流量特征:高并发、持续性查询
        
        Attacker->>DC: searchRequest (Filter: objectClass=domain)
        DC-->>Attacker: searchResEntry (域策略、密码策略)
        
        Attacker->>DC: searchRequest (Filter: objectClass=user)
        DC-->>Attacker: searchResEntry (返回 5000+ 用户对象数据)
        
        Attacker->>DC: searchRequest (Filter: objectClass=computer)
        DC-->>Attacker: searchResEntry (返回 1000+ 计算机对象数据)
        
        Attacker->>DC: searchRequest (Filter: objectClass=group)
        DC-->>Attacker: searchResEntry (返回所有组及成员)

        loop ACL 权限枚举 (最嘈杂的部分)
            Attacker->>DC: searchRequest (查询 nTSecurityDescriptor 属性)
            DC-->>Attacker: searchResEntry (返回复杂的二进制 ACL)
            Attacker->>DC: searchRequest (查询 下一个对象的 ACL...)
            DC-->>Attacker: searchResEntry (...)
        end
    end

    Note over Firewall: 🚨 触发告警: [LDAP Reconnaissance]<br>检测到来自 192.168.1.66 的异常 LDAP 查询量

    Note over Attacker, DC: 阶段三:会话结束
    Attacker->>DC: unbindRequest
    DC-->>Attacker: TCP [FIN, ACK]

域认证体系

在Windows域环境中,认证体系并非只有网络上讨论最多的Kerberos协议,而是由两套平行且互补的协议组成

1.Kerberos(主):现代、安全、高效。基于票据体系

2.NTLM(备):古老、简单、兼容性好。基于C/R体系,在上一篇Windows本地网络认证的文章中已有讨论。

决定使用Kerberos还是NTLM的角色是一个名为Negotiate的Windows API。它的原则是能用Kerberos尽量用,用不了时降级使用NTLM,使用IP访问、SPN错误的情况会导致Kerberos无法使用,

Kerberos

Kerberos是域环境的默认认证机制,也是最复杂的体系。

它由MIT(麻省理工学院)开发,诞生于MIT著名的Project Athena(雅典娜计划)的一部分。

摘自维基百科

麻省理工学院研发Kerberos协议来保护雅典娜工程(Project Athena)提供的网络服务器。这个协议以希腊神话中的人物Kerberos(或者Cerberus)命名,他在希腊神话中是Hades的一条凶猛的三头保卫神犬。目前该协议存在一些版本,版本1-3都只有麻省理工内部发行。

undefined

这条三头保卫神犬在希腊神话中叫做刻尔伯洛斯,在神话中说此犬有50个头,而在后来的一些艺术作品中大多表现它有3个头,因此在汉语语境的通俗表达中也常称其为地域三头犬

而MIT的开发者给这个协议取名为Kerberos并使用地域三头犬的形象logo,不仅仅是因为历史缘故,更是因为这三个头完美对应了Kerberos协议赖以生存的三个核心实体

Kerberos的三个核心实体

在Kerberos协议的三角关系中,这三个头分别是Client、Server和KDC

Client是想去访问域内资源的计算机,Server是被访问的目标服务器

KDC是最关键的那个实体,全称为Key Distribution Center密钥分发中心,它是整个体系中的信托

而KDC主要包含AS、TGS和AD

  • Authentication Server:负责验证用户身份,发放TGT
  • Ticket Granting Server:验证TGT,发放ST
  • Account Database:存储所有Principal(用户、计算机、服务)的长期密钥

Kerberos认证过程

第一阶段,Client会携带Client ID、Nonce(随机数,防止relay攻击)、Encrypted Timestap向KDC发起KRB_AS_REQ请求,该请求会被AS接受并验证,如果验证成功,AS会返回KRB_AS_REP,其中包含Logon Session Key,是使用Client的Long-term key进行的加密,client也可以使用它来解密。其次返回TGT(Ticket Granting Ticket),它是使用KDC自身的Long-term Key加密的(也就是KDC上krbtgt用户的hash),client无法解密TGT,只能原样持有。

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ffffff', 'edgeLabelBackground':'#ffffff', 'tertiaryColor': '#fcfcfc'}, 'sequence': { 'mirrorActors': false, 'bottomMarginAdj': 10, 'messageAlign': 'center', 'noteAlign': 'left', 'actorMargin': 150 } } }%%
sequenceDiagram
    autonumber
    
    participant C as Client<br>(Principal)
    
    box rgb(235, 245, 255) "Trusted Third Party: KDC"
        participant AS as AS<br>(Authentication Server)
    end

    Note over C, AS: 阶段一:AS Exchange (Authentication Service)

    C->>AS: KRB_AS_REQ
    Note right of C: 包含:<br>1. Client ID<br>2. Nonce (随机数)<br>3. Encrypted Timestamp (预认证)

    activate AS
    AS-->>C: KRB_AS_REP
    deactivate AS
    
    Note left of AS: 返回包含:<br>1. {Logon Session Key}_ClientKey<br>(Client 用自己密码解密)<br><br>2. TGT ({Logon Session Key}_KrbTgtKey)<br>(Client 无法解密,妥善保存)

来到二阶段,client已经具有AS发放的TGT

Client利用TGT向KDC的TGS申请特定服务的Service Ticket,简称ST

其中会携带SPN(Service Principal Name)目标服务主体名称、TGT和Authenticator(是一阶段AS返回的Logon Session key解密后加密的时间戳,用于证明其是TGT的合法持有者)

TGS使用krbtgt密钥解密TGT,获取Logon Session Key,再用它解密Authentictor。若验证通过,TGS生成Service Session Key(服务回话密钥),并返回ST(Service Ticket)和Encrypted Service Session Key(使用Logon Session Key加密的新生成的Service Session Key 供Client解密使用)

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ffffff', 'edgeLabelBackground':'#ffffff', 'tertiaryColor': '#fcfcfc'}, 'sequence': { 'mirrorActors': false, 'bottomMarginAdj': 10, 'messageAlign': 'center', 'noteAlign': 'left', 'actorMargin': 150 } } }%%
sequenceDiagram
    autonumber 3
    
    participant C as Client<br>(Principal)
    
    box rgb(235, 245, 255) "Trusted Third Party: KDC"
        participant TGS as TGS<br>(Ticket Granting Server)
    end

    Note over C, TGS: 阶段二:TGS Exchange (Ticket Granting Service)

    C->>TGS: KRB_TGS_REQ
    Note right of C: 包含:<br>1. SPN (目标服务名)<br>2. TGT (上一轮拿到的)<br>3. Authenticator ({Client ID}_LogonKey)<br>(证明我有 Logon Session Key)

    activate TGS
    TGS-->>C: KRB_TGS_REP
    deactivate TGS
    
    Note left of TGS: 返回包含:<br>1. {Service Session Key}_LogonKey<br>(Client 解密得到本次会话密钥)<br><br>2. ST ({Service Session Key}_ServerKey)<br>(即 Service Ticket,Client 无法解密)

最后到第三阶段,client已经取得了访问目标服务的ST,那么在这个阶段KDC不再需要直接参与

client携带ST和New Authenticator发送KRB_AP_REQ请求,Server接收到后使用自己的Logon-term Key解密ST,提取出Service Session Key,然后使用该Session Key解密Authenticator,验证时间戳

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ffffff', 'edgeLabelBackground':'#ffffff', 'tertiaryColor': '#fcfcfc'}, 'sequence': { 'mirrorActors': false, 'bottomMarginAdj': 10, 'messageAlign': 'center', 'noteAlign': 'left', 'actorMargin': 150 } } }%%
sequenceDiagram
    autonumber 5
    
    participant C as Client<br>(Principal)
    participant S as Server<br>(Target Service)

    Note over C, S: 阶段三:CS Exchange (Client/Server)

    C->>S: KRB_AP_REQ
    Note right of C: 包含:<br>1. ST (服务票据)<br>2. New Authenticator ({Client ID}_ServiceKey)<br>(证明我有 Service Session Key)

    activate S
    S-->>C: KRB_AP_REP (可选)
    deactivate S
    
    Note left of S: 双向认证成功:<br>{Timestamp}_ServiceKey<br>(Server 证明它成功解密了 ST<br>并提取了正确的 Session Key)

完整的通信过程如下

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ffffff', 'edgeLabelBackground':'#ffffff', 'tertiaryColor': '#fcfcfc'}, 'sequence': { 'mirrorActors': false, 'bottomMarginAdj': 10, 'messageAlign': 'center', 'noteAlign': 'left', 'actorMargin': 150 } } }%%
sequenceDiagram
    autonumber
    
    participant C as Client<br>(Principal)
    
    box Trusted Third Party: KDC (密钥分发中心)
        participant AS as AS<br>(Authentication Server)
        participant TGS as TGS<br>(Ticket Granting Server)
    end
    
    participant S as Server<br>(Target Service)

    %% ==========================================
    %% Phase 1: Authentication Service Exchange
    %% ==========================================
    rect rgb(255, 250, 240)
        Note over C, AS: 阶段一:AS Exchange (获取 TGT)
        
        C->>AS: KRB_AS_REQ
        Note right of C: 包含: Client ID, Nonce<br>(可选: Pre-Auth Data)
        
        activate AS
        AS-->>C: KRB_AS_REP
        deactivate AS
        Note left of AS: 包含 2 部分:<br>1. {Logon Session Key}_ClientKey<br>2. TGT ({Logon Session Key, Client ID}_KrbTgtKey)
    end

    %% ==========================================
    %% Phase 2: Ticket Granting Service Exchange
    %% ==========================================
    rect rgb(240, 255, 240)
        Note over C, TGS: 阶段二:TGS Exchange (获取 ST)
        
        C->>TGS: KRB_TGS_REQ
        Note right of C: 包含 3 部分:<br>1. TGT (原样)<br>2. Authenticator ({Client ID, Time}_LogonKey)<br>3. SPN (目标服务名)
        
        activate TGS
        TGS-->>C: KRB_TGS_REP
        deactivate TGS
        Note left of TGS: 包含 2 部分:<br>1. {Service Session Key}_LogonKey<br>2. ST ({Service Session Key, Client ID}_ServerKey)
    end

    %% ==========================================
    %% Phase 3: Client/Server Exchange
    %% ==========================================
    rect rgb(240, 240, 255)
        Note over C, S: 阶段三:CS Exchange (访问服务)
        
        C->>S: KRB_AP_REQ
        Note right of C: 包含 2 部分:<br>1. ST (服务票据)<br>2. New Authenticator ({Client ID, Time}_ServiceKey)
        
        activate S
        S-->>C: KRB_AP_REP (可选/双向认证)
        deactivate S
        Note left of S: 包含:<br>{Timestamp}_ServiceKey<br>(证明 Server 成功解密了 ST)
    end

为了加深对Kerberos通信过程的印象,明确一下核心术语的精确含义:

  • Session Key(会话密钥)

    由KDC生成的临时、短效的对称密钥。它用于在不传输Long-term Key的前提下,加密Client与KDC或Client与Server之间的通信

  • Authenticator(认证符)

    由Client生成的数据结构,包含Client ID和Timestamp,并使用当前的Session Key加密。它通过证明Client拥有Session Key来验证身份,并利用时间戳防止Relay重放攻击

  • Ticket(票据)

    一种将Client身份信息和Session Key安全的从KDC传递给Server的封装结构。Ticket总是使用接收方的Long-term Key加密

  • Long-term Key(长期密钥)

    它是Principal(用户或计算机)与KDC之间共享的长期密钥,它被静态存储在KDC磁盘的NTDS.dit文件中,除非用户修改密码,否则它永远不会改变。

This post is licensed under CC BY 4.0 by the author.