이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • cache hit ratio, origin offload, p95 latency를 보면서도 보안 사고를 피하려면 무엇을 봐야 하는가?
  • cache poisoning, web cache deception, 사용자 데이터 노출은 어떤 설정에서 발생하는가?
  • 기업 운영과 개인 프로젝트에서 현실적인 cache 안전장치를 어떻게 다르게 잡는가?

개요

캐시는 성능과 비용을 크게 개선하지만 보안 경계를 흐릴 수 있다. 특히 공유 cache가 인증 응답을 저장하거나, 공격자가 cache key에 반영되지 않는 header/query를 이용해 오염된 응답을 저장시키면 많은 사용자에게 같은 잘못된 응답이 퍼질 수 있다.

  • 성능 지표는 HIT율만 보지 말고 origin latency, byte hit ratio, stale 응답률, purge 후 miss 폭증을 함께 본다.
  • 보안 지표는 cacheable endpoint 목록, auth/cookie 포함 응답, Vary, cache key 정책을 함께 본다.
  • cache는 읽기 성능을 높이지만 쓰기 이후 정합성과 권한 변경 반영을 어렵게 만든다.

원리

cache 성능은 보통 다음 효과를 낸다.

  • 사용자와 가까운 edge에서 응답해 latency를 줄인다.
  • origin CPU, DB, network egress를 줄인다.
  • traffic spike를 흡수한다.

반대로 위험은 다음에서 생긴다.

  • 민감 응답이 공유 cache에 저장된다.
  • cache key가 응답 차이를 충분히 반영하지 못한다.
  • 공격자가 cache 가능한 오류/redirect/script 응답을 주입한다.
  • purge와 TTL 정책이 권한/가격/재고 변경을 따라가지 못한다.

성능 지표 해석

지표의미함정
hit ratio요청 수 기준 cache HIT 비율작은 파일 HIT가 많아도 비용 절감은 작을 수 있음
byte hit ratiobyte 기준 HIT 비율큰 파일 최적화 효과 확인
origin offloadorigin 요청 감소율origin 장애를 CDN이 숨길 수 있음
p95/p99 latency사용자 체감 지연MISS와 HIT를 분리해야 함
stale servedstale 응답 제공 횟수UX 보호와 최신성 저하가 동시에 있음
purge rate무효화 빈도과도하면 cache 효과 감소와 origin spike

보안 위험

cache poisoning은 공격자가 cache에 잘못된 응답을 저장시켜 다른 사용자에게 제공되게 하는 공격이다. web cache deception은 사용자의 민감 페이지가 정적 파일처럼 보이는 URL 패턴으로 cache되게 유도하는 공격이다.

위험한 조합은 다음과 같다.

  • Authorization 또는 session cookie가 있는데 public cache가 가능하다.
  • URL path만 cache key로 보고 query/header/cookie 차이를 무시한다.
  • /account/settings.css 같은 경로가 민감 페이지를 반환하지만 CDN은 확장자 기준으로 cache한다.
  • Host, X-Forwarded-Host, Origin 같은 header가 응답 생성에 쓰이지만 cache key나 Vary에 반영되지 않는다.

안전한 Header 출발점

민감 응답은 보수적으로 시작한다.

Cache-Control: no-store

사용자별이지만 브라우저 cache 정도는 허용할 수 있다면 더 좁게 잡는다.

Cache-Control: private, no-cache

정적 fingerprint asset은 공격 표면을 확인한 뒤 길게 둔다.

Cache-Control: public, max-age=31536000, immutable

CDN cache 대상 endpoint는 allowlist 방식으로 관리하는 편이 안전하다. “기본 cache, 민감 endpoint 예외”보다 “기본 bypass, 공개 endpoint만 cache”가 실수에 강하다.

코드와 명령으로 확인하기

민감 endpoint가 공유 cache에 저장될 위험이 있는지 smoke test한다.

curl -sI https://api.example.com/me \
  -H 'Authorization: Bearer user-a-token' \
  | grep -iE 'cache-control|age|vary|x-cache|cf-cache-status'
 
curl -sI https://api.example.com/me \
  -H 'Authorization: Bearer user-b-token' \
  | grep -iE 'cache-control|age|vary|x-cache|cf-cache-status'

URL 확장자 기반 cache rule을 의심할 때는 민감 경로가 정적 확장자처럼 보이지 않는지 확인한다.

curl -i 'https://www.example.com/account/profile.css' \
  -H 'Cookie: sid=test'

응답이 HTML 계정 페이지인데 CDN이 cache한다면 web cache deception 위험이 있다.

인프라 협업 포인트

  • CDN cache rule은 보안 리뷰 대상이다. path pattern, method, query, header, cookie, auth 처리 기준을 명시한다.
  • WAF나 gateway가 redirect/location/header를 변조하는 경우 cache poisoning 가능성을 같이 본다.
  • 인프라 팀의 고충은 cache rule 하나가 성능, 비용, 장애 완화, 보안 리스크를 동시에 건드린다는 점이다. 앱 팀은 endpoint 의미와 데이터 민감도를 제공해야 한다.
  • purge 권한은 제한하고 감사 로그를 남긴다. 잘못된 purge는 장애 완화 도구가 아니라 장애 트리거가 될 수 있다.

실전 팁

  • cache HIT율 목표를 잡기 전에 cache해도 되는 데이터 목록부터 만든다.
  • 인증이 필요한 API는 CDN cache bypass를 기본으로 두고, 공개 read API만 명시적으로 cache한다.
  • cache stampede가 예상되면 stale-while-revalidate, request coalescing, origin shield를 검토한다.
  • 보안 사고 대응에서는 cache purge도 incident response 절차에 포함한다. 민감 데이터가 edge에 남아 있을 수 있다.
  • 개인 프로젝트는 Cloudflare 같은 managed CDN을 쓰더라도 /api/*는 기본 bypass, /assets/*는 fingerprint + long TTL로 시작하면 안전하다.

위험 신호!

  • Set-Cookie가 있는 응답에 public cache가 붙는다.
  • CDN이 확장자 기준으로만 cache하고 application route 의미를 모른다.
  • Vary 없이 Origin, Accept-Encoding, Authorization 차이가 있는 응답을 cache한다.
  • purge 권한과 감사 로그가 없다.

확인 질문

확인 질문

  • cache hit ratio가 높아도 보안상 안심할 수 없는 이유는 무엇인가?
    • 잘못 캐시된 민감 응답도 높은 HIT율로 빠르게 퍼질 수 있기 때문이다.
  • web cache deception은 어떤 상황에서 생기는가?
    • 민감 페이지가 정적 파일처럼 보이는 URL로 접근 가능하고 CDN이 경로나 확장자 기준으로 cache할 때 발생할 수 있다.
  • 개인 프로젝트에서 안전한 CDN 출발점은 무엇인가?
    • /assets/* 같은 fingerprint 정적 파일만 길게 cache하고, /api/*와 인증 응답은 기본 bypass 또는 no-store로 시작하는 것이다.

참고 문서