anyue3
暗月靶场项目三复盘:从外网入口到内网 MSSQL 命令执行
这次打的是暗月靶场项目三。整体链路不是单点漏洞,而是从外网 Web 漏洞开始,逐步拿到后台、写入 WebShell、进入内网,再利用内网 MSSQL 弱口令和 xp_cmdshell 获得命令执行权限。
当前已经走通的链路可以概括为:
1 | |
外网入口
外网入口主机是:
1 | |
后续确认这台机器有双网卡:
1 | |
也就是说,web1 不只是外网入口,同时也是进入 192.168.112.0/24 内网段的跳板。
一开始看过第一个系统的 SQL 注入,但这个点不能跨库查询,也不能直接 getshell,所以没有继续浪费时间。真正有价值的入口是 TomExam 的 SQL 注入。
TomExam 注入点:
1 | |
布尔判断现象很明确:
1 | |
这个注入点可以跨库查询,所以后面用它去读 jspXCMS 的管理员数据。
跨库读取 jspXCMS 管理员
通过 TomExam SQL 注入跨库读到了 jspXCMS 的管理员账号信息。
已知管理员账号:
1 | |
对应 hash 和 salt:
1 | |
jspXCMS 的密码算法也确认过,大致是:
1 | |
后台地址:
1 | |
中间试过低权限账号:
1 | |
这个账号能登录,但没有 super 角色,访问文件管理会触发 Shiro 权限错误:
1 | |
所以最终使用的是:
1 | |
jspXCMS 后台 getshell
getshell 走的不是普通上传接口,而是 jspXCMS 后台的站点文件管理。
关键接口:
1 | |
关键参数:
1 | |
这里踩过一个坑:在 Git Bash 环境下,/jsp 会被 MSYS 自动转换成 Windows 路径,导致服务端收到错误路径。解决方式是在 curl 前加:
1 | |
上传成功后,内部路径是:
1 | |
但由于 jspXCMS 的 JSP 映射规则,外部访问路径变成:
1 | |
简单 JSP 命令 shell 的参数是:
1 | |
验证结果:
1 | |
返回:
1 | |
这一步说明已经拿到 web1 上的命令执行,并且权限是本地管理员。
Godzilla WebShell
后面又上传了 Godzilla JSP shell。
本地文件:
1 | |
远程地址:
1 | |
Godzilla 配置:
1 | |
直接访问 for.jsp 页面空白是正常的,因为它不是普通 Web 页面,而是需要 Godzilla 客户端按协议交互。
Godzilla 代理启动日志:
1 | |
这说明本机开了一个 SOCKS 代理:
1 | |
Cobalt Strike 监听排查
Cobalt Strike 的 TeamServer 跑在 WSL 中。监听地址排查过一轮,最终确认这次靶场应该使用本机在靶场网段里的地址:
1 | |
有效 Listener 配置:
1 | |
之前考虑过 Windows portproxy 和 10.8.0.6 的链路,但本次实际能回连的是 192.168.111.25。后面会话正常回来,证明这个监听地址选择是对的。
内网发现
进入 web1 后,开始看内网。
web1 网卡信息:
1 | |
net view 曾返回 6118,这个错误不能说明内网没有主机,只能说明浏览列表不可用,可能是服务、权限或防火墙限制。
通过扫描和验证,发现真实内网主机:
1 | |
通过 Godzilla SOCKS 扫描时遇到过假阳性,例如 192.168.112.1 显示大量端口开放。这个结果不可信,判断是代理行为导致的误报。后面主要以从 web1 直接探测到的结果为准。
MSSQL 弱口令和 xp_cmdshell
192.168.112.23 的 MSSQL 端口开放:
1 | |
已知凭据:
1 | |
这里需要注意,sa/admin123 是 MSSQL 凭据,不是 Windows 系统账号。所以不能拿它去做 Cobalt Strike 的 spawnas。
之前试过类似:
1 | |
结果失败 1326,原因就是凭据类型错了。
为方便操作 MSSQL,写了一个辅助脚本:
1 | |
脚本逻辑是:通过 web1 上的 JSP 命令 shell 执行 PowerShell,再由 web1 去连接 192.168.112.23 MSSQL,启用并调用 xp_cmdshell。
默认参数:
1 | |
验证命令:
1 | |
返回:
1 | |
这说明:
1 | |
也确认过该身份具备:
1 | |
从漏洞影响角度,这一步已经很关键:外网入口最终导致内网 MSSQL 主机命令执行。
server2012 和域环境信息
在 .23 上执行 ipconfig /all 后,虽然中文输出乱码,但关键信息已经能看出来。
主机信息:
1 | |
网卡信息:
1 | |
因此 .23 也是双网卡主机:
1 | |
域信息:
1 | |
10.10.10.139 高概率是域控或至少是域内 DNS。
访问域控共享的结果
尝试从 .23 访问域控管理共享:
1 | |
失败。
进一步测了几个路径:
1 | |
这个结果说明,不是 C: 下面没东西,而是当前身份没有权限访问域控共享。
正常情况下,c$ 如果能访问,至少应该能看到 Windows、Users 等目录。现在连目录都列不出来,说明不是 flag 不存在,而是权限不够。
另外,SYSVOL 通常域用户可读,但当前 nt service\mssqlserver 上下文也访问失败,说明当前上下文并不是一个可用的域用户访问上下文。
.23 的 80 端口
.23 还开放了 80 端口,但没有找到可直接写入的 Web 根目录。
检查结果:
1 | |
显示:
1 | |
PID 4 是 System,说明 80 端口更像是 HTTP.sys 或某个系统服务注册的 HTTP 监听。
其他检查结果:
1 | |
因此暂时不能把 .23:80 当成普通 IIS 站点来写 WebShell。
文件下载问题
曾尝试让 .23 从本机 192.168.111.25:8000 下载文件,结果失败。原因很合理:.23 在 192.168.112.0/24 和 10.10.10.0/24,它不一定能访问攻击机的 192.168.111.25。
更合理的思路是让 .23 访问 web1 的内网地址:
1 | |
因为 .23 和 web1 的内网网卡都在 192.168.112.0/24。
当前已知资产
本地文件:
1 | |
WebShell 地址:
1 | |
MSSQL 操作方式:
1 | |
当前结论
这次已经完成了一条从外网入口到内网命令执行的完整链路:
1 | |
当前还没有拿到域控权限。访问 \\10.10.10.139\c$ 和 SYSVOL 都失败,说明当前 MSSQL 服务身份没有可用的域访问权限。
如果从报告角度看,这条链已经足够有价值:它证明了外网漏洞可以一路打到内网 MSSQL RCE,并且可以发现域环境。后续继续深入的方向应该是从 .23 本机寻找域凭据、本机提权点或配置泄露,而不是直接硬读域控管理共享。
Cobalt Strike 上线
拿到 MSSQL 命令执行后,下一步是建立更稳定的 C2 通道。之前的 Godzilla WebShell 和 xp_cmdshell 都可以执行命令,但 Cobalt Strike beacon 提供更完善的后渗透功能。
TeamServer 监听配置
CS TeamServer 运行在 WSL 中,监听地址的选择很关键。这次靶场的网络拓扑是:
1 | |
通过测试确认,攻击机可以 ping 通 192.168.111.20 (web1),说明通过 VPN 可以访问靶场网络。因此 CS 监听器配置为:
1 | |
Web1 beacon 上线
生成 beacon payload 后,通过 jspXCMS 后台文件管理上传到 web1:
1 | |
通过 Godzilla WebShell 执行 beacon,成功回连到 CS。权限是 web1\administrator,说明是本地管理员权限。
内网 MSSQL 代理访问
有了 web1 的 beacon 后,可以通过 SOCKS 代理访问内网。在 CS 中执行:
1 | |
这会在本地 127.0.0.1:64145 开启一个 SOCKS4a 代理,流量通过 beacon 转发到 web1,再由 web1 访问内网。
配置 WSL 中的 proxychains4:
1 | |
通过代理连接 MSSQL:
1 | |
成功连接到 192.168.112.23 的 MSSQL,启用 xp_cmdshell:
1 | |
返回 nt service\mssqlserver,确认命令执行可用。
Server2012 beacon 上线
现在的问题是,.23 在内网 DMZ 段 (192.168.112.23),它不能直接访问外网的 CS 监听器。需要通过 web1 作为跳板。
网络连通性测试
先确认 .23 能访问哪些地址。通过 xp_cmdshell 测试:
1 | |
结论:.23 只能访问 192.168.112.20 (web1 的 DMZ 接口),不能访问外网段。
配置 CS Pivot
CS 的 Pivot 功能(中文版叫”转发上线”)可以让内网机器通过已有 beacon 上线。
在 CS 中,右键 web1 的 beacon → 转发上线 → 监听器:
1 | |
生成连接到这个监听器的 payload beacon_tb.exe。
传输并执行
通过 web1 中转传输 beacon 到 .23。先用 Godzilla 上传 beacon_tb.exe 到 web1 的 Web 根目录:
1 | |
然后在 .23 的 beacon 中下载(此时还没有 .23 的 beacon,通过 xp_cmdshell 操作):
1 | |
执行 beacon:
1 | |
CS 中看到新的 beacon 上线,来自 .23 (192.168.112.23),权限是 nt service\mssqlserver。流量链路是:
1 | |
提权尝试
当前权限是 nt service\mssqlserver,虽然有 SeImpersonatePrivilege 特权,但不是本地管理员。尝试提权以获得更高权限。
CS 内置提权方法
CS 提供了多种内置的提权方法。在 beacon 中尝试:
1 | |
失败,错误 ERROR_ACCESS_DENIED。这个方法需要能够写入 ADMIN$ 共享和操作服务控制管理器,当前权限不足。
继续尝试其他方法:
1 | |
Potato 提权尝试
由于有 SeImpersonatePrivilege 特权,理论上可以使用 Potato 类漏洞(SweetPotato, GodPotato)提权到 SYSTEM。
尝试上传 potato.exe 到 .23:
1 | |
执行提权:
1 | |
没有看到新的 SYSTEM 权限 beacon 上线。Server 2012 可能已经打了补丁,或者工具版本不兼容。
放弃提权,继续攻击
多次提权尝试都失败了。但实际上,ZeroLogon 攻击是网络层面的协议攻击,不需要本地 SYSTEM 权限。当前的 nt service\mssqlserver 权限足够执行命令和网络操作,决定直接用当前权限继续。
ZeroLogon 攻击
ZeroLogon (CVE-2020-1472) 是 Netlogon 远程协议的权限提升漏洞,可以将域控的机器账户密码重置为空。
网络连通性确认
.23 有两个网卡:
1 | |
测试能否访问域控:
1 | |
成功,0% 丢失,延迟 <1ms。说明 .23 可以正常访问域控。
传输 SharpZeroLogon
通过 web1 中转的方式传输工具。用 Godzilla 上传 SharpZeroLogon.exe 到:
1 | |
在 .23 的 beacon 中下载:
1 | |
下载成功(约 8.5KB)。
执行 ZeroLogon 攻击
先测试漏洞是否存在:
1 | |
返回:
1 | |
确认漏洞存在。执行实际攻击,重置密码:
1 | |
输出:
1 | |
成功!域控机器账户 ad01$ 的密码已重置为空。空密码的 NTLM hash 是 31d6cfe0d16ae931b73c59d7e0c089c0。
DCSync 获取域管凭据
ZeroLogon 攻击成功后,可以使用空密码的 DC 机器账户执行 DCSync,从域控复制所有用户的凭据。
配置 SOCKS 代理
之前的 SOCKS 代理是在 web1 的 beacon 上开启的 (端口 64145),但 web1 不能访问 10.10.10.139 (域控)。需要在 .23 的 beacon 上开启代理,因为 .23 在域控的同一网段。
在 CS 中,选择 .23 的 beacon:
1 | |
输出:
1 | |
修改 proxychains 配置:
1 | |
执行 DCSync
使用 impacket 的 secretsdump.py,通过空密码进行 DCSync:
1 | |
代理连接成功:
1 | |
虽然一开始有 ACCESS_DENIED 错误,但继续执行后成功 dump 了域凭据:
1 | |
成功获取关键信息:
- Administrator NTLM hash:
81220c729f6ccb63d782a77007550f74 - AD01$ NTLM hash:
31d6cfe0d16ae931b73c59d7e0c089c0(确认是空密码) - krbtgt hash 和其他域用户的 hash
还获取了 Kerberos 密钥(AES256, AES128, DES)。
Pass-the-Hash 登录域控
有了 Administrator 的 NTLM hash,可以使用 Pass-the-Hash 技术登录域控,无需知道明文密码。
使用 impacket 的 wmiexec.py,添加 -codec gbk 参数避免中文乱码:
1 | |
成功登录域控,获得一个 WMI 命令 shell,权限是 NT AUTHORITY\SYSTEM。
搜索 flag:
1 | |
或直接查看常见位置:
1 | |
成功获取 flag!
完整攻击链总结
这次从外网入口到域控提权的完整链路:
1 | |
关键技术点
网络分段和代理技术
这次靶场最大的特点是网络分段清晰:
- 外网段 (192.168.111.x):攻击机可直接访问
- DMZ 段 (192.168.112.x):通过 web1 中转
- 内网段 (10.10.10.x):通过 .23 中转
必须根据目标所在网段选择正确的 SOCKS 代理:
- 访问 DMZ (192.168.112.x):使用 web1 的代理
- 访问内网域控 (10.10.10.x):使用 .23 的代理
这也是为什么一开始 DCSync 失败的原因:用了 web1 的代理去访问域控,web1 根本访问不到那个网段。
CS Pivot 的应用
当内网机器无法直接访问 CS 监听器时,Pivot (转发上线) 是标准解决方案。流量链路:
1 | |
在中文版 CS 中,这个功能叫”转发上线”,配置很简单,但要注意监听地址要用内网机器能访问的地址。
ZeroLogon 的威力
ZeroLogon (CVE-2020-1472) 是一个非常强大的漏洞:
- 无需任何凭据
- 可以从网络层面攻击
- 直接将 DC 机器账户密码置空
- 之后可以用空密码执行 DCSync
但有两个注意点:
- 参数格式:SharpZeroLogon 直接用 FQDN (
ad01.sec123.cnk),不需要复杂的参数 - 代理路由:攻击 DC 的流量必须从能访问 DC 的机器发出 (.23)
提权不是必须的
开始以为必须提权到 SYSTEM 才能继续,但实际上:
- ZeroLogon 是网络攻击,不需要本地高权限
- DCSync 通过代理执行,本地权限不重要
- 文件传输可以选择有权限的目录
nt service\mssqlserver 权限虽然不是管理员,但足够完成整个攻击链。
工具和技巧
文件传输
当 beacon 无法直接上传文件(权限不足或网络问题),可以通过 web 服务器中转:
- 上传到 web1 的 HTTP 根目录
- 目标机器用 certutil 下载
1 | |
proxychains4 配置
proxychains 是 Linux 下强大的代理工具,配置简单:
1 | |
可以让任何命令行工具通过 SOCKS 代理运行,非常适合配合 impacket 工具使用。
impacket 工具链
这次用到了 impacket 的三个工具:
- mssqlclient.py: 连接 MSSQL,启用 xp_cmdshell
- secretsdump.py: 执行 DCSync,dump 域凭据
- wmiexec.py: Pass-the-Hash 登录,获得命令 shell
都支持通过 proxychains 代理使用,且 -codec gbk 参数可以解决中文乱码问题。
反思
这条链路验证了一个完整的域渗透流程:外网 SQL 注入 → WebShell → C2 上线 → 内网横向 → 域漏洞利用 → 域管权限。
关键是理解网络拓扑和合理利用代理。每一步都要确认当前位置能访问目标,选择正确的代理或跳板。提权虽然好,但不是所有场景都必须,要根据实际目标选择最有效的路径。