[ruby-on-rails] Rails 진위성 토큰 이해

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

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



답변

무슨 일이야

사용자가 리소스를 생성, 업데이트 또는 삭제하기 위해 폼을 볼 때 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의 의견을 확인하십시오 . 그는 내가 여기서 한 것보다 더 나은 방법으로 설명합니다.


답변

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

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

<%= form_authenticity_token %>

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

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


답변

CSRF 란 무엇입니까?

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

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

시나리오 :

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

CSRF 솔루션 :

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

답변

방지 할 수있는 최소 공격 예 : 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 (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.comsession_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) 공격-그 방법입니다. 그러나 그것은 다른 날에 다른 취약점입니다.


답변

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

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


답변

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

 <%= token_tag nil %>

만들다

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

어딘가에