ProxyShell利用分析2——CVE-2021-34523
0x00 前言
本文将要介绍ProxyShell中第二个漏洞的细节,分析利用思路。
0x01 简介
本文将要介绍以下内容:
- CommonAccessToken
- Exchange PowerShell Remoting
- 利用分析
0x02 CommonAccessToken
在上篇文章《ProxyShell利用分析1——CVE-2021-34473》提到,我没有找到通过参数指定EWS认证用户的方法,但是对于Exchange PowerShell Remoting,可以通过传入CommonAccessToken指定认证用户,访问Exchange PowerShell Remoting
1.定位参数传入方法
使用dnsSpy打开文件C:\Program Files\Microsoft\Exchange Server\V15\Bin\Microsoft.Exchange.Configuration.RemotePowershellBackendCmdletProxyModule.dll
依次定位到Microsoft.Exchange.Configuration.RemotePowershellBackendCmdletProxy
-> RemotePowershellBackendCmdletProxyModule
-> CommonAccessToken CommonAccessTokenFromUrl(string user, Uri requestURI, out Exception ex)
如下图
可以看到,通过X-Rps-CAT作为参数传入CommonAccessToken
传递参数的方式可以参考下图
2.CommonAccessToken的生成
使用dnsSpy打开文件C:\Program Files\Microsoft\Exchange Server\V15\Bin\Microsoft.Exchange.Net.dll
依次定位到Microsoft.Exchange.Security.Authorization
-> CommonAccessToken
-> Deserialize(Stream stream)
如下图
在起始位置下断点
执行命令:
C:\Windows\System32\inetsrv\appcmd list wp
找到applicationPool:MSExchangePowerShellAppPool对应的进程pid
附加到该进程上,等待一段时间,能够捕获到正确的格式
此时,选中Locals中的binaryReader,依次按鼠标右键 -> 选择Show in Memory Window -> Memory 1,如下图
查看该内存区域附近的内容,捕获到了正确的格式,如下图
经过分析,捕获的内容结构如下:
V + 版本(\x01\x00) + T + 类型长度(\x07) + 类型(Windows) + C + \x00 + A + 认证类型长度(\x08) + 认证类型(kerberos) + L + 用户名长度 + 用户名 + U + sid长度 + sid + G + 组个数(4字节,little endian,\x06\x00\x00\x00) + 分隔符\x07\x00\x00\x00 + 组1长度 + 组1 + 分隔符\x07\x00\x00\x00 + 组2长度 + 组2 + 分隔符\x07\x00\x00\x00 + 组3长度 + 组3 + 分隔符\x07\x00\x00\x00 + 组4长度 + 组4 + 分隔符\x07\x00\x00\x00 + 组5长度 + 组5 + 分隔符\x07\x00\x00\x00 + 组6长度 + 组6 + E + \x00\x00\x00\x00
对于认证类型长度,长度为1字节,字节序为little endian,内容为认证类型的字符串长度,例如认证类型为basic,那么认证类型长度为\x05
在Python代码实现上,计算认证类型长度可以使用如下代码:
authtype = "kerberos"
authlen = (len(authtype)).to_bytes(1, 'little')
经过实际测试,构造CommonAccessToken时,有以下技巧:
- 用户名只要是合法用户即可,可以使用默认邮箱
- sid为关键内容,代表认证用户的权限,如果需要认证为管理员用户Administrator,这里的格式为S-1-5-domain-500
- 如果域环境禁用了管理员用户administrator,仍然能够认证成功
- group sid只要是可用的即可,例如随便指定一个S-1-1-0
关于sid的格式可以参考:
https://docs.microsoft.com/en-US/windows/security/identity-protection/access-control/security-identifiers
3.CommonAccessToken的验证
在以正确的方式传入参数X-Rps-CAT,如果CommonAccessToken也有效,那么在访问/Powershell时会返回状态码200
0x03 Exchange PowerShell Remoting
参考资料:
https://docs.microsoft.com/en-us/powershell/module/exchange/?view=exchange-ps
在之前的文章《渗透基础——从Exchange服务器上搜索和导出邮件》介绍过Exchange PowerShell Remoting的相关用法,这里做一些补充
1.默认设置下,所有域用户都可以连接remote PowerShell
常用命令:
查看用户是否具有访问remote PowerShell的权限:
Get-User -Identity <UserIdentity> | Format-List RemotePowerShellEnabled
列出所有用户是否具有访问remote PowerShell的权限:
Get-User -ResultSize unlimited | Format-Table -Auto Name,DisplayName,RemotePowerShellEnabled
列出具有访问remote PowerShell权限的用户:
Get-User -ResultSize unlimited -Filter 'RemotePowerShellEnabled -eq $true'
删除指定用户的remote PowerShell访问权限:
Set-User -Identity <UserIdentity> -RemotePowerShellEnabled $false
开启指定用户的remote PowerShell访问权限:
Set-User -Identity <UserIdentity> -RemotePowerShellEnabled $true
如果想要执行管理Exchange服务器的命令,用户需要成为Organization Management
组的成员
查看Organization Management
组成员的命令如下:
Get-RoleGroupMember "Organization Management"
2.连接remote PowerShell的内置方法
Powershell示例命令如下:
$User = "test\user1"
$Pass = ConvertTo-SecureString -AsPlainText Password1 -Force
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $User,$Pass
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exchangeserver.test.com/PowerShell/ -Authentication Kerberos -Credential $Credential
Import-PSSession $Session -AllowClobber
Get-RoleGroupMember "Organization Management"
Remove-PSSession $Session
该方法默认只能从域内主机发起连接,不支持从域外连接
0x04 利用分析
1.CommonAccessToken的格式
用户sid需要设置成Administrator,默认为S-1-5-domain-500
这里可以选择其他用户的sid,但需要满足用户位于”Organization Management”组中
2.使用PyPSRP连接remote PowerShell的一个问题
使用PyPSRP执行Powershell命令时,无法执行添加用户的操作
这是因为传递Password的值时需要执行Powershell命令convertto-securestring
,而convertto-securestring
不是Exchange PowerShell Remoting支持的命令
如果选择执行Powershell脚本,由于默认Powershell策略的限制,会提示无法执行Powershell脚本
0x05 小结
对于ProxyShell中的第二个漏洞CVE-2021-34523,结合利用思路,不难猜出最简单粗暴的防御方法:将”Organization Management”组内的用户清空,就可以防止攻击者执行高权限的Exchange Powershell命令