Kestrel
대시보드로 돌아가기
CVE-2026-54246MEDIUM· 5.7GHSA대응게시일: 2026. 07. 17.수정일: 2026. 07. 17.

Skipper's routesrv-no-auth component: All routesrv API Endpoints Lack Authentication

위협 신호 · CVSS · EPSS · KEV

정기 패치· 높은 악용 신호 없음
CVSS
5.7medium

이론적 심각도 점수

EPSS

예측 데이터 없음

KEV
미등재

실측 악용 기록 없음

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

계획된 패치 주기 내 조치(60일 이내)

외부 노출· KEV 미등재 · 자동화 어려움 · 부분 영향 · 외부 노출

CVSS 벡터 · 메트릭

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

상세 설명

Description

The routesrv component exposes the full cluster route topology (Ingress/RouteGroup configurations, backend URLs, filter chains, OAuth/OIDC callback paths) and cache-cluster topology (Redis/Valkey shard addresses) over plain HTTP with zero authentication. Any pod in the Kubernetes cluster can reach routesrv via its predictable DNS name and retrieve sensitive cluster-wide routing and cache infrastructure data.

Vulnerable Code

routesrv/routesrv.go:87-99,114-137 — all handler registrations on the main mux:

text
1mux.Handle("/routes", b) // eskipBytes.ServeHTTP — all route data
2mux.Handle("/routes/{zone}", b) // zone-scoped route data
3mux.Handle("/swarm/redis/shards", rh) // Redis cluster addresses
4mux.Handle("/swarm/valkey/shards", vh) // Valkey cluster addresses

routesrv/eskipbytes.go:134-196eskipBytes.ServeHTTP:

text
1func (e *eskipBytes) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
2 // ... only checks GET/HEAD method, NO auth check
3 if r.Method != "GET" && r.Method != "HEAD" {
4 w.WriteHeader(http.StatusMethodNotAllowed)
5 return
6 }
7 // ... serves all route data immediately
8}

routesrv/redishandler.go:28-41RedisHandler.ServeHTTP:

text
1func (rh *RedisHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
2 if r.Method != "GET" {
3 w.WriteHeader(http.StatusMethodNotAllowed)
4 return
5 }
6 // ... serves Redis cluster addresses immediately, NO auth check
7}

routesrv/valkeyhandler.go:28-41ValkeyHandler.ServeHTTP:

text
1func (vh *ValkeyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
2 if r.Method != "GET" {
3 w.WriteHeader(http.StatusMethodNotAllowed)
4 return
5 }
6 // ... serves Valkey cluster addresses immediately, NO auth check
7}

Attack Path

  1. Initial Compromise: Attacker compromises any pod in the Kubernetes cluster (via application CVE, supply-chain attack, malicious container image, etc.)
  2. Discovery: Attacker discovers routesrv via predictable Kubernetes DNS name: skipper-ingress-routesrv.kube-system.svc.cluster.local:9090 (documented at docs/tutorials/operations.md:108, docs/tutorials/ratelimit.md:137,197)
  3. Data Extraction without Auth:
    • GET http://<routesrv>:9090/routes → All Ingress/RouteGroup configurations across ALL namespaces
    • GET http://<routesrv>:9090/swarm/redis/shards → Redis cache cluster node addresses
    • GET http://<routesrv>:9090/swarm/valkey/shards → Valkey cache cluster node addresses
  4. Subsequent Attacks: With cache cluster topology, attacker can perform direct cache-level attacks (ratelimit data manipulation, session data exfiltration)

Permission Boundary Analysis

The routesrv uses a ServiceAccount with cluster-wide RBAC to list Ingress (networking.k8s.io), RouteGroup (zalando.org), Endpoints, and Services across all namespaces (see clusterclient.go:648-653 fetchClusterState). The kube-apiserver requires proper ServiceAccount token + RBAC authorization for the Kubernetes API itself, but routesrv exposes the aggregated data over HTTP with zero authentication.

A compromised pod with limited RBAC (restricted to its own namespace) can bypass Kubernetes RBAC entirely by reading routesrv. This crosses the boundary from "namespace-scoped Kubernetes workload with restricted RBAC" to "full cluster route topology across all namespaces".

No NetworkPolicy manifests exist in the deploy/ directory. The default Kubernetes flat network model allows any pod to reach any service, further widening the attack surface.

Exposed Data

EndpointData ExposedImpact
GET /routesAll ingress/routegroup backends: internal service URLs, filter chains (auth, rate limiting, OAuth, JWT, OPA policies), load balancer group membershipCluster-wide reconnaissance, targeted backend attacks
GET /routes/{zone}Zone-scoped subset of above route dataSame, scoped
GET /swarm/redis/shardsRedis cluster internal IP:port pairsDirect cache-level attacks, ratelimit data manipulation
GET /swarm/valkey/shardsValkey cluster internal IP:port pairsSame

Additionally, the data-plane client (eskipfile/remote.go:190-219) also performs plain HTTP GET with no credentials — only an ETag header is sent — confirming that no auth capability exists in the architecture at all.

Mitigation

  1. Add authentication to all routesrv HTTP endpoints (basic auth, bearer token, mTLS, or shared secret) via flag -route-server-filters=""
  2. Deploy Kubernetes NetworkPolicies restricting ingress to routesrv to only the data-plane skipper pod selectors
  3. Consider using mutual TLS authentication between data-plane and control-plane components

NetworkPolicy does not remove the missing-auth condition

Restrictive NetworkPolicies are a valid mitigation, but they are not an application-layer authentication mechanism. The security-relevant defect remains that routesrv serves control-plane-derived data to unauthenticated callers whenever network reachability exists.

Impact framing

This report does not rely on claiming direct integrity or availability impact. The verified issue is a confidentiality-focused control-plane exposure: route definitions, backend topology, filter-chain details, and Redis/Valkey shard addresses become readable to any reachable in-cluster client.

Resources

  • routesrv/routesrv.go:87-99 — handler registration (zero auth)
  • routesrv/eskipbytes.go:134-196 — route data handler (no auth)
  • routesrv/redishandler.go:28-41 — Redis shard handler (no auth)
  • routesrv/valkeyhandler.go:28-41 — Valkey shard handler (no auth)
  • dataclients/kubernetes/clusterclient.go:648-653fetchClusterState() — shows cluster-wide RBAC
  • eskipfile/remote.go:190-219 — data-plane client also has no auth capability
  • docs/tutorials/operations.md:108, docs/tutorials/ratelimit.md:137,197 — documented routesrv DNS name

AI 심층 분석

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