1/19/2020

SameSite=Lax가 Default로? SameSite Cookie에 대해 정확하게 알아보기

올 2월부터 Chrome 브라우저에서 SameSite=Lax가 기본값으로 변경됩니다.

Early October, 2019: Experimental SameSite-by-default and SameSite=None-requires-Secure behavior launched to 50% of users on Chrome Canary and Dev (Chrome Canary and Dev versions 78+). Windows and Mac users on domain-joined devices and Chrome OS users on enterprise-registered devices will be excluded from the experiment. Chrome 78 Beta users will not receive the experimental behavior.

October 31, 2019: Chrome 79 Beta released. Experiment extended to 50% of Chrome 79 Beta users, including domain-joined and enterprise-registered devices. Policies to manage the experimental behavior (see below) will be available on Chrome 79.

Dec 10, 2019: Chrome 79 Stable released. Stable users on Chrome 79 will NOT receive the new SameSite behavior.

Dec 19, 2019: Chrome 80 Beta released. Experimental behavior still enabled for 50% of Chrome 80 Beta users.

February, 2020: Chrome 80 Stable will begin rolling out over a period of time. SameSite-by-default and SameSite=None-requires-Secure will then start being enabled as the default behavior during the Chrome 80 Stable lifecycle.

그리고 SameSite=None을 사용하기 위해선 해당 쿠키에 Secure가 강제된다고 하니.. 꼭 참고하시길 바래요.

보안쪽 입장에선 환영할 부분이지만, 버그바운티헌터나 개발자 입장에선 고려해야할 부분이 많아지는건 사실입니다. 작년에 가볍게 보고 넘어갔던 내용인데, 최근에 리서치해보고 테스트해볼일이 있었는데, 복습 차원으로 글로 남겨봅니다.



SameSite on Cookie?

기본적으로 쿠키는 대상 도메인의 기준으로 전송 유무가 판단됩니다. 예를들어
www.google.com에 발급된 쿠키는 www.hahwul.com에선 사용할 수 없지만 www.hahwul.com에서 www.google.com으로 이동할 땐 쿠키가 붙어서 전송됩니다.

아래처럼 gmail.com이 <a> 태그로 있는 경우도 동일하죠. (구글 로그인이 되었다면 gmail이 열리겠죠.)

gmail

이렇게 웹 페이지간 이동에서 기본적으로 사용되던 쿠키를 이제는 SameSite를 이용해서 외부에서 온 요청인지, 도메인 내부의 요청인지 명확하게 검증하게 됩니다. 이 과정은 작년부터 진행되고 있고 결국은 Lax가 Default가 되는 현상까지 일어났네요.
https://www.chromium.org/updates/same-site

방금까지 이야기한 내용만 토대로 보면 CSRF의 대응방안이 될 수 있습니다. Lax나 Strict가 걸려있는한 공격자가 CSRF를 성공하기 위해선 Cross-domain 정책을 우회할만한 환경이나 기술이 더 필요해진거죠. 관련해선 임준오님 블로그 글 한번 읽어보시면 좋습니다.

SameSite Policy

크게 정책은 3가지로 나뉘어 있습니다.

SameSite=None

SameSite=None

현재 브라우저들 기준으로 Default 값이며 쿠키 사용에 있어서 소스가 되는 주소를 검증하지 않습니다. 

SameSite=Strict

SameSite=Strict

강하게 제한하는 정책으로 소스가 되는 도메인과 대상 도메인이 일치해야만 쿠키가 포함되어 전송됩니다.
예를들면..

(O) www.google.com => www.google.com
(X) www.hahwul.com => www.google.com

여기서 전송이라고 하면, <img> <form> <iframe> $.get() 등 모든 요청을 의미합니다..

SameSite=Lax

SameSite=Lax

마지막으로 Lax는 기존 Strict 정책에서 예외처리가 몇개 된 정책이라고 생각하시면 됩니다. 

<a href> , <link href> <form method=get> 정도만 예외되고 나머지는 Strict와 동일하게 동작합니다.


크로미움에서 정의한 내용도 이와 같습니다.
A cookie with "SameSite=Strict" will only be sent with a same-site request. 
A cookie with "SameSite=Lax" will be sent with a same-site request, or a cross-site top-level navigation with a "safe" HTTP method.
A cookie with "SameSite=None" will be sent with both same-site and cross-site requests.


