简介
TabShell(CVE-2022-41076)是12月份补丁的一个PowerShell的漏洞。这个漏洞允许攻击者在受限的PowerShell环境中逃逸出受限的环境执行任意命令。在Exchange Server的场景中,可以用于在域内提权到SYSTEM权限。
漏洞软件:PowerShell
前提条件:已知低权限账户的用户名和密码
漏洞效果:逃逸出受限环境。在Exchange Server中可以提权到SYSTEM权限。
影响范围: 没打2022年12月份补丁之前的所有Windows版本。
复现环境
笔者这里搭建了ExchangeServer2016CU12进行漏洞复现。操作系统为Windows Server 2016。
背景知识
Language Mode
Language Mode定义了PowerShell Session所能做的能力,例如能执行哪些cmdlet。Language Mode有四种。
-
FullLanguage 可以执行所有的命令,默认的PowerShell Session是这个模式
-
RestrictedLanguage 为Windows RT设计,现在被弃用了。
-
ConstrainedLanguage 只允许基本的操作(循环、分支条件、字符串等),只允许有限类型的对象。
-
NoLanguage 不允许运行脚本或者定义变量,只能执行基本的命令和cmdlet。
Exchange Server提供的PowerShell接口是NoLanguage模式,所以只能执行相当有限的cmdlet。
Tab Expansion
Tab Expansion是用来自动补全的的功能。例如按下Tab键之后,PowerShell自动补全。Tab Expansion功能是用内部的TabExpansion
和TabExpansion2
函数实现的。
根因分析
Exchange Server
上提供的远程powershell功能是一个受限的powershell,只有有限的powershell命令,一些危险的命令都没有提供,例如Start-Process
。
在创建PowerShell Session的时候(通过New-PSSession
),可以指定WSManStackVersion
参数。当值小于3的时候,Commands里会添加TabExpansion
函数。
TabExpansion
TabExpansion
脚本可以参考gist地址:https://gist.github.com/rskvp93/4158ac74eb9b583e7577f9cf4d72e155。下面摘出了关键的部分。TabExpansion
有两个参数line
和lastword
。
该函数会首先根据lastword
进行switch判断,当lastword
满足如下的正则表达式时,即以-
开头,后面跟若干字母数字,这一步很好满足,例如传入-test
。然后该函数就会把参数line
根据|;=
字符分割,并把分割的数组的最后一个赋值给$_command
变量。
后面会调用Get-Command
命令,把$_command
作为Name
的参数,这里的Name
就可以攻击者控制。下面需要的攻击就是如何通过Get-Command
的Name
参数达到执行任意PowerShell命令。
Get-Command
的用法很多,其中的一个用法是Name
参数后跟的是[Module path][cmdlet]
的形式,这样可以查看某个模块里的某个cmdlet
。读者可能看到这里就发现一个问题Get-Command
会不会自动载入这个模块。Get-Command
的逻辑极其复杂,笔者这里不去分析其完整的实现,有兴趣的读者可以去dnspy或github查看源码。笔者这里只分析最关键的。Get-Command
有一个地方会调用AutoloadSpecifiedModule
函数,这个函数会调用Import-Module
命令,其中的Name
参数用户是可以指定的,那么这里就是导入目标模块的地方。笔者在IIS的Powershell进程中AutoloadSpecifiedModule
下断点,通过栈回溯可以看到Get-Command
的实现最后调用到了这里。
下面笔者在普通的powershell中去调用Get-Command
命令复现,来观察能不能通过Get-Command
导入一个Module。这里的PSMBin.dll
是笔者自己写的一个Powershell的模块,其中只有一个命令Get-Greeting
。通过下面的命令可以导入这个模块,并使用Get-Greeting
命令。
读者看到这里可能会问为什么不直接使用Get-Command
命令,而用TabExpansion
去间接调用Get-Command
呢。笔者在Exchange Server的远程powershell中测试,可以看到直接使用Get-Command
是无法导入目标模块的。
调试发现在TryModuleAutoLoading
函数中会判断commandOrigin
是不是来自于内部,只有来自内部才会调用AutoloadSpeficiedModule
导入目标模块。而TabExpansion
是内部调用,满足这个情况。
复现效果
笔者对Exchange Server进行攻击,执行mspaint.exe,效果如下。
patch分析
微软直接将PowerShell里的TabExpansion删掉,参考github地址:https://github.com/PowerShell/PowerShell/commit/eb612c0be8e99c5d804e14c94f8973bbbc7d19c3。
参考引用
-
https://blog.viettelcybersecurity.com/tabshell-owassrf/
-
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_language_modes?view=powershell-7.3
-
https://gist.github.com/testanull/518871a2e2057caa2bc9c6ae6634103e
-
https://gist.github.com/rskvp93/4158ac74eb9b583e7577f9cf4d72e155
-
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/get-command?view=powershell-7.3
-
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_tab_expansion?view=powershell-7.3
本公众号发布、转载的文章所涉及的技术、思路、工具仅供学习交流,任何人不得将其用于非法用途及盈利等目的,否则后果自行承担!
原文始发于微信公众号(华为安全应急响应中心):[漏洞分析] CVE-2022-41076 TabShell 漏洞分析