2011-02-06 3 views
16

In regards to this Haacked blog을 방지하기 위해 HTTP GET에 MVC3의 AntiForgeryToken를 사용하여, 나는 비 REST-을 포함 JSON 하이재킹을 완화에자바 스크립트 CSRF 취약점을

  1. 권장 솔루션 이후 제안 된 안티 - JSON GET 하이재킹 솔루션을 구현하기가 주저 해요 전체 JSON POST로 데이터 가져 오기

  2. 대체 솔루션 (오브젝트 랩핑)은 타사 컨트롤에서 문제를 일으 킵니다. 소스 코드 액세스 권한이 없습니다.

  3. 보안 토큰을 작성하는 방법에 대한 대안 솔루션 (아래 나열 됨)을 구현하는 커뮤니티에서 검증 한 구현을 찾지 못하거나 웹 페이지에서 안전하게 전달할 수 없습니다. 나는 또한 내 자신의 구현을 롤백하는 데 충분한 전문가라고 주장하지 않을 것입니다.

  4. 리퍼러 헤더는

배경

This blog JSON 하이재킹 관련, CSRF 문제에 대해 설명에 의존 할 수 없으며 데이터를 얻을 수 JSON 게시물을 사용하는 것이 좋습니다. HTTP POST를 사용하여 데이터를 가져 오는 것이 REST 전체가 아니기 때문에 세션 당 또는 페이지 당 REST 동작을 가능하게하는보다 RESTfull 솔루션을 찾고 싶습니다.

또 다른 완화 기법은 개체에 JSON 데이터를 래핑하는 것입니다. as described here. 다른 기술이 발견 될 때까지 문제가 지연 될 수 있습니다.

나에게

대체 구현, 내 JSON에 대한 GET을의 jQuery HTTP의 사용에 ASP.NET MVC's AntiForgeryToken을 확장 할 자연 보인다. 좀 민감한 데이터를 얻는 경우

예를 들어, 위의 Haacked 링크에 따라, 다음 코드는 취약 : 나는 그것을 권장 POST 해결 방법을 사용하여 데이터를 얻을 수 RESTfull되지 않는다는 것을 동의

$.getJSON('[url]', { [parameters] }, function(json) { 
    // callback function code 
}); 

. 내 생각은 URL에 유효성 확인 토큰을 보내는 것입니다. 그렇게하면 CSRF 스타일 공격자는 전체 URL을 알 수 없습니다. 캐시되거나 캐시되지 않으면 데이터를 가져올 수 없습니다.

다음은 JSON GET 쿼리를 수행하는 방법의 두 가지 예입니다. 어떤 구현이 가장 효과적인 지 잘 모르겠지만 첫 번째 매개 변수가이 데이터를 캐싱하는 잘못된 프록시로 인해 더 안전하므로 공격자가 취약해질 수 있습니다. 뿐만 MVC3의 AntiForgeryToken 또는 이의 변이체 (see swt) 일 수

http://localhost:54607/Home/AdminBalances/ENCODEDTOKEN-TOKEN-HERE

또는

http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE

.... 이 토큰은 위에 선택된 URL 형식의 인라인 값으로 설정됩니다.내 자신의 솔루션을 압연에서 저를 방지

샘플 질문 (위)는 JSON의 GET (슬래시,와 Questionmark 등)의 유효성을 검사 할 때 사용하는

  1. 어떤 URL 형식은 프록시 http://localhost:54607/Home/AdminBalances에 응답합니다 http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE 데이터가 있습니까?

  2. 인코딩 된 토큰을 어떻게 웹 페이지에 전달하겠습니까? 인라인 또는 페이지 변수로?

  3. 토큰을 어떻게 작성 하시겠습니까? AntiforgeryToken에 내장되어 있습니까?

  4. AntiForgeryToken은 쿠키를 사용합니다. 이 경우 뒷받침 쿠키를 사용해야합니까/필요합니까? HTTP 전용? HTTP 전용과 함께 SSL은 어떻습니까?

  5. 캐시 헤더를 어떻게 설정 하시겠습니까? Google Web Accelerator의 특별한 기능 (예 :

    )
  6. JSON 요청을 SSL로 만드는 것의 의미는 무엇입니까?

  7. 안전을 위해 반환 된 JSON 배열을 여전히 객체에 래핑해야합니까?

  8. 어떻게

