🗿Exchange越权执行命令漏洞CVE-2022-41076复现分析
type
status
date
slug
summary
tags
category
icon
password
最后编辑时间
Apr 20, 2023 02:13 PM
order
漏洞编号
Author
环境漏洞详情(CVE-2022-41076)dnspy调试三步攻击过程第一步 目录穿越加载外部dll(Import-Module)第二步 加载外部dll的cmdlet(Invoke-Expression)第三步 cmdlet执行其他命令白名单cmdlet调用参考
PS:简单记录一下过程中的关键步骤和数据,相关知识点未作科普,言之无文
环境
Windows Server 2016 x64
Exchange Server 2016 CU21 build15.1.2308.27
已知一个普通用户类型的Exchange账号密码
漏洞详情(CVE-2022-41076)
- 正常功能使用
普通exchange用户可以创建受限的远程powershell会话,此会话仅能运行白名单Exchange cmdlet+一些核心cmdlet,如Get-Command,Get-Mailbox,Get-Help等,代码如下
(参数备注:123123 为 用户密码,ceshi\Administrator 为 域\用户名,winser2016.ceshi.com 为 主机名.域名)

- 漏洞攻击过程
创建 powershell 会话时,攻击者传递
ApplicationArguments参数WSManStackVersion<3.0,在 initialSessionState 中启用公共 TabExpansion 函数,最终可以在受限的 powershell 会话中越权调用它。此命令可以通过
-line参数导入、加载任意模块,在此参数中利用路径遍历从文件系统中加载任意dll模块导入当前对话,自此可以不受限制的使用powershell危险的cmdletInvoke-Expression。利用代码如下
对应
w3wp.exe 进程命令行参数dnspy调试
- 路径
C:\Windows\System32\inetsrv下,cmd命令appcmd list wp查看iis进程

- dnspy附加对应进程(可通过POC起进程时其父w3wp.exe进程的命令行确定),调试→附加到进程,根据pid附加
MSExchangePowerShellAppPool的w3wp.exe进程

- 调试→窗口→模块,打开模块窗口,此处有两个
System.Management.Automation.dll,分别调试在DefaultDomain中和独立的Powershell appdomain中,经过下断点测试,参数传递的是独立app域中的dll,双击加载
C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll

从分析文章 OWASSRF + TabShell 漏洞利用链 (viettelcybersecurity.com) 初步确定关键函数是加载外部模块的函数
LoadBinaryModule(Microsoft.PowerShell.Commands.ModuleCmdletBase) 
- 打下断点启动调试

发poc,成功断下

三步攻击过程
第一步 目录穿越加载外部dll(Import-Module)
在
System.Management.Automation.CommandDiscovery类和LookupCommandInfo方法中。首先使用
TryNormalSearch 方法,但如果找不到命令(null),则将调用 TryModuleAutoLoading 方法。在 TryModuleAutoLoading 方法中,模块名称(text2 变量)将从 commandName 解析然后模块将使用自动加载指定模块方法加载dll模块和cmdlet
在
AutoloadSpecifiedMoudle方法cmdlet赋值为 Import-Module
接着来到
LoadBinaryModule 方法,查看局部变量获取到传入的 moduleName 和 fileName ,在此处加载dll
堆栈



返回到
processrecord
第二步 加载外部dll的cmdlet(Invoke-Expression)
在
System.Management.Automation.CommandDiscovery类的LookupCommandInfo方法在
System.Management.Automation.dll!System.Management.Automation.CommandDiscovery.TryModuleAutoLoading(string commandName, System.Management.Automation.ExecutionContext context, string originalCommandName, System.Management.Automation.CommandOrigin commandOrigin, System.Management.Automation.CommandInfo result, ref System.Exception lastError) (IL≈0x0182, Native=0x00007FFC4D902FD0+0x40D) 打下断点
这里拿到
commandinfo为Invoke-Expression
此时的调用栈

后续CreateCommandProcessor

堆栈

第三步 cmdlet执行其他命令
接着上一步获取到iex的参数为

堆栈

返回值commandProcessorBase

堆栈

加载cmdlet后,在
Microsoft.Powershell.Commands.Utility.dll(appdomain)模块中 Microsoft.Powershell.Commands.InvokeExpressionCommand类 断下,逐过程调试,在 System.Management.Automation.dll!System.Management.Automation.CommandProcessor.ProcessRecord() (IL=0x0175, Native=0x00007FFC4D86B9B0+0x50D) 获取到cmdlet的参数,即执行的命令
此时的调用栈

逐语句跟进到
InvokeWithPipeLmpl ,经 RunVoid1 来到 Interpreter 的Run函数
执行命令

完整堆栈


最后返回值

继续调试另一个iex命令

解析iex命令的时候对new-object这个cmdlet又进行了lookup

此时调用栈


之后来到doexecute

此时堆栈


白名单cmdlet调用
TryNormalSearch断点
接着来到这,在
System.Management.Automation.CommandProcessor类的ProcessRecord方法打断点
此时的调用栈

最后经过
Run函数(System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction)捕获异常
执行成功时堆栈

执行完命令结束程序时的堆栈

参考
Loading...