Rails 진위성 토큰 이해


982

나는 지금 여러 번이나 Rails의 진품 토큰에 관한 몇 가지 문제를 겪고 있습니다.

그러나 나는 정말로이 문제를 해결하고 계속하고 싶지 않습니다. 진품 토큰을 정말로 이해하고 싶습니다. 글쎄, 내 질문은, 당신은이 주제에 대한 완전한 정보원이 있습니까? 아니면 여기에서 자세히 설명하기 위해 시간을 보내시겠습니까?


7
또한 "Google이 왜 응답에 while (1)을 JSON 응답에 추가합니까?"를 참조하십시오. stackoverflow.com/questions/2669690/…
클로

답변:


1462

무슨 일이야

사용자가 리소스를 생성, 업데이트 또는 삭제하기 위해 폼을 볼 때 Rails 앱은 random을 생성 authenticity_token하고이 토큰을 세션에 저장 한 다음 폼의 숨겨진 필드에 배치합니다. 사용자가 양식을 제출하면 Rails는를 찾아 authenticity_token세션에 저장된 것과 비교하고 일치하면 요청을 계속할 수 있습니다.

왜 그런가

인증 토큰이 세션에 저장되므로 클라이언트는 해당 값을 알 수 없습니다. 이를 통해 사람들은 해당 앱 자체 내에서 양식을 보지 않고도 양식을 Rails 앱에 제출할 수 없습니다. 서비스 A를 사용 중이고 서비스에 로그인했는데 모든 것이 정상이라고 가정하십시오. 이제 서비스 B를 사용하여 좋아하는 사진을보고 더 큰 크기의 사진을 보려면 사진을 눌렀다 고 상상해보십시오. 이제 서비스 B에 악의적 인 코드가있는 경우 서비스 A (로그인 한 서비스)에 요청을 보내고에 요청을 보내 계정을 삭제하도록 요청할 수 http://serviceA.com/close_account있습니다. 이것이 CSRF (Cross Site Request Forgery) 입니다.

서비스 A가 인증 토큰을 사용하는 경우 서비스 B의 요청에 올바른 인증 토큰이 포함되지 않고 계속 진행할 수 없으므로이 공격 벡터는 더 이상 적용되지 않습니다.

API 문서 는 메타 태그에 대한 세부 사항을 설명합니다.

CSRF 보호는 protect_from_forgery토큰을 확인하고 예상 한 것과 일치하지 않으면 세션을 재설정하는 방법으로 설정됩니다. 이 메소드에 대한 호출은 기본적으로 새 Rails 애플리케이션에 대해 생성됩니다. 토큰 매개 변수는 authenticity_token기본적으로 이름이 지정 됩니다. 이 토큰의 이름과 값은 csrf_meta_tagsHTML 헤드 에 포함하여 양식을 렌더링하는 모든 레이아웃에 추가해야합니다 .

노트

Rails는 dem 등식이 아닌 방법 (POST, PUT / PATCH 및 DELETE) 만 검증하지 않습니다. GET 요청은 진위 토큰을 확인하지 않습니다. 왜? GET 요청을 HTTP 사양 상태는 나무 등입니다해야하고 있기 때문에 하지 , ALTER 만들거나 서버에서 자원을 파괴하고, 요청이 멱등해야한다 (같은 명령을 여러 번 실행하면, 당신은 동일한 결과를 모든 시간을 얻어야한다).

또한 실제 구현은 처음에 정의 된대로 조금 더 복잡하여 더 나은 보안을 보장합니다. Rails는 모든 형식에 대해 동일한 저장된 토큰을 발행하지 않습니다. 매번 다른 토큰을 생성하고 저장하지도 않습니다. 세션에서 암호화 해시를 생성 및 저장하고 페이지가 렌더링 될 때마다 저장된 토큰과 일치 할 수있는 새로운 암호화 토큰을 발급합니다. request_forgery_protection.rb를 참조하십시오 .

수업

authenticity_tokendem 등식이 아닌 방법 (POST, PUT / PATCH 및 DELETE)을 보호하는 데 사용하십시오 . 또한 서버의 자원을 잠재적으로 수정할 수있는 GET 요청을 허용하지 않아야합니다.


편집 : dem 등원 인 GET 요청에 관한 @erturne의 의견을 확인하십시오 . 그는 내가 여기서 한 것보다 더 나은 방법으로 설명합니다.


25
@Faisal은 공격자가 서비스 A 양식의 '숨겨진'요소를 간단히 읽고 캡처하여 사용자가 시작한 세션에 액세스 한 경우 사용자를 위해 생성 된 고유 토큰을 얻는 것이 가능합니다. 서비스 A를 위해?
marcamillion

11
@marcamillion : 누군가 서비스 A에서 세션을 가로 채면 진위 토큰이 보호하지 않습니다. 납치범은 요청을 제출할 수 있으며 계속 진행할 수 있습니다.
파이잘

12
@zabba : Rails는 적절한 토큰없이 양식이 제출되면 ActionController :: InvalidAuthenticityToken 예외를 발생시킵니다. 예외에서 rescue_from하고 원하는 처리를 할 수 있습니다.
파이잘

5
"또한 서버의 리소스를 잠재적으로 수정할 수있는 GET 요청을하지 않아야합니다." -여기에는 POST 만 수신 할 컨트롤러 작업에 GET 요청을 허용 할 수있는 경로에 match ()를 사용하지 않는 것이 포함됩니다.
Steven Soroka

102
"... 그리고 요청은 dem 등원이어야합니다 (동일한 명령을 여러 번 실행하는 경우 매번 같은 결과를 얻음)" 여기에 미묘한 설명이 있습니다. 안전은 부작용이 없음을 의미합니다. dem 등원 (Idempotent)은 서비스 호출 횟수에 관계없이 동일한 부작용을 의미합니다. 부작용이 없기 때문에 모든 안전한 서비스는 본질적으로 dem 등입니다. 현재 시간 리소스에서 GET을 여러 번 호출하면 매번 다른 결과가 반환되지만 안전하므로 dem 등합니다.
erturne

137

인증 토큰은 웹 사이트에서 양식이 제출되고 있음을 알 수 있도록 설계되었습니다. 컴퓨터에서만 알 수있는 고유 식별자로 실행되는 컴퓨터에서 생성되므로 사이트 간 요청 위조 공격을 방지 할 수 있습니다.

AJAX 스크립트 액세스를 거부하는 레일에 어려움이있는 경우 사용할 수 있습니다

<%= form_authenticity_token %>

양식을 만들 때 올바른 토큰을 생성합니다.

자세한 내용은 설명서를 참조하십시오 .


88

CSRF 란 무엇입니까?

진위성 토큰은 CSRF (Cross-Site Request Forgery)에 대한 대책입니다. CSRF 란 무엇입니까?

공격자가 세션 토큰을 몰라도 세션을 가로 챌 수있는 방법입니다.

시나리오 :

  • 은행 사이트를 방문하여 로그인하십시오.
  • 그런 다음 공격자의 사이트를 방문하십시오 (예 : 신뢰할 수없는 조직의 스폰서 광고).
  • 공격자 페이지에는 은행의 "이체 자금"양식과 동일한 필드가있는 양식이 포함되어 있습니다.
  • 공격자는 귀하의 계정 정보를 알고 있으며 귀하의 계정에서 공격자의 계정으로 돈을 이체하기 위해 양식 필드를 미리 작성했습니다.
  • 공격자 페이지에는 은행에 양식을 제출하는 자바 스크립트가 포함되어 있습니다.
  • 양식이 제출되면 브라우저는 세션 토큰을 포함하여 은행 사이트에 대한 쿠키를 포함합니다.
  • 은행은 돈을 공격자의 계좌로 이체합니다.
  • 이 양식은 보이지 않는 iframe에있을 수 있으므로 공격이 발생한 것을 알 수 없습니다.
  • 이를 CSRF (Cross-Site Request Forgery)라고합니다.

