警告:本仓库包含与安全漏洞相关的信息和代码。请仅用于教育目的或在授权环境中使用。
在 Wazuh 集群配置(版本 ≥ 4.0.0)中发现了两个严重漏洞。这些缺陷影响使用多节点进行水平扩展、负载均衡和高可用性的部署。该配置允许管理多个代理而不会影响 Wazuh 服务器。
允许通过 DAPi 请求在主节点(master)和工作节点(worker)之间进行通信。工作节点使用 LocalClient 模块发送对象;主节点接受该消息并使用易受攻击的函数 as_wazuh_object() 反序列化该对象,从而允许在主节点上执行命令。
该漏洞是对上述漏洞的补充,允许通过 <command> 和 <localfile> 标签执行命令。攻击者可以在每次加载 /var/ossec/etc/ossec.conf 配置文件时执行命令。
两者都允许在利用集群功能的环境中产生[总体影响:权限提升、远程执行等]。
Wazuh manager ≥ 4.0.0(直至已修补版本 X.Y.Z)
所有启用了节点间通信且具有 master 或 worker 角色的节点。
集群配置用于拥有大量代理的部署中。它允许:
水平扩展:添加更多工作节点以分担负载。
高可用性:如果某个工作节点发生故障,其他节点在节点恢复期间继续运行。
负载均衡:代理分布在各个工作节点之间。
如果该架构未得到充分保护,则可能暴露本文档所述的攻击向量。
主节点调用此函数,该函数允许创建可任意执行命令的子进程。
def as_wazuh_object(dct: Dict):
try:
if '__callable__' in dct:
encoded_callable = dct['__callable__']
funcname = encoded_callable['__name__'] #getoutput
if '__wazuh__' in encoded_callable:
# Encoded Wazuh instance method.
wazuh = Wazuh()
return getattr(wazuh, funcname)
else:
# Encoded function or static method.
qualname = encoded_callable['__qualname__'].split('.') # getoutput
classname = qualname[0] if len(qualname) > 1 else None
module_path = encoded_callable['__module__'] # subprocess
module = import_module(module_path) # ARBITRARY IMPORT
if classname is None:
return getattr(module, funcname) # RETURNS ARBITRARY FUNCTION
else:
return getattr(getattr(module, classname), funcname)
Wazuh 集群协议(TCP/1516)使用该进程在节点之间同步文件。该进程以非特权用户身份运行,接受相对路径。
"""Create a file descriptor to store the incoming file.
Parameters
----------
data : bytes
Relative path to the file.
Returns
-------
bytes
Result.
bytes
Response message.
"""
# VULNERABLE LINE: No validation of 'data', no checking for '../', direct file open.
self.in_file[data] = {'fd': open(common.WAZUH_PATH + data.decode(), 'wb'), 'checksum': hashlib.sha256()}
return b"ok ", b"Ready to receive new file"
利用此配置,攻击者可以覆盖配置目录并执行命令。
攻击者可以:
影响机密性、完整性、可用性和权限提升。
破坏整个受监控基础设施的完整性。
原始 PoC 由 vikman90 开发,并作为本次分析的基础。以下是一个利用示例:
# 1. init docker compose
docker compose up -d
# 2. wait init all clusters
# 3. Verify cluster is connected
docker exec poc-master /var/ossec/bin/cluster_control -l
# Expected output should show worker01 connected:
# worker01 172.28.0.11 active
# 4. Execute exploit from worker
docker exec poc-worker /var/ossec/framework/python/bin/python3 /scripts/poc.py
# 5. Verify RCE on master
docker exec poc-master cat /var/ossec/etc/ossec.conf