01DEFINITION
한 줄로 말하면
세션 쿠키에 HttpOnly 가 없으면 자바스크립트로 읽힙니다. XSS 한 번에 계정이 그대로 넘어간다는 뜻입니다. Secure 가 없으면 http 요청에도 쿠키가 실려 나가고, SameSite 가 없으면 다른 사이트가 우리 쪽으로 보내는 요청에도 쿠키가 따라붙습니다(CSRF). 세 속성은 각각 다른 사고를 막기 때문에, 하나가 빠지면 정확히 그 구멍만 열려 있습니다.
02RISK
없으면 무슨 일이 생기나
HttpOnly 가 빠진 경우가 가장 직접적입니다. 페이지 어딘가에 스크립트가 한 줄 끼어들면 그 스크립트가 세션 쿠키를 읽어 외부로 보낼 수 있습니다. 공격자는 그 값으로 우리 사이트에 그 사용자로 접속합니다. 비밀번호를 몰라도 되고, 이중 인증을 켜 두었어도 이미 인증된 세션이라 그대로 통과합니다.
Secure 가 빠지면 쿠키가 암호화되지 않은 요청에도 실려 나갑니다. https 로만 서비스한다고 생각해도, 방문자가 주소를 http 로 한 번 치거나 옛 링크를 누르는 순간 세션 값이 평문으로 네트워크를 지나갑니다. https 강제 리다이렉트를 걸어 두었어도 그 첫 요청에는 이미 쿠키가 실려 있습니다.
SameSite 가 빠진 경우는 조금 다릅니다. 공격자가 만든 페이지에서 우리 사이트로 요청을 보낼 때 브라우저가 우리 쿠키를 함께 붙여 줍니다. 사용자는 자기 계정으로 로그인해 있으므로 그 요청은 정상 처리됩니다. 회원정보 변경이나 결제가 사용자 모르게 실행되는 CSRF 가 여기서 나옵니다.
03CHECK IT YOURSELF
직접 확인하는 방법
아래는 저희를 거치지 않고 지금 해 보실 수 있는 방법입니다. 결과를 저희에게 보내실 필요도 없습니다.
-
01
로그인 후 설정되는 쿠키를 본다
중요한 것은 세션 쿠키입니다. 로그인 요청의 응답에서 Set-Cookie 줄을 확인하십시오. 로그인 전 홈에서 보이는 쿠키만 확인하면 정작 세션 쿠키를 못 봅니다.
$ curl -sI https://example.com/ | grep -i set-cookie set-cookie: PHPSESSID=abc123; path=/; HttpOnly; Secure; SameSite=Lax
-
02
브라우저에서 세 칸을 확인한다
개발자도구의 애플리케이션 탭에서 쿠키 목록을 열면 HttpOnly, Secure, SameSite 가 각각 열로 나옵니다. 세션 쿠키 한 줄만 보시면 됩니다.
-
03
스크립트로 읽히는지 직접 해 본다
콘솔에서 아래를 실행했을 때 세션 쿠키 이름이 목록에 나오면 HttpOnly 가 빠진 것입니다. 가장 확실한 확인 방법입니다.
> document.cookie
04HOW TO FIX
고치는 방법
서버 환경에 따라 적을 자리가 다릅니다. 아래는 가장 흔한 구성 기준이고, 적용 전에 현재 설정을 백업하십시오.
php.ini 를 고칠 수 있다면 그쪽이 가장 확실합니다. 세션이 시작되기 전에 적용되어야 하므로 코드에서 바꿀 때는 session_start 앞에 두어야 합니다.
session.cookie_httponly = 1 session.cookie_secure = 1 session.cookie_samesite = Lax
공유 호스팅이나 코어 수정이 금지된 환경에서 쓰는 방법입니다. 이미 속성이 붙어 있는 쿠키는 건드리지 않도록 조건을 겁니다.
Header always edit Set-Cookie "^(?!.*[Hh]ttp[Oo]nly)(.*)$" "$1; HttpOnly" Header always edit Set-Cookie "^(?!.*[Ss]ame[Ss]ite)(.*)$" "$1; SameSite=Lax" Header always edit Set-Cookie "^(?!.*[Ss]ecure)(.*)$" "$1; Secure"
Strict 로 두면 외부에서 들어오는 링크를 눌렀을 때 로그인 상태가 아닌 것처럼 보입니다. 메일로 보낸 주문 조회 링크가 대표적인 피해자입니다. Lax 는 일반적인 링크 이동을 허용하면서 위험한 요청만 막습니다.
https 가 아직 없는 상태에서 Secure 를 붙이면 쿠키가 아예 전달되지 않아 로그인이 되지 않습니다. 순서는 인증서, https 강제, 그다음 Secure 입니다.
05FAQ
자주 묻는 질문
HttpOnly 를 켜면 자바스크립트에서 로그인 상태를 못 읽나요
- 세션 쿠키를 직접 읽지 못하게 되는 것은 맞습니다. 다만 로그인 여부를 화면에 표시하는 정도는 서버가 렌더링할 때 넘겨 주거나 별도의 비민감 쿠키를 하나 더 두면 해결됩니다. 세션 값 자체를 스크립트가 읽어야 하는 정상적인 이유는 거의 없습니다.
Lax 와 Strict 중 무엇을 골라야 하나요
- 외부에서 링크를 타고 들어오는 방문이 있다면 Lax 입니다. Strict 는 다른 사이트에서 넘어온 모든 요청에 쿠키를 붙이지 않기 때문에, 메일이나 메신저로 보낸 링크를 눌러 들어온 사용자가 로그인되지 않은 화면을 보게 됩니다. 관리자 전용 도구처럼 외부 유입이 없는 경우에만 Strict 가 적합합니다.
쿠키가 여러 개인데 전부 이 속성을 붙여야 하나요
- 세션과 인증에 관련된 쿠키가 우선입니다. 화면 설정이나 최근 본 상품처럼 민감하지 않은 값까지 전부 HttpOnly 로 만들면 정상적으로 쓰던 스크립트가 동작하지 않습니다. 무엇이 인증에 쓰이는 쿠키인지 먼저 구분하십시오.
SameSite 만 켜면 CSRF 대책이 끝나나요
- 끝나지 않습니다. SameSite 는 브라우저가 지켜 주는 방어라서 브라우저를 거치지 않는 요청에는 적용되지 않고, 같은 사이트 안에서 시작된 요청도 막지 않습니다. 서버 쪽 토큰 검증은 그대로 있어야 하고, SameSite 는 그 위에 한 겹 더 얹는 것입니다.
RELATED
같이 보시면 좋은 항목
GET STARTED
내 사이트는
이 항목을 통과할까요
주소만 넣으시면 이 항목을 포함해 25가지를 판정해 점수와 실패 개수를 보여 드립니다. 로그인도, 소유 확인도 필요 없습니다 — 전부 밖에서 관찰만 하는 항목이기 때문입니다.