CSRF 솔루션 :

  • 서버는 서버 자체에서 온 양식을 표시 할 수 있습니다
  • 모든 양식에는 추가 인증 토큰이 숨겨진 필드로 포함되어야합니다.
  • 토큰은 예측할 수 없어야합니다 (공격자가 추측 할 수 없음).
  • 서버는 페이지에 유효한 토큰을 양식으로 제공합니다.
  • 서버는 양식을 게시 할 때 토큰을 확인하고 적절한 토큰없이 양식을 거부합니다.
  • 토큰 예 : 서버 비밀 키로 암호화 된 세션 식별자.
  • Rails는 이러한 토큰을 자동으로 생성합니다. 모든 형식의 authenticity_token 입력 필드를 참조하십시오.

1
다음은 덜 정확하지만 덜 추상적 인이 같은 설명의 버전은 다음과 같습니다 stackoverflow.com/a/33829607/2810305
루츠 Prechelt

확실하지 않지만 최신 브라우저에서 dem 등원이 아닌 요청 (POST / PUT / Delete)을 다른 도메인으로 보낼 수 있습니까? 브라우저 자체에있는 것들에 대한 보호 기능이 있어야한다고 생각합니다.
splitByZero

45

방지 할 수있는 최소 공격 예 : CSRF

내 웹 사이트 evil.com에서 다음 양식을 제출할 것을 확신합니다.

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="to"      value="ciro"></p>
  <p><input type="hidden" name="ammount" value="100"></p>
  <p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>

세션 쿠키를 통해 은행에 로그인 한 경우 쿠키가 전송되고 사용자 모르게 전송됩니다.

CSRF 토큰이 등장했습니다.

  • 폼을 반환 한 GET 응답으로 Rails는 매우 긴 임의의 숨겨진 파라미터를 보냅니다
  • 브라우저는 POST 요청을 할 때 매개 변수를 함께 보내고 서버는 일치하는 경우에만 매개 변수를 수락합니다.

따라서 실제 브라우저의 양식은 다음과 같습니다.

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
  <p><input type="hidden" name="to"                 value="ciro"></p>
  <p><input type="hidden" name="ammount"            value="100"></p>
  <p><button type="submit">Send 100$ to Ciro.</button></p>
</form>

따라서 authenticity_token매개 변수를 보내지 않았기 때문에 공격이 실패 하고 큰 임의의 숫자이므로 추측 할 수있는 방법이 없습니다.

이 방지 기술을 Synchronizer Token Pattern 이라고 합니다 .

동일한 원산지 정책

그러나 공격자가 JavaScript로 두 가지 요청을했는데 하나는 토큰을 읽고 다른 하나는 전송을 요청하면 어떨까요?

싱크로 나이저 토큰 패턴만으로는 충분하지 않습니다!

/security/8264/why-is-the-same-origin-policy-so-important/72569# 에서 설명한 것처럼 이것이 동일한 출처 정책이 구출되는 곳입니다. 72569

Rails가 토큰을 보내는 방법

적용 대상 : Rails : csrf_meta_tag는 어떻게 작동합니까?

원래:

  • HTML 도우미 form_tag는 GET 양식이 아닌 경우 숨겨진 필드를 양식에 추가하는 것을 좋아 합니다.

  • AJAX는 jquery-ujs 가 자동으로 처리합니다. jquery-ujsmeta헤더에 추가 된 요소 csrf_meta_tags(기본 템플릿에 있음)에서 토큰을 읽고 모든 요청에 ​​추가합니다.

    uJS는 또한 오래된 캐시 조각의 형태로 토큰을 업데이트하려고 시도합니다.

다른 예방 방법


고맙지 만 CSRF 토큰을 먼저 읽을 수 없다는 동일한 원산지 정책에 대한 요점은 결함이있는 것 같습니다. 그래서 먼저 다른 원점으로 POST 할 수는 있지만 읽을 수는 없지만 이상하게 보이지만 올바른 것 같지만 페이지에 도착하여 이미지 또는 스크립트 태그를 삽입하고 핸들러를 링크하여 응답을 구문 분석 할 수 있습니다 그리고 그래?
bjm88

@ bjm88은 스크립트를 어디에 주입합니까? 귀하의 사이트 또는 공격받은 사이트에서? 공격받은 사이트에서 스크립트 삽입을 허용하는 것은 잘 알려진 보안 결함이며 웹 사이트를 효과적으로 전당포합니다. 모든 웹 사이트는 입력 위생을 통해 싸워야합니다. 이미지의 경우 공격에 어떻게 사용될 수 있는지 알 수 없습니다. 공격 사이트에서 : 당신은 읽기를 허용하도록 브라우저를 수정할 수 있으며, 따라서 :-)에 따라 자동으로 전당포 할 수 있지만 괜찮은 브라우저는 기본적으로 그것을 방지하고 시도해보십시오.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