다만 Lax에서 허가된 것들이 "Safe"한 HTTP Method 이고, 이건 GET을 의미하는 것 같은데요.. 많은 경우가 있듯이 POST=>GET으로 변경 했을 때 가능한 CSRF도 굉장히 많기 때문에 이 또한 인지하고 테스트해야할 부분인 것 같네요.

간단하게 Cross-site 환경에서 Iframe으로 테스트해보면 이렇습니다.

SameSite=None 일 때 <iframe src>

SameSite=Lax 일 때 <iframe src> , Cookie 발생하지 않음


SameSite의 정확한 기준

작년에 SameSite에 대해 처음 알았을땐 사실 도메인에 대한 기준에 별 관심이 없어서 그냥 지나쳤었는데, 최근에 이와 관련해서 테스트해보고 여러 의견을 나눠본 결과.. 매우 중요 했네요.

요점은 www.google.comaaa.google.com, 즉 서브 도메인만 다른 경우 SameSite인가? 이고 결론은 SameSite 입니다. 다만 하나 알고가야할건, 이를 나누는 기준이 Public suffix에 명시된 최상위 도메인을 비교하는 겁니다.
https://publicsuffix.org/list/public_suffix_list.dat

그래서, 1.google.com2.google.com은 SameSite이지만, 1.github.io2.github.io는 Cross-site 입니다..

web.dev쪽 링크 한번 읽어보시면 좋습니다.

Key Term:

If the user is on www.web.dev and requests an image from static.web.dev then that is a same-site request.

The public suffix list defines this, so it's not just top-level domains like .com but also includes services like github.io. That enables your-project.github.io and my-project.github.io to count as separate sites.

크롬만 SameSite=Lax를 적용하는건가?

크롬이 2월에 예정되어 있어서 보안이나 개발 모두 신경쓰고 있어야하는 부분입니다. 그럼 다른 브라우저는 어떻게 되는걸까요? 우선은 SameSite 는 크롬보다 Firefox나 Safari의 구현이 더 빨랐고 현재도 대다수 브라우저들이 모두 지원하는 상태입니다.


아직은 확실하게 날짜가 나오진 않았지만, Firefox를 비롯해서 다른 브라우저도 Default 값으로 가져가게 되는 것 같습니다.


How to Testing and Programming?

자 이제 어떤건지 알아봤으니 테스트하는 방법을 간략하게 정리해봅시다. 각 브라우저로 별로 현재(20년 1월)까진 기본값이 None으로 설정된 상태라서 테스트가 어렵습니다. 크게 2가지 방법 정도로 테스트해 볼 수 있는데요.

Browser Config

가장 좋은 방법입니다. 크롬(76 이상)과 파폭(69 이상) 모두 Config를 통해 강제로 Lax를 Default로 동작시킬 수 있습니다.

1) FireFox
Firefox의 경우 about:config 진입 후 network.cookie.sameSite.laxByDefault 를 true로 바꿔쥐면 Default가 Lax로 동작합니다.



2) Chrome
Chrome 또한 flags에서 Enable 시켜주시면 Default가 Lax로 동작합니다.
chrome://flags/#cookies-without-same-site-must-be-secure


Browser Cookie Addon

두번째는 EditThisCookie 같은 Addon을 통한 변경 방법입니다. 위 기본값을 바꾸는 것과는 다르게 특정 쿠키만 Lax, Strict를 줄 수 있기 때문에 쿠키 정책을 테스트해볼때 제일 적합한 도구라고 보이네요.


SameSite 구현 예시

물론 전 개발자가 아니기 때문에 구현해야할 일이 많지는 않겠지만, 크롬쪽에서 예시 페이지를 공유해주고 있어서 같이 포함해봤습니다.
https://github.com/GoogleChromeLabs/samesite-examples

뭐 사실 별거 없습니다..ㅋㅋ
document.cookie = 'same-site-cookie=foo; SameSite=Lax';
document.cookie = 'cross-site-cookie=bar; SameSite=None; Secure';

워낙 잘 나와있어서 보고 적용해보시면 될 것 같습니다 :)

References


https://web.dev/samesite-cookies-explained/#explicitly-state-cookie-usage-with-the-samesite-attribute
https://github.com/GoogleChromeLabs/samesite-examples
https://www.chromium.org/updates/same-site
https://imjuno.com/author/imjuno99/


HAHWUL

Security engineer, Rubyist, Gopher and H4cker!

Share: | Coffee Me: