type
status
date
slug
summary
tags
category
icon
password
最后编辑时间
Apr 20, 2023 02:13 PM
漏洞编号
No.
同步状态
状态
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)捕获异常
执行成功时堆栈

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

参考
- 作者:3R1C
- 链接:https://notion-3r1c.vercel.app/article/123
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。