43

진위성 토큰은 CSRF (Cross-Site Request Forgery) 공격을 방지하는 데 사용됩니다. 진위 토큰을 이해하려면 먼저 CSRF 공격을 이해해야합니다.

CSRF

귀하가의 저자라고 가정합니다 bank.com. 귀하의 사이트에는 GET 요청으로 다른 계좌로 송금하는 데 사용되는 양식이 있습니다.

여기에 이미지 설명을 입력하십시오

해커는 서버에 HTTP 요청을 보낼 수 있습니다 GET /transfer?amount=$1000000&account-to=999999.

여기에 이미지 설명을 입력하십시오

잘못된. 해커의 공격이 작동하지 않습니다. 서버는 기본적으로 생각할까요?

응? 이 사람은 누가 이체를 시도합니까? 계정 소유자가 아닙니다. 확실합니다.

서버는 이것을 어떻게 알 수 있습니까? session_id요청자를 인증하는 쿠키 가 없기 때문 입니다.

사용자 이름과 비밀번호로 로그인하면 서버가 session_id브라우저 에서 쿠키를 설정 합니다. 그렇게하면 사용자 이름과 비밀번호로 각 요청을 인증 할 필요가 없습니다. 브라우저가 session_id쿠키를 보내면 서버는 다음을 알고 있습니다.

아, 존 도우입니다. 2.5 분 전에 성공적으로 로그인했습니다. 그는 잘 지내요.

해커는 다음과 같이 생각할 수 있습니다.

흠. 정상적인 HTTP 요청은 작동하지 않지만 session_id쿠키에 손을 대면 황금색이됩니다.

사용자 브라우저에는 bank.com도메인에 대한 쿠키 세트가 있습니다. 사용자가 bank.com도메인에 요청할 때마다 모든 쿠키가 전송됩니다. session_id쿠키를 포함합니다 .

따라서 해커가 귀하의 계좌로 돈을 이체하는 GET 요청을 할 수 있다면 성공할 것입니다. 어떻게 당신을 속일 수 있습니까? 교차 사이트 요청 위조

실제로는 간단합니다. 해커는 당신이 그의 웹 사이트를 방문하게 할 수 있습니다. 웹 사이트에서 다음 이미지 태그를 가질 수 있습니다.

<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">

사용자 브라우저가 해당 이미지 태그를 발견하면 해당 URL에 GET 요청을합니다. 요청은 브라우저에서 제공되므로에 연결된 모든 쿠키가 요청과 함께 전송됩니다 bank.com. 사용자가 최근에 로그인 한 경우 bank.com... session_id쿠키가 설정되고 서버는 사용자가 $ 1,000,000를 계정 999999로 이체한다고 생각합니다!

여기에 이미지 설명을 입력하십시오

글쎄, 위험한 사이트를 방문하지 않으면 괜찮을 것입니다.

충분하지 않습니다. 누군가가 그 이미지를 Facebook에 게시하고 벽에 나타나면 어떻게해야합니까? XSS 공격으로 방문하는 사이트에 주입되면 어떻게됩니까?

그렇게 나쁘지 않습니다. GET 요청 만 취약합니다.

사실이 아니다. POST 요청을 보내는 양식을 동적으로 생성 할 수 있습니다. 보안에 관한 Rails Guide 의 예제는 다음과 같습니다 .

<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;">To the harmless survey</a>

진품 토큰

당신 ApplicationController이 이것을 가지고 있을 때 :

protect_from_forgery with: :exception

이:

<%= form_tag do %>
  Form contents
<% end %>

이것으로 컴파일됩니다 :

<form accept-charset="UTF-8" action="/" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
  Form contents
</form>

특히 다음이 생성됩니다.

<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />

CSRF 공격으로부터 보호하기 위해 Rails가 요청과 함께 전송 된 인증 토큰을 보지 못하면 요청이 안전한 것으로 간주하지 않습니다.

