每次有人让我推荐适合入门Windows域渗透的靶机,我脑子里第一个浮现的往往是这台Active。它是HackTheBox上编号靠前的Windows靶机,难度标注为Easy,平台是Windows,IP固定为10.10.10.100。我是在刷到第66个靶机时遇到它的,当时用一个下午完整走了一遍,打完最大的感受是:它把Active Directory相关的几个经典攻击面串成了一条干干净净的链路——匿名SMB枚举、GPP组策略密码泄露、Kerberoasting离线爆破,最后到大摇大摆接管域控。全程没有一个系统漏洞被利用,靠的全是配置错误和凭据管理疏漏。
这篇Walkthrough不是简单把命令贴一遍,而是把每一步"为什么要这么做""背后的原理是什么""有哪些容易踩的坑"都讲清楚。适合对Windows内网渗透有基础概念、想通过靶机实操巩固AD攻击面的读者;如果你还不太懂LDAP、Kerberos、SMB这些基础协议,建议先补补协议常识再来看,否则某些环节容易看懵。
1. 环境准备与靶机识别
1.1 开始前的环境确认
HackTheBox的机器分配之后,第一步不是急着扫描,而是先做两件小事:确认网络连通性,确认主机名解析。这台机器的域名叫active.htb,很多人习惯直接扫IP,忽略了域名解析,结果后面Kerberoasting阶段各种报错,还会怀疑是不是工具出了问题。
先把hosts文件加上域名映射:
echo '10.10.10.100 active.htb' | sudo tee -a /etc/hosts然后简单ping一下确认机器在线。这里有个细节:HTB有些机器会禁ICMP,ping不通不代表机器没开,所以更稳的方式是用nmap或者直接nc探测端口。
ping -c 3 10.10.10.100 nc -vz 10.10.10.100 445如果445端口通了,说明机器已经正常启动并且开放了SMB服务,可以进入正式的信息收集环节。别小看这两步,我在实际打靶过程中见过太多人因为没配hosts,导致后面Impacket工具报了各种奇怪的DNS错误,折腾半天才发现是解析问题。
1.2 端口扫描与指纹识别
接下来做全端口扫描。很多人习惯用默认的nmap快速扫描,只扫常见端口,这样很容易漏掉关键信息。对于域控类靶机,推荐直接用全端口加版本检测:
nmap -sS -sV -sC -p- 10.10.10.100 -oA nmap/active-sS是SYN半开扫描,速度快;-sV做版本探测;-sC跑默认安全脚本。全端口扫描可能会慢一点,但在靶机环境里值得等。扫描结果非常规整:
53/tcp open domain 88/tcp open kerberos-sec 135/tcp open msrpc 139/tcp open netbios-ssn 389/tcp open ldap 445/tcp open microsoft-ds 464/tcp open kpasswd5 593/tcp open http-rpc-epmap 636/tcp open ldapssl 3268/tcp open ldap 3269/tcp open globalcatLDAP 3389/tcp open ms-wbt-server 5985/tcp open http这批端口放在一起,几乎就是域控制器的标准画像。我整理了一张端口判断表:
| 端口 | 服务 | 判断依据 |
|---|---|---|
| 53 | DNS | DC必备的域名解析服务 |
| 88 | Kerberos | AD域控认证核心服务 |
| 389/636 | LDAP/LDAPS | 目录服务,域控标配 |
| 3268/3269 | 全局编录 | 域控GC角色独有 |
| 464 | kpasswd5 | Kerberos密码修改服务 |
| 445 | SMB | 后续渗透的核心入口 |
| 5985 | WinRM | 远程管理通道,拿到凭据后的登录路径 |
| 3389 | RDP | 远程桌面,备选入口 |
普通Windows工作站不会同时开放88、389、3268这些端口,只有DC(域控制器)才会有。看到这个端口组合,可以确定10.10.10.100就是active.htb域的域控,而且目标的主机名就是Active。
1.3 攻击面初判
在还没有任何凭据的情况下,对外开放的服务里真正值得优先关注的是445和5985。445端口的SMB服务在匿名环境下可以尝试共享枚举,这是最容易出现信息泄露的点;5985端口的WinRM虽然默认需要认证,但一旦后面拿到任何合法账户,它就是横向上域控的最短路径。
389端口的LDAP也值得留意,不过在没有凭据的环境下,匿名查询通常会受到限制,能查到的信息比较有限。所以下一阶段的重点,就落在SMB共享的匿名访问上。
2. SMB共享枚举:从Anonymous到Groups.xml
2.1 匿名枚举共享列表
域环境里SMB共享枚举是最基础也最容易被忽视的信息收集手段。这里用到的是smbclient自带的匿名登录模式:
smbclient -L //10.10.10.100 -N-N参数表示不询问密码,也就是完全匿名会话。如果目标开启了guest访问或者空会话,就能直接列出共享列表。也可以换crackmapexec来枚举:
crackmapexec smb 10.10.10.100 -u '' -p '' --shares输出结果里除了ADMIN$、C$、IPC$这些Windows默认共享之外,还有一个NETLOGON、一个SYSVOL,然后出现了一个非常扎眼的名字:Replication。
所谓Replication,字面意思是"复制、同步",这个共享绝不会是域控默认自带的。看到非标准共享名的第一反应应该是:这可能是一个备份目录或者同步副本,里面极有可能躺着域内的敏感文件。攻击者视角里,这种共享名就是我们常说的"信息泄露点"。
2.2 深入Replication共享翻文件
确认共享存在后,直接匿名登录进去:
smbclient //10.10.10.100/Replication -N进去之后先ls看一下结构,会看到一个active.htb文件夹,顺着往里走就能看到Policies目录。为了省事,可以直接开启递归再列一次目录:
smb: \> recurse ON smb: \> ls也可以使用smbmap做递归列出:
smbmap -H 10.10.10.100 -u '' -p '' -R Replication最终在路径下找到了一个经典文件:
Replication/active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Preferences/Groups/Groups.xml注意这个GUID,{31B2F340-016D-11D2-945F-00C04FB984F9}是Windows默认域策略的标准GUID,也就是说这个Replication共享里保存的,很可能是SYSVOL策略目录的一个副本。SYSVOL里的Groups.xml本身就是一个巨大的信息泄露点,这在真实内网里也非常常见。
用smbclient把它下载下来:
smb: \> get "active.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Preferences/Groups/Groups.xml" groups.xml读取文件内容后,关键部分长这样:
<Groups clsid="{3125E937-EB16-4b4C-9934-544FC6D24D26}"> <Group clsid="{...}" name="SVC_TGS" image="..." name="SVC_TGS"> <Properties action="U" newName="SVC_TGS" name="Administrator" fullName="" description="" cPassword="一串base64密文" changeLogon="false" noChange="false" ... /> </Group> </Groups>看到cPassword字段的那一刻,基本就等于拿到了明文密码的一半。因为这条密码是由域策略下发到域内所有机器上的,里面的用户是SVC_TGS,一看名字就知道是服务账户。
2.3 为什么说cPassword形同虚设
这里需要讲清楚一个背景。GPP全称是Group Policy Preferences,微软从Windows Server 2008开始引入了这套机制,让域管理员可以通过组策略下发本地用户、映射驱动器、计划任务等配置。为了支持"创建本地用户并设置密码"这个需求,微软就在策略XML里设计了一个cPassword字段。
问题在于,这个cPassword使用的加密方式非常离谱:它用AES-256-CBC算法加密,但用于加密的密钥不是随机生成的,而是直接写死在微软的公开文档里。也就是说,任何一个拿到Groups.xml的人,都可以用同一把公开密钥把里面的密码解出来。微软直到2014年才发布MS14-025公告承认这个问题,并强烈建议各组织清理域内所有GPP密码配置。
没错,这个"加密"在安全模型里基本等于明文存储。直到今天我参加企业内网攻防演练的时候,在SYSVOL共享里翻出Groups.xml并且成功解出域用户密码的情况依然时有发生。这个点对任何做域渗透的人来说都应该是刻在DNA里的常识。
3. GPP密码解密与凭据验证
3.1 使用gpp-decrypt一键解密
拿到cPassword值之后,解密工具在Kali里是现成的:
gpp-decrypt '那串base64密文'输出结果会这样显示:
[*] Using GPP still stands strong on Windows [+] Credential: ACTIVE\SVC_TGS : 明文密码解密过程背后就是AES-256-CBC配上公开密钥,所有cPassword的值都能用同一个密钥解开。如果你用的环境没有gpp-decrypt,也可以用Python的pycryptodome库写一段AES解密脚本实现同样的效果。
这里有一个非常实用的细节:解密出来用户名的格式是"域名\用户名",也就是ACTIVE\SVC_TGS。在后续使用Impacket工具的时候,用户名的格式必须写成active.htb/svc_tgs或ACTIVE/svc_tgs这种带域前缀的形式,不能只写svc_tgs,否则Kerberos认证会失败。
3.2 验证凭据有效性
拿到明文密码之后,不要急着满天飞地乱试,第一步是验证凭据的有效性。crackmapexec是干这个活最顺手的工具:
crackmapexec smb 10.10.10.100 -u svc_tgs -p '明文密码' --shares如果能正常返回共享列表,并且显示认证成功,那说明这个密码是真的。如果显示STATUS_LOGON_FAILURE,大概率是用户名的域前缀少了,或者密码本身就有大小写问题。
实际上这个凭据还有一个额外的利用价值:这台机器开放了5985端口,svc_tgs用户不一定在远程桌面用户组里,但WinRM的访问控制往往更宽松。实测下来,直接用svc_tgs是可以走evil-winrm登录上去的:
evil-winrm -i 10.10.10.100 -u svc_tgs -p '明文密码'登录成功后在SVC_TGS用户桌面里就能读取user.txt。不过这还不是终点,因为svc_tgs只是一个普通域用户,真正的目标是域管权限。后面要做的,就是拿这个普通用户凭据去撬动整个域。
4. Kerberoasting:从普通域用户到域管凭据
4.1 Kerberoasting的完整原理
把Kerberoasting讲透,要从Kerberos协议的工作方式说起。
在Kerberos体系里,一个用户请求某个服务的时候,流程是这样的:客户端首先向KDC发送AS-REQ请求自己身份的TGT,KDC验证用户密码用NT哈希加密返回TGT;客户端拿到TGT之后,再向KDC发起TGS-REQ请求某个SPN对应的服务票据,KDC验证TGT有效后,返回用服务账户密码哈希加密的TGS票据。
问题就出在这个TGS票据上。客户端需要的只是这个票据本身,票据内容对客户端来说是不可读的,但攻击者拿着票据完全不需要去解密它的内容,只需要把它保存下来,然后离线枚举可能的密码,重新计算出对应的票据加密结果做比对。换句话说,只要TGS票据是用服务账户的密码哈希加密的,这个票据就变成了一个可以用来离线爆破密码的"密码保险箱"。
什么情况下可以拿到某个账户的TGS票据?只要这个账户注册了SPN。管理员为了让某些服务支持Kerberos认证,会给服务账户注册一个SPN。如果这个"服务账户"恰好是域管账户,或者是一个高权限账户,那么任何知道合法域用户凭据的人,都可以向KDC请求这个高权限账户的TGS票据,然后拿回去离线破解。
Kerberoasting的核心攻击条件有三个:一是有任意一个合法的域用户凭据,二是存在注册了SPN的高价值账户,三是服务账户的密码强度不够。这台靶机上,前两个条件全部满足,剩下的就看字典给不给力。
4.2 枚举SPN并请求服务票据
现在凭据有了,下一步是枚举和请求。这里直接用Impacket工具包里的GetUserSPNs.py:
python3 GetUserSPNs.py active.htb/svc_tgs:'明文密码' -dc-ip 10.10.10.100 -request -outputfile active_hash.txt关键参数说明:
- active.htb/svc_tgs:密码是域账号和密码的完整格式
- -dc-ip指向域控IP,这里不写hostname而写IP能避开部分DNS解析问题
- -request表示请求并输出TGS票据
- -outputfile把哈希保存到文件里
命令执行之后,脚本先枚举域内的SPN,然后对每个SPN请求TGS票据。输出结果里能看到类似这样的信息:
ServicePrincipalName Name MemberOf active.htb/Administrator Administrator CN=Administrator,CN=Users,DC=active,DC=htb重点就是这里:域管账户Administrator居然注册了SPN。这意味着所有域用户都能合法地请求Administrator的服务票据,然后拿回去做离线破解。保存下来的哈希文件内容大致长这样:
$krb5tgs$23$*Administrator$active.htb$active.htb/Administrator*$xxxxxxxx这个格式就是hashcat的13100模式可以识别的格式。如果脚本执行出错,先检查hosts文件里有没有active.htb的解析,其次是确认系统时间和域控时间同步,Kerberos对时间漂移非常敏感,偏差超过5分钟就会报错。
4.3 hashcat离线爆破
TGS票据拿到之后,本地爆破环节登场。使用hashcat的13100模式:
hashcat -m 13100 active_hash.txt /usr/share/wordlists/rockyou.txt --show13100对应的就是Kerberoasting的TGS-REP哈希。rockyou.txt是Kali自带的最常用字典,体积不算大,但对这种场景已经够用了。如果第一次跑没出结果,不要急着换工具,先确认几个问题:
- 哈希文件里有没有多余的空格或乱行
- 字典路径是否正确
- 用
hashcat -m 13100 hash.txt --show确认确实还没破解成功 - 或者加规则再跑一轮,比如
hashcat -m 13100 hash.txt rockyou.txt -r /usr/share/hashcat/rules/best64.rule
如果还不行,换更大的字典比如SecLists里的Common-Credentials、或者xato-net-10-million-passwords-1000000.txt。在大部分靶机场景下,rockyou.txt就已经能出结果了。
破解结果会直接输出Administrator账户的明文密码。到这一步,其实已经把域管密码握在手里了,接下来就是如何登录的问题。
5. 权限接管:登录域控与Flag收割
5.1 使用evil-winrm登录域控
已知Administrator的明文密码,加上5985端口开放,最顺手的登录方式就是evil-winrm:
evil-winrm -i 10.10.10.100 -u Administrator -p '破解出来的密码'evil-winrm本质上是调用WinRM服务做远程管理,比RDP更轻量,比psexec更隐蔽,在靶机环境里体验很好。如果你所在的环境没有5985端口,psexec.py是另一个常见方案:
psexec.py active.htb/Administrator:'密码'@10.10.10.100psexec的原理是通过SMB的管理共享上传一个服务二进制,然后通过Windows服务控制管理器启动它来执行命令。两种方式效果一样,都是拿到SYSTEM权限级别的shell,不过evil-winrm平时用起来更顺手一些。
5.2 验证权限并读取Flag
登录成功之后第一件事就是确认身份:
whoami输出一般是active\administrator,说明当前会话已经是域管。再用ipconfig /all确认一下机器名和域名,确认无误就可以直接收割Flag了。
type C:\Users\Administrator\Desktop\root.txt这就是域控管理员桌面上的root flag。如果你之前已经用svc_tgs登录过WinRM,那user.txt应该已经提前拿到。如果还没拿,登录administrator后同样可以补齐:
type C:\Users\SVC_TGS\Desktop\user.txt到这里,完整攻击链走完了:匿名访问共享 → 翻到Groups.xml → 解密GPP密码 → 获得普通域用户 → Kerberoasting → 破解出域管密码 → 登录域控。整条链干净利落,没有一个系统漏洞被利用。
6. 常见问题与避坑技巧汇总
打靶过程中踩坑是常态,我把这个靶机以及同类域渗透场景里最容易踩的坑整理了一下,做成一个速查表:
| 问题现象 | 常见原因 | 解决办法 |
|---|---|---|
| nmap没扫到5985 | 没有做全端口扫描 | 改用-p-全端口扫描 |
| smbclient匿名登录被拒 | guest访问被禁用或者IPC$空会话受限 | 尝试-U guest、--no-pass,或者用crackmapexec辅助枚举 |
| Group.xml路径太长get失败 | 路径中的花括号或特殊符号被shell解析 | 用双引号包裹路径,或者用smbget递归下载 |
| gpp-decrypt报错 | base64串里包含特殊字符,被shell转义 | 用单引号包裹密文,或者把密文写入文件再传入 |
| GetUserSPNs.py请求TGS失败 | hosts解析缺失、时间不同步、用户名大小写错误 | 检查/etc/hosts,ntpdate同步时间,用户名写成active.htb/svc_tgs完整格式 |
| hashcat跑不出结果 | 字典太弱、哈希格式不对、没加规则 | 先确认$krb5tgs$23$开头,换rockyou,加best64规则重试 |
| evil-winrm连不上 | 5985端口没开放、用户名大小写错误、密码抄错 | 检查端口、确认域前缀、重新复制密码 |
除了表格里的问题,还有一个我特别想强调的原则:拿到非标准共享名后,不要只盯着单个文件翻。SYSVOL、Replication这种共享里除了Groups.xml,还可能藏着脚本、配置文件、临时备份,任何一个里面都可能留着硬盘密码或者自动化任务的明文凭据。在企业内网攻防里,我在SYSVOL共享里挖出过带数据库密码的PowerShell脚本,也在网络共享目录里翻到过管理员密码本。这个信息收集习惯一旦养成,渗透效率会提高一大截。
7. 关于这个靶机的一点个人总结
每次有人问"AD渗透怎么入门",我都会建议先把Active完整过一遍。这台机器的珍贵之处在于它的攻击链没有引入任何系统漏洞:没有永恒之蓝,没有MS17-010,没有任何提权CVE。有的只是三个几乎"人畜无害"的问题——SMB共享设置了不安全的访问控制,GPP密码看了等于没加密,域管账户注册了SPN。这三个问题单独拿出来危害都有限,串在一起就变成了从零到域管的完整路径。
这一点恰好也是现代企业内网安全的缩影:真正让你丢域控的往往不是精妙的0day,而是随手配置出的"小问题"在攻击者手里连成了大链。作为防守方,清理SYSVOL里的敏感文件、禁止高权限用户注册SPN、定期审计GPP遗留配置,每一条看起来都不起眼,实际都是在断攻击者的链。
最后分享一个我自己的变化:打完这台机器后,我对内网资产梳理的态度彻底变了。以前觉得SYSVOL这种目录天天见,没什么看头;现在凡是遇到域环境,我都会先翻一遍SYSVOL和所有非默认共享里的XML、脚本、配置文件。不是每次都能有收获,但每次有收获都是大收获。