답변:
무슨 일이야
사용자가 리소스를 생성, 업데이트 또는 삭제하기 위해 폼을 볼 때 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_tags
HTML 헤드 에 포함하여 양식을 렌더링하는 모든 레이아웃에 추가해야합니다 .
노트
Rails는 dem 등식이 아닌 방법 (POST, PUT / PATCH 및 DELETE) 만 검증하지 않습니다. GET 요청은 진위 토큰을 확인하지 않습니다. 왜? GET 요청을 HTTP 사양 상태는 나무 등입니다해야하고 있기 때문에 하지 , ALTER 만들거나 서버에서 자원을 파괴하고, 요청이 멱등해야한다 (같은 명령을 여러 번 실행하면, 당신은 동일한 결과를 모든 시간을 얻어야한다).
또한 실제 구현은 처음에 정의 된대로 조금 더 복잡하여 더 나은 보안을 보장합니다. Rails는 모든 형식에 대해 동일한 저장된 토큰을 발행하지 않습니다. 매번 다른 토큰을 생성하고 저장하지도 않습니다. 세션에서 암호화 해시를 생성 및 저장하고 페이지가 렌더링 될 때마다 저장된 토큰과 일치 할 수있는 새로운 암호화 토큰을 발급합니다. request_forgery_protection.rb를 참조하십시오 .
수업
authenticity_token
dem 등식이 아닌 방법 (POST, PUT / PATCH 및 DELETE)을 보호하는 데 사용하십시오 . 또한 서버의 자원을 잠재적으로 수정할 수있는 GET 요청을 허용하지 않아야합니다.
편집 : dem 등원 인 GET 요청에 관한 @erturne의 의견을 확인하십시오 . 그는 내가 여기서 한 것보다 더 나은 방법으로 설명합니다.
인증 토큰은 웹 사이트에서 양식이 제출되고 있음을 알 수 있도록 설계되었습니다. 컴퓨터에서만 알 수있는 고유 식별자로 실행되는 컴퓨터에서 생성되므로 사이트 간 요청 위조 공격을 방지 할 수 있습니다.
AJAX 스크립트 액세스를 거부하는 레일에 어려움이있는 경우 사용할 수 있습니다
<%= form_authenticity_token %>
양식을 만들 때 올바른 토큰을 생성합니다.
자세한 내용은 설명서를 참조하십시오 .
진위성 토큰은 CSRF (Cross-Site Request Forgery)에 대한 대책입니다. CSRF 란 무엇입니까?
공격자가 세션 토큰을 몰라도 세션을 가로 챌 수있는 방법입니다.
시나리오 :
CSRF 솔루션 :
방지 할 수있는 최소 공격 예 : 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 토큰이 등장했습니다.
따라서 실제 브라우저의 양식은 다음과 같습니다.
<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-ujs 는 meta
헤더에 추가 된 요소 csrf_meta_tags
(기본 템플릿에 있음)에서 토큰을 읽고 모든 요청에 추가합니다.
uJS는 또한 오래된 캐시 조각의 형태로 토큰을 업데이트하려고 시도합니다.
다른 예방 방법
X-Requested-With
. 예 :
Origin
헤더 값을 확인하십시오 : /security/91165/why-is-the-synchronizer-token-pattern-preferred-over-the-origin-header-check-to진위성 토큰은 CSRF (Cross-Site Request Forgery) 공격을 방지하는 데 사용됩니다. 진위 토큰을 이해하려면 먼저 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="✓" />
<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">
어딘가에
XSS
로그인 페이지에서 사악한 목적이 아니라 사전에 채워진 사용자 이름으로 새 세션을 만들려고했습니다. 이제는 그냥 사용할 수 있다는 것을 알고 있습니다 value="token_value"
.
동일한 클라이언트에서 여러 개의 동시 요청이있는 경우 진위 토큰 메커니즘으로 인해 경쟁 조건이 발생할 수 있습니다. 이 상황에서 서버는 하나만 있어야 할 때 여러 개의 인증 토큰을 생성 할 수 있으며 세션 쿠키 토큰을 덮어 써서 다음 요청에서 양식의 이전 토큰을받는 클라이언트가 실패합니다. 이 문제에 대한 글이 있으며 여기에 완전히 사소한 해결책은 없습니다 : http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/
authenticity_token
필요한 곳
authenticity_token
Idempotent 메소드가 데이터에 영향을주기 때문에 post, put 및 delete와 같은 idempotent 메소드의 경우 필요합니다.
왜 필요한가
악의적 행동을 막아야합니다. authenticity_token은 자원을 작성하거나 업데이트하기 위해 웹 페이지에서 양식을 작성할 때마다 숨겨진 필드에 저장되고 서버에서 양식과 함께 전송됩니다. 조치를 실행하기 전에 사용자가 보낸 authenticity_token이
authenticity_token
세션에 저장된 상태와 상호 점검 됩니다. 경우authenticity_token
입니다 같은 다음 프로세스는 작업을 수행하지 않습니다, 그렇지 않으면 계속합니다.
authentication_token은 무엇입니까?
이는 사용자가 다른 앱이나 사이트가 아닌 앱 페이지에서 작업을 요청하거나 수행하는지 확인하기 위해 레일스 응용 프로그램에서 사용하는 임의의 문자열입니다.
authentication_token이 필요한 이유는 무엇입니까?
교차 사이트 요청 위조로부터 앱 또는 사이트를 보호합니다.
양식에 authentication_token을 추가하는 방법은 무엇입니까?
form_for 태그를 사용하여 양식을 생성하는 경우 authentication_token이 자동으로 추가되어 사용할 수 있습니다 <%= csrf_meta_tag %>
.