질문은 위의 I 앞서 단조이 나 자신을 안할거야 이유 마이크로 소프트의 제안 templating and databinding 기능이 솔루션의 상호 운용성있는 것입니다. 말할 것도없이 나는 생각지 못했지만 더 많은 위험을 안고 있습니다. 이 HTTP POST (는 OWASP XSRF Prevention Cheat Sheet에 설명 된 "Double Submit Cookies"기술을 사용)에 의존하는 쿠키에 의존하기 때문에

+0

이것은 CSRF의 변형입니다. – SLaks

답변

13

Asp.net MVC AntiForgeryToken는 HTTP GET을 통해 작동하지 않습니다. httponly으로 설정하여 클라이언트에 보낸 쿠키를 추가로 보호 할 수 있으므로 스크립트를 통해 스푸핑 할 수 없습니다.

this document에는 XSRF를 방지하는 데 사용할 수있는 다양한 기술이 있습니다. 설명 된 방법이 접근법 1에 해당하는 것으로 보입니다.하지만 Ajax HTTP GET 요청을 사용할 때 서버에서 세션을 검색하는 방법에 문제가 있습니다. 쿠키가 요청과 함께 전송되지 않기 때문입니다. 따라서 세션 식별자를 작업 URL에 추가해야합니다 (즉, 도용하기 쉬운 쿠키없는 세션). 따라서 공격을 수행하기 위해 공격자는 GET 요청을 수행하기 위해 올바른 URL을 알아야합니다.

아마도 좋은 해결책은 사용자 SSL 인증서의 일부 키 (예 : certs thumb-print)를 사용하여 세션 데이터를 저장하는 것입니다. 이렇게하면 SSL 인증서의 소유자 만 자신의 세션에 액세스 할 수 있습니다. 이렇게하면 쿠키를 사용할 필요가 없으며 쿼리 문자열 매개 변수를 통해 세션 식별자를 보낼 필요가 없습니다.

Asp.net MVC에서 HTTP POST를 사용하지 않으려면 어쨌든 자신의 XSRF 보호를 배포해야합니다.

+0

게시 한 링크 내에서 OWASP CSRF 가드에 의지 할 것입니다. 고맙습니다. http://www.owasp.org/index.php/.Net_CSRF_Guard – LamonteCristo

+0

관련 내용 :이 질문을 할 때도이 기사에서 언급 한 Javascript 공격을 해결하고 싶었습니다 (https : //www.info-point- security.com/open_downloads/alt/JavaScript_Hijacking.pdf). 5 페이지의 보안 문제를 혼란스럽게 생각합니다. – LamonteCristo

3

나는이 문제에 직면했지만 해결책은 그리 간단하지는 않지만 환상적인 블로그를 통해 시작하고 아약스를 가져올 수 있습니다.

http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC

당신은 모든 게시물 글로벌 이름 공간에 다음과 같은 배치하면

/장점 토큰 안티 위조를 갖는 걸릴 수 있습니다 얻고 당신이 당신의 아약스 전화를 수정할 필요가 없습니다. 공통 페이지에 입력 요소를 만듭니다.

<form id="__AjaxAntiForgeryForm" action="#" method="post">@Html.AntiForgeryToken()</form> 

다음 자바 스크립트는 위조 방지 토큰을 읽고 요청 헤더에 추가합니다.

// Wire up the global jQuery ajaxSend event handler. 
$(document).ajaxSend(namespace.ajax.globalSendHandler); 

// <summary> 
// Global handler for all ajax send events. 
// </summary> 
namespace.ajax.globalSendHandler = function (event, xhr, ajaxOptions) { 
    // Add the anti forgery token 
    xhr.setRequestHeader('__RequestVerificationToken', $("#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]").val()); 
};