침입자는이 토큰이 무엇인지 어떻게 알 수 있습니까? 양식이 생성 될 때마다 다른 값이 무작위로 생성됩니다.

여기에 이미지 설명을 입력하십시오

XSS (Cross Site Scripting) 공격-그 방법입니다. 그러나 그것은 다른 날에 다른 취약점입니다.


39

Authenticity Token레일 '하는 방법 방지 사이트 간 요청 위조 (CSRF 또는 XSRF) 공격' .

간단히 말하면 웹 응용 프로그램에 대한 PUT / POST / DELETE (컨텐츠를 수정할 수있는 방법) 요청은 쿠키에 액세스 할 수있는 제 3 자 (공격자)가 아닌 클라이언트의 브라우저에서 이루어집니다. 클라이언트 측에서.


34

때문에 Authenticity Token매우 중요하고, 레일에 3.0 당신은 사용할 수 있습니다

 <%= token_tag nil %>

만들다

<input name="authenticity_token" type="hidden" value="token_value">

어딘가에


이것은 나에게 도움이되었다. 실제로 XSS로그인 페이지에서 사악한 목적이 아니라 사전에 채워진 사용자 이름으로 새 세션을 만들려고했습니다. 이제는 그냥 사용할 수 있다는 것을 알고 있습니다 value="token_value".
마이클 - 클레이 셔키는 어디

27

동일한 클라이언트에서 여러 개의 동시 요청이있는 경우 진위 토큰 메커니즘으로 인해 경쟁 조건이 발생할 수 있습니다. 이 상황에서 서버는 하나만 있어야 할 때 여러 개의 인증 토큰을 생성 할 수 있으며 세션 쿠키 토큰을 덮어 써서 다음 요청에서 양식의 이전 토큰을받는 클라이언트가 실패합니다. 이 문제에 대한 글이 있으며 여기에 완전히 사소한 해결책은 없습니다 : http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/


11

authenticity_token필요한 곳

authenticity_token Idempotent 메소드가 데이터에 영향을주기 때문에 post, put 및 delete와 같은 idempotent 메소드의 경우 필요합니다.

왜 필요한가

악의적 행동을 막아야합니다. authenticity_token은 자원을 작성하거나 업데이트하기 위해 웹 페이지에서 양식을 작성할 때마다 숨겨진 필드에 저장되고 서버에서 양식과 함께 전송됩니다. 조치를 실행하기 전에 사용자가 보낸 authenticity_token이 authenticity_token세션에 저장된 상태와 상호 점검 됩니다. 경우 authenticity_token입니다 같은 다음 프로세스는 작업을 수행하지 않습니다, 그렇지 않으면 계속합니다.


3
사실, 그 반대가 아닙니까? GET은 호출이 시스템 상태를 변경하지 않아야하므로 since 등원입니다. 여기서 PUT POST 및 DELETE 동사는 시스템 상태를 변경하기 때문에 NOT 등원 동사가 아닙니다. IE : i 등원이 아닌 메소드의 경우 authenticity_token이 필요합니다.
Jean-Théo

2
@ Jean-Daube, uma : dem 등원은 두 번 수행하면 행동이 한 번만 발생 함을 의미합니다. GET, PUT 및 DELETE idempotent입니다. w3.org/Protocols/rfc2616/rfc2616-sec9.html 여기서 핵심 특성은 idempotency가 아니지만 메소드가 "안전한 메소드"라고하는 데이터를 변경하거나 변경하지 않는 경우입니다.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

6

authentication_token은 무엇입니까?

이는 사용자가 다른 앱이나 사이트가 아닌 앱 페이지에서 작업을 요청하거나 수행하는지 확인하기 위해 레일스 응용 프로그램에서 사용하는 임의의 문자열입니다.

authentication_token이 필요한 이유는 무엇입니까?

교차 사이트 요청 위조로부터 앱 또는 사이트를 보호합니다.

양식에 authentication_token을 추가하는 방법은 무엇입니까?

form_for 태그를 사용하여 양식을 생성하는 경우 authentication_token이 자동으로 추가되어 사용할 수 있습니다 <%= csrf_meta_tag %>.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.