HttpOnly 미설정 쿠키 노출

Sensitive Cookie Without HttpOnly Flag

설명

서버가 쿠키를 설정할 때 HttpOnly 플래그를 누락하면 클라이언트 JavaScript(예: document.cookie)로 쿠키를 읽을 수 있습니다. 이렇게 되면 XSS가 발생했을 때 공격자가 인증 쿠키나 세션 토큰을 쉽게 탈취하여 사용자를 가장할 수 있습니다. HttpOnly는 페이지 스크립트가 쿠키 값을 읽는 것을 제한하지만 XSS 자체나 감염된 브라우저 전체를 방어하지는 않습니다.

잠재적 영향

  • Session Hijacking (세션 탈취): 공격자가 세션 쿠키를 훔쳐 합법적 사용자로 가장해 애플리케이션에 접근합니다.
  • Account Takeover (계정 탈취): 세션 장기화나 약한 재인증 정책과 결합될 경우 사용자의 계정을 완전히 장악할 수 있습니다.
  • Data Exposure (데이터 노출): 인증된 세션을 이용해 민감 정보 조회·다운로드가 가능해집니다.

해결 방법

  • 민감한 서버 사이드 쿠키는 HttpOnly를 설정하세요. Express와 Next.js에서는 httpOnly: true를 명시하고, Node.js의 Set-Cookie 헤더에는 HttpOnly 속성을 포함하세요.
  • 함께 설정 권장: Secure(HTTPS 전송만 허용), SameSite(Strict 또는 Lax), 적절한 Path/Domain, 만료 시간(Max-Age/Expires).
  • 세션 ID, 액세스 토큰 등 민감 정보는 로컬스토리지 대신 HttpOnly 쿠키로 보관하고, 필요 시 서버 세션 스토어와 회전(rotation) 정책을 사용하세요.
  • 프레임워크별 가이드
    • Express: res.cookie(name, value, { httpOnly: true, secure: true, sameSite: 'Strict' })
    • Koa: httpOnly 기본값은 true이므로 생략해도 HttpOnly는 활성화됩니다. httpOnly: false로 비활성화하지 마세요.
    • Next.js의 Server Function/Route Handler: (await cookies()).set(name, value, { httpOnly: true, secure: true, sameSite: 'strict' })
    • Node http: Set-Cookie 헤더에 반드시 ; HttpOnly를 포함하세요.
  • XSS 예방: 입력 검증, 출력 인코딩, CSP(Content Security Policy) 적용으로 쿠키 탈취의 위험을 줄이세요.

예시

변경 전

javascript
// 비준수 예시: HttpOnly 미설정
const crypto = require("crypto");
const express = require("express");
const app = express();

app.get("/signin", (req, res) => {
  const token = crypto.randomBytes(32).toString("base64url");
  // BAD: HttpOnly 누락 -> document.cookie로 읽기 가능
  res.cookie("auth", token, {
    secure: true,
    sameSite: "Lax",
    path: "/",
  });
  res.send("signed in");
});

app.listen(3000);

변경 후

javascript
// 준수 예시: HttpOnly 포함
const crypto = require("crypto");
const express = require("express");
const app = express();

app.get("/signin", (req, res) => {
  const token = crypto.randomBytes(32).toString("base64url");
  // GOOD: HttpOnly, Secure, SameSite 명시
  res.cookie("auth", token, {
    httpOnly: true,
    secure: true,
    sameSite: "Strict",
    path: "/",
    maxAge: 10 * 60 * 1000, // 10분
  });
  res.send("signed in");
});

app.listen(3000);

설명:

  • 변경 전: HttpOnly가 없으므로 브라우저의 JavaScript에서 document.cookie로 쿠키 값을 읽을 수 있습니다. XSS가 발생하면 공격자가 인증 쿠키를 탈취해 세션을 가로챌 수 있습니다.
  • 변경 후: HttpOnly를 설정해 스크립트 접근을 차단하고, Secure와 SameSite를 함께 사용해 전송 중 탈취와 CSRF 위험을 줄였습니다. 이로써 XSS 발생 시에도 쿠키 탈취 가능성을 크게 낮춥니다.

참조