缩放会议默认受6位数字密码保护,即最多100万个密码。我在Zoom web客户端中发现了一个漏洞,由于CSRF损坏且没有速率限制,该漏洞允许检查会议密码是否正确。
这使得攻击者可以在几分钟内尝试所有100万个密码,并获得访问其他人的私人(受密码保护的)Zoom会议的权限。
这也提出了一个令人不安的问题,即其他人是否已经在潜在地利用此漏洞来监听他人的电话(例如,英国内阁会议!)。
我向Zoom报告了这个问题,他很快让Web客户端离线来解决问题。他们似乎通过要求用户登录才能加入Web客户端中的会议,并将默认会议密码更新为非数字和更长的密码,从而缓解了这一问题。
3月31日,鲍里斯·约翰逊(Boris Johnson)在推特上表示,他将主持有史以来第一次数字内阁会议。我是注意到屏幕截图包含Zoom会议ID的许多人之一。Twitter上有很多人说他们正试图加入,但Zoom默认情况下会用密码保护会议(当政府使用Zoom进行辩护时就指出了这一点)。
在尝试加入后,我想看看是否能破解Zoom私人会议的密码。在接下来的几天里,我花了一些时间对Web客户端Zoom Provide的端点进行反向工程,发现我能够迭代所有可能的默认密码来发现给定私人会议的密码。
在试图加入内阁会议后,我浏览了一下Zoom应用程序,注意到默认密码是6位数字,这意味着最多有100万个密码。
密码安全的一个相当标准的原则是对密码尝试进行速率限制,以防止攻击者迭代候选密码列表并尝试所有密码。我以为Zoom会这么做,但还是决定再检查一遍。
我决定瞄准Zoom的网络客户端,但我的发现也适用于通过该应用程序的所有版本发起和进行的会议。
当用户创建新会议时,自动缩放功能会在表单(下面是虚拟数据)中生成一个供用户加入的链接:
Https://zoom.us/j/618086352?pwd=SE5OWjE6UDhwaDVJR3FJRzUyZUI3QT09它包含会议ID和自动生成的密码。我相信此密码是6位数字密码的散列版本,但我也发现Web客户端端点可以接受将其替换为6位数字版本,因此我们可以忽略散列版本,而专注于数字版本。
如果您删除pwd参数,然后访问Web客户端加入链接(https://zoom.us/wc/join/618086352),然后您将看到登录屏幕:
这似乎触发了一个XHR GET请求,然后将您带到另一个页面。
当您第一次打开任何没有现有cookie的Web客户端页面时,会设置一个cookie,其中包含一个GUID。这似乎是您的匿名用户ID。
如果您填写了用户/通行证表单,但尚未完成隐私协议,您将被重定向至该表单。要完成它,只需向给定端点发出一个简单的GET请求,该端点包含您的GUID。在此步骤中发送了一个CSRF HTTP标头,但是如果省略它,那么无论如何请求似乎仍然工作得很好。
当您提交用户名和密码时,无论密码是否正确,您都会被302重定向到另一个页面。如果您没有完成隐私政策,您将得到200个回复。
重定向将把您带到一个新页面,该页面似乎知道服务器端您的GUID之前是否输入了正确的密码。即上一步存储状态服务器端标记您是否获得了正确的密码。
CSRF令牌上的故障使得它比其他情况下更容易被滥用,但是修复它并不能提供更多的保护来抵御这种攻击。
这个过程有点复杂,难以实现自动化,这可能就是以前没有详细研究过这个端点的原因。我跳过了一些细节,比如需要从一个请求保存到另一个请求的参数,但它们对于理解主要问题并不重要。
关于上述过程需要注意的重要一点是,对于重复密码尝试没有速率限制(每个HTTP请求包括2个HTTP请求-一个提交密码,后续请求检查服务器是否接受密码)。但是,速度受到发出HTTP请求的速度的限制,HTTP请求具有自然的延迟,这将使破解密码成为一个缓慢的过程;服务器端状态意味着您必须等待第一个请求完成,然后才能发送第二个请求。
但是,我们应该注意到状态是根据提供的GUID存储的,您可以通过发送不带cookie的HTTP请求来向服务器请求任意数量的GUID。这意味着我们可以请求一批GUID,然后将它们之间可能的100万个密码分块,并并行运行多个请求。
我把一些(相当笨重的)Python放在一起,请求一批GUID,然后产生多个线程,以便它们可以并行运行请求。在我的家用机器上运行的初始测试有100个线程:
我们可以看到,我们每秒检查大约25个密码,发现了密码(在本例中,我知道密码,因此限制了我的搜索)。我在AWS的一台机器上运行了类似的测试,在25分钟内检查了91k密码。
有了改进的线程,并且分布在4-5个云服务器上,你可以在几分钟内检查整个密码空间。这很容易做到,但我拒绝了,因为我已经演示了这个过程,并希望谨慎不要打扰Zoom的服务(我确实做了一些短期的更高速率的测试,从未被限制或阻止)。
还要注意,查找密码的预期时间会更短,因为您通常不需要搜索整个可能的密码列表。
还要注意的是,包括“个人会议ID(PMI)”在内的定期会议总是使用相同的密码,因此一旦密码被破解,您就可以持续访问。
我的攻击的初始版本只能在会议开始后运行,但我后来发现,Un-Start的DOM指示密码是否正确或不正确,这意味着您也可以破解预定的会议。
首先,请注意,虽然似乎无法更改自发会议的6位数字密码,但可以覆盖计划会议的密码,但这是更改提供的默认密码的明确步骤。我检查了我过去收到的大约20个Zoom会议邀请,这些邀请来自不同的人,我发现他们都使用默认的6位密码。
如果您确实覆盖密码并生成较长的字母数字密码,则电话用户仍可能生成6位数字密码。此密码不被接受,至少在我尝试用于Web客户端的端点上是不接受的。我不确定其他端点是否也是如此-我没有检查。
还要注意,如果密码要更新为字母数字,我估计您仍然可以在不到一个小时的时间内运行密码列表,比如说,前1000万个密码。
在其他测试中,我发现Zoom的最大密码长度为10个字符,虽然它接受非ASCII字符(如ü、EURO等),但它会将它们全部转换为?在您保存密码之后。
最后,我在鲍里斯·约翰逊(Boris Johnson)的截图中注意到,有一个简单的名为“iPhone”的用户(见右下角)在关闭摄像头的情况下将其设为静音:
这让我想知道这个漏洞以前是否被发现过--如果我能发现它,那么似乎其他人也能发现它,这使得这个漏洞特别令人担忧。
将GUID的速率限制为合理的密码尝试次数(例如,对于给定会议,一小时内有10次[不同]次尝试失败)。
如果给定会议通过设置的密码尝试失败失败率,则速率限制或触发警告。
修复隐私条款表单上的CSRF,使自动攻击变得更加困难。
据我所知(Zoom没有让我深入了解他们采取了什么措施来缓解这个问题),Zoom似乎做了几个改变:
开始强制用户通过Web客户端加入会议;目前还不清楚这是否是永久性的更改(据我所知,这对一些用户来说是个问题)。
已将默认密码更新为字母数字密码。这似乎是在分阶段推出,因为我有时仍然看到只有数字的密码。
我直接向Zoom报告了这个问题,他们很快让整个网络客户端离线了几天,同时他们对问题进行了分类,几天后又出现了这个问题。
我知道,鉴于新冠肺炎疫情带来的使用量突然飙升,Zoom的安全做法一直受到密切关注。从我与团队的互动中,他们似乎关心平台的安全,他们的用户和他们似乎很欣赏这份报告。
Zoom运行一个私人的,仅限邀请的错误赏金计划,这对许多组织来说是相当普遍的做法。我被邀请将这个bug提交给bug赏金计划,但我要求等待,因为我对他们正在研究的新bug赏金计划感兴趣。我想知道新的项目规则是否会保证同意披露,因为我觉得这是一个公共利益的漏洞。当新程序启动时,Zoom同意我可以在新程序下提交错误。
不幸的是,我还没有看到任何关于新的赏金计划的东西,也没有回复我最近给Zoom的消息(我肯定他们很忙,这个错误已经修复了,tbf)。因此,考虑到它已经修复了一段时间,我要披露这个bug(他们已经同意披露)。
我确实通过HackerOne上的私人程序提交了其他几个小错误,并收到了这些小错误的赏金。感谢缩放团队!🙂。
令我惊讶的是,该平台的中央机制缺乏费率限制,再加上糟糕的默认密码系统和故障的CSRF,意味着会议真的不安全。
然而,Zoom的反应很快,他们很快解决了限速问题。Zoom Meetings还获得了默认密码升级,这很棒。
在过去的几个月里,ZOOM的易用性和视频会议质量使其成为数百万人在艰难时期使用的非常有价值的工具。很多(大多数?)。完全免费使用。这是一件很棒的事情,我很感激Zoom的存在。感谢Zoom团队!
4月1日-我向Zoom报告了这个问题,并且Python POC工作正常。我通过他们的通用支持表单和电子邮件发送了这封邮件。
4月2日-我随后给出了这篇文章的草稿作为补充说明,并提供了更好的Python代码注释版本。我在Zoom上发推文询问状态,和他们在一起的DM传递了车票号码。
4月2日-从他们的团队那里得知他们正在寻找(这是在我的报告之后大约24小时),然后收到了Zoom的CISO的跟进。
4月2日-注意到Zoom Web客户端离线,返回403。这也影响了web SDK。