Zabbix是一个非常流行的开源监控平台,用于收集、集中和跟踪整个基础设施的CPU负载和网络流量等指标。它与Pandora FMS和Nagios等解决方案非常相似。由于Zabbix的受欢迎程度、功能以及它在大多数公司网络中的特权地位,Zabbix已成为攻击者的首选目标。我们在Zabbix的客户端会话实现中发现了一个高度严重的漏洞,它可能会导致整个网络的破坏。
在本文中,我们将介绍不同类型的会话存储,并讨论实现安全的可能性。最后,我们将描述在Zabbix中发现的漏洞的技术细节、其影响以及如何防范。
客户端会话存储
会话都是关于跨多个HTTP请求存储状态的,是无状态设计。为此,应用程序通常给每个客户端一个唯一的标识符。他们必须将其与未来的请求一起传输。然后,服务器可以加载相关信息,无论它是存储在内存中、数据库中还是本地文件系统上。这就是我们通常所说的服务器端会话存储。
这种历史方法效果很好,但与现代web应用程序的开发和部署方式相比存在缺陷。例如,它不能很好地扩展。如果后端服务分散在多个服务器上,如何确保一个会话可以跨服务甚至整个服务器队列使用?
因此,开发人员在客户端引入了会话存储。他们现在不必为客户端分配会话标识符,而是必须在每个请求中发送状态的副本。像 ASP 和 Java 这样的技术堆栈将这个概念包装在一种称为“视图状态(View State)”的内容中,但现在很常见的是依赖于 JSON Web 令牌 (JWT) 标准。
这两种方法的目标都是在客户端安全存储数据,但在某种程度上,后端服务仍然可以确保数据的真实性和完整性,它需要使用加密技术来提供这些保证。尽管存在配置错误的风险(弱秘密、支持破坏的加密算法)以及撤销 JWT 的固有困难,但这基本上是一种安全的方法。
在此类用例中,不得混淆加密和身份验证提供的安全保证。虽然加密数据在未受过教育的人看来可能看起来是“安全的”,但后端服务无法检测到会话数据是否被客户端更改。使用 ECB 等加密模式甚至可以让攻击者在不知道密钥的情况下制作有效的任意密文!
为了演示由于客户端会话代码的不安全设计和实现而可能出现的风险,让我们看看我们在 Zabbix 中发现的两个漏洞的技术细节。
Zabbix Web 前端漏洞
监控平台 Zabbix 通常部署在具有四个不同组件的基础设施上:
Zabbix Agent:运行在所有被监控节点上的服务,当 Zabbix Server 请求时收集信息;
Zabbix Server:它连接到 Zabbix代理,以收集监控数据并在达到配置的阈值时发出警报;
Zabbix 代理:将单个 Zabbix 服务器与数百个 Zabbix 代理相关联可能非常昂贵且难以在某些网络拓扑中部署。Zabbix Proxy实例的目的是集中整个区域的数据,并将收集到的数据报告给Zabbix主服务器;
Zabbix Web前端:Zabbix服务器的接口,通过TCP和共享数据库进行通信。系统管理员使用此仪表板访问收集的监控数据并配置 Zabbix 服务器(例如列出主机、在 Zabbix 代理上运行脚本)。
在 2021 年 12 月,我们分析了 Zabbix Web 前端的外部攻击面,以更好地了解与该软件暴露于不受信任的网络相关的风险。这一努力导致发现了两个关键漏洞,CVE-2022-23131和CVE-2022-23134。
这些发现都与 Zabbix 在客户端存储会话数据的方式有关。我们将指导你完成其易受攻击的实施,讨论其影响以及如何在早期利用阶段发现它。
影响
发现的漏洞影响我们研究时所有受支持的 Zabbix Web 前端版本,包括 5.4.8、5.0.18 和 4.0.36。它们不需要事先了解目标,并且可以被攻击者毫不费力地实现自动化。
我们强烈建议你将运行 Zabbix Web 前端的实例升级到 6.0.0beta2、5.4.9、5.0.19 或 4.0.37 以保护你的基础设施。
在启用了SAML SSO身份验证的实例中,它允许绕过身份验证并获得管理员权限。攻击者可以利用这种访问在链接的Zabbix Server和Zabbix Agent实例上执行任意命令,CVE-2021-46088利用代码已经公开。与Zabbix Agent不同,不可能配置Zabbix服务器来禁止命令的执行。
Zabbix 的客户端会话存储实现
服务器端会话是 PHP 的内置功能,客户端在 cookie 中被分配了一个唯一的会话标识符,PHPSESSID 是最常见的一个,并且必须在每个请求中传输它。在服务器端,PHP 采用该值并在文件系统(/var/lib/php/sessions,有时是 /tmp/)上查找关联的会话值,以填充超全局变量 $_SESSION。客户端不能随意修改会话值,因为它们只控制会话的标识符。
Zabbix Web 前端基于 PHP 的强大功能自定义会话处理程序推出了自己的客户端存储实现。通过使用实现 SessionHandlerInterface 的类调用 session_set_save_handler(),对 $_SESSION 的所有后续访问都将由此类的方法处理。
在此示例中,目标是将任何对$_SESSION的访问映射到cookie。例如,索引$_SESSION导致调用cookiesession::read();cookie helper::get()只是一个围绕$_COOKIE的包装器:
ui/include/classes/core/CCookieSession.php
Zabbix 开发人员引入了一种方法来验证存储在 cookie 中的数据并确保它们不被篡改。此功能在 CEncryptedCookieSession 中实现:
ui/include/classes/core/CEncryptedCookieSession.php
需要注意的是,术语“sign[ature]”和“encrypted”是可以互换使用的。 CEncryptHelper::sign() 内部使用 AES ECB,容易出现可延展性,无法提供数据真实性的安全保证。使用此构造还导致了另一个安全建议,但本文不会详细介绍。
CEncryptedCookieSession::checkSign()方法只在CEncryptedCookieSession::extractSessionId()中被调用,但是从来没有在cookiesession方法中被调用(例如在访问期间在cookiesession::read())。当访问sessionid以外的字段时,会话的真实性永远不会被验证。
由于cookie完全由客户端控制,它们基本上控制了会话。这是非常罕见的,并且打破了关于存储在其中的值的可信度的大多数假设。它可能导致使用会话的应用程序的某些部分出现漏洞。
CVE-2022-23131——绕过 SAML SSO 身份验证
安全断言标记语言 (SAML) 是最常见的单点登录 (SSO) 标准之一。围绕 XML 实现,它允许身份提供者(IdP,一个能够对用户进行身份验证的实体)告诉服务提供者(SP,这里是 Zabbix)你是谁。你可以将 Zabbix Web 前端配置为允许通过 SAML 进行用户身份验证,但默认情况下不启用它,因为它需要了解身份提供者的详细信息,这是企业部署最常见的设置。
与 SAML 认证机制相关的代码可以在 index_sso.php 中找到。简而言之,它的目标是:
将用户重定向到 IdP;
用户通过身份验证后,验证传入 SAML 有效负载的格式和签名。创建一个名为 saml_data 的会话条目来记住用户的属性;
如果会话中存在名为 saml_data 的条目,则提取其值并根据 username_attribute 的值在 Zabbix 上对用户进行身份验证。
如上所述,CEncryptedCookieSession::checkSign()永远不会在这个文件中被调用,因此会话条目 saml_data[username_attribute] 的值可以完全由客户端控制:
ui/index_sso.php
漏洞利用很简单,特别是因为 Zabbix Web 前端自动配置了一个名为 Admin 的高权限用户。
一旦在仪表板上被验证为管理员,攻击者可以在任何附加的 Zabbix 服务器上执行任意命令,如果在配置中明确允许 AllowKey=system.run[*](非默认),则攻击者可以在Zabbix代理上执行任意命令。
CVE-2022-23134——重新配置实例
在 setup.php 中发现了另一个不安全使用会话的情况。此脚本通常由系统管理员在首次部署 Zabbix Web 前端时运行,以后仅允许经过身份验证的高权限用户访问。
此页面通常使用会话来跟踪设置步骤的进度,同样,CEncryptedCookieSession::checkSign()永远不会在这里被调用。使用设置为6的入口步骤创建一个会话,允许重新运行安装过程的最新步骤。
这一步对攻击者来说非常有趣,因为它的目标是创建 Zabbix Web 前端配置文件 conf/zabbix.conf.php:
ui/include/classes/setup/CSetupWizard.php
在 [1] 处,创建了一个新的 CConfigFile 对象来存储和验证新的配置值。 CSetupWizard::getConfig() 方法只是当前会话的简单包装,因此这些值完全由攻击者控制。
在 [2] 处,代码试图通过尝试连接新的数据库配置来识别它是否有效。由于此代码仅应在初始设置过程中调用,当尚未配置用户帐户和数据库设置(如加密密钥)时,控制会话的攻击者将能够通过各种检查。
因此,即使 Zabbix Web Frontend 实例已经处于工作状态,攻击者也可以覆盖现有的配置文件。通过指向他们控制的数据库,攻击者可以使用高权限帐户访问仪表板。
重要的是要理解这种访问不能用于访问网络上部署的 Zabbix Agent:Zabbix Web Frontend 和 Zabbix服务器必须使用相同的数据库才能进行通信。它仍然有可能将其与web仪表盘上的代码执行漏洞联系起来,以获得对数据库和网络的控制。
在非加固的或旧的环境中也可以使用其他的开发场景。例如,PHP的MySQL客户端实现了LOAD DATA LOCAL语句,但现在默认情况下禁用了3年。另一个原因可能是在验证数据库配置时使用完全控制的参数调用file_exists(),这是一个安全风险,因为像phar://这样的方案包装器有潜在的危险。
修复情况
Zabbix 维护人员分别解决了这两个漏洞:
SSO 身份验证流程中引入了一个额外的签名字段,以防止用户更改存储在会话中的 SAML 属性 (0395828a);
会话 cookie 的身份验证方式现在使用 HMAC 构造而不是 AES ECB (eea1f70a) 完成;
如果实例已安装且当前用户没有超级管理员角色 (20943ae3),则设置过程现在会提前退出;
他们还决定不强制执行 cookie 签名检查:这种方法的主要缺点是,如果忘记了对 CEncryptedCookieSession::checkSign() 的调用,依赖于会话的新功能可能会引入类似的漏洞。
本文翻译自:https://blog.sonarsource.com/zabbix-case-study-of-unsafe-session-storage如若转载,请注明原文地址