Kestrel
대시보드로 돌아가기
CVE-2026-88018CRITICAL· 9.8MITRENVDGHSA대응게시일: 2026. 09. 10.수정일: 2026. 09. 10.

rclone serve s3: --auth-proxy without --auth-key authenticates nobody - full SigV4 signature bypass

Auth

위협 신호 · CVSS · EPSS · KEV

시급 검토· 이론 심각도 Critical
CVSS
9.8critical

이론적 심각도 점수

EPSS

예측 데이터 없음

KEV
미등재

실측 악용 기록 없음

권장 대응 기한3일 이내CISA SSVC 기준

즉시(3일 이내) 패치 — 최우선 대응

자동화 가능완전 장악외부 노출· KEV 미등재 · 자동화 가능 · 완전 장악 · 외부 노출

CVSS 벡터 · 메트릭

악용 경로
공격 벡터네트워크
공격 복잡도낮음
필요 권한불필요
사용자 상호작용불필요
범위불변
영향
기밀성 영향높음
무결성 영향높음
가용성 영향높음
버전별 점수
CVSS 3.19.8CRITICAL
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

상세 설명

Summary

rclone serve s3's handler chain, when --auth-proxy is configured, is (outermost first): authPairMiddleware -> proxyAuthMiddleware -> gofakes3's own SigV4-verifying handler.

authPairMiddleware parses the accessKeyID straight out of the incoming request's own Authorization header (entirely client-controlled) and registers {accessKey: ws.s3Secret} into gofakes3's shared credential store via AddAuthKeys, for EVERY access key any client presents - not just ones previously known to the server. ws.s3Secret defaults to "" whenever --auth-key is not set, which the --auth-proxy documentation (and the reference bin/test_proxy.py) presents as a complete, standalone authentication mechanism requiring no other flag - matching how it's used for serve webdav/ftp/sftp.

gofakes3's SigV4 verification then checks the request's signature against exactly the secret authPairMiddleware just registered for that same client-chosen key. An empty string is a valid HMAC key, so a caller can trivially compute a correct SigV4 signature for ANY access key ID of their choosing using an empty secret, and verification passes.

Crucially, the auth-proxy script never receives a real secret to verify against, for S3 specifically: Server.auth() calls w.proxy.Call(md5(accessKeyID), accessKeyID, false, r.RemoteAddr) - passing the access key ID itself as BOTH the hashed "user" and the raw "auth"/password fields. Contrast with serve webdav/ftp/sftp, whose proxy integration passes the client's actual typed password (see bin/test_proxy.py, which forwards it into a backing SFTP login for real verification). For S3, no independent secret is ever transmitted to the proxy script at all, so no script - however carefully written - can distinguish a legitimate holder of an access key ID from an attacker who merely picked the same string.

Net effect: with --auth-proxy configured and --auth-key not also set (the configuration the feature is documented to support standalone), SigV4 signature verification authenticates nobody.

Details

Vulnerable code (before fix):

text
1func authPairMiddleware(next http.Handler, ws *Server) http.Handler {
2 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
3 accessKey, _ := parseAccessKeyID(r)
4 authPair := map[string]string{accessKey: ws.s3Secret}
5 ws.faker.AddAuthKeys(authPair)
6 next.ServeHTTP(w, r)
7 })
8}

PoC

Built and signed a request by hand (via the vendored github.com/aws/aws-sdk-go-v2/aws/signer/v4) using a freshly-random access key ID never configured or returned by anything, with SecretAccessKey: "", against a real rclone serve s3 --auth-proxy <script> instance with no --auth-key set:

text
1status=200
2<ListAllMyBucketsResult>...<Bucket><Name>mybucket</Name>...

A fully authenticated, successful bucket listing, with zero prior credential knowledge.

Impact

Any network-reachable, unauthenticated attacker who knows (or discovers) that a target is running rclone serve s3 --auth-proxy without --auth-key can choose an arbitrary access key ID, sign a request against an empty secret, and be treated as an authenticated user by the auth-proxy script - reaching whatever backend that script resolves the chosen identity to. No credentials, prior access, or user interaction of any kind are required.

Fix

Refuse to start rclone serve s3 when --auth-proxy is set without --auth-key, rather than silently falling back to a signature check that authenticates nobody:

text
1if proxyOpt.AuthProxy != "" && len(opt.AuthKey) == 0 {
2 return nil, errors.New("serve s3: --auth-proxy requires --auth-key to also be set (SigV4 has no other way to verify a signature for a dynamically-proxied identity)")
3}

Note this is a minimal fix for the zero-knowledge bypass; once --auth-key is also set, every access key ID still shares that one static secret for signature-verification purposes (a caller who knows it can request any identity from the proxy script) - a narrower, pre-existing limitation flagged for awareness but not changed here, since a complete fix needs the auth-proxy wire protocol to carry a per-identity secret for S3 specifically (a larger design change).

AI 심층 분석

공격 시나리오 · 재현 가능한 PoC 페이로드 · 즉시 적용 가능한 차단 패치를 한 번에 받아 보세요. 보안 운영팀이 그대로 점검·티켓팅에 쓸 수 있는 형태로 정리해 드립니다.