위조 방지 토큰(Anti-Forgery Tokens)

ASP.NET MVC에서는 CSRF 공격을 방지하기 위해서 위조 방지 토큰을 사용하는데, 이를 요청 검증 토큰(Request Verification Tokens)이라고 부르기도 합니다.

  1. 클라이언트가 폼이 존재하는 HTML 페이지를 요청합니다.
  2.  
  3. 그러면, 서버는 응답에 두 가지 토큰을 포함시켜서 반환합니다. 그 중, 한 가지 토큰은 쿠키를 통해서 전송됩니다. 그리고, 다른 토큰은 숨겨진 폼 필드에 담겨집니다. 이 토큰들은 악의적인 사용자들이 값을 추측할 수 없도록 무작위로 생성됩니다.
  4. 클라이언트가 폼을 제출할 때, 두 가지 토큰이 모두 서버로 재전송돼야 합니다. 클라이언트는 쿠키 토큰은 쿠키를 통해서 전송하고, 폼 토큰은 폼 데이터에 담아서 전송합니다. (브라우저 클라이언트가 사용자가 폼을 제출할 때 자동으로 이 작업을 처리해줍니다.)
  5. 만약, 두 토큰 중 하나라도 일치하지 않으면 서버가 해당 요청을 허용하지 않습니다.

다음은 숨겨진 폼 토큰을 포함하고 있는 HTML 폼의 한 예입니다:

===================================================================

<form action="/Home/Test" method="post">

       <input name="__RequestVerificationToken" type="hidden"       

                value="6fGBtLZmVBZ59oUad1Fr33BuPxANKY9q3Srr5y[...]" />

        <input type="submit" value="Submit" />

</form>

===================================================================

 

위조 방지 토큰으로 CSRF 공격을 방지할 수 있는 이유는, Same-Origin 정책에 따라 악의적인 페이지에서 사용자의 토큰을 읽을 수 없기 때문입니다.

(Same-Orgin 정책 https://www.w3.org/Security/wiki/Same_Origin_Policy  은 두 개의 다른 사이트에서 호스트되고 있는 문서들이 서로 상대방의 콘텐트에 접근하는 것을 막습니다. 그래서 첫 번째 예제에서 살펴본 것처럼 악의적인 페이지에서 example.com으로 요청을 전송할 수는 있어도, 응답을 읽을 수는 없습니다.)

 

Same Origin Policy - Web Security

Same-Origin Policy There is no single same-origin policy. General Principles An origin is defined by the scheme, host, and port of a URL. Generally speaking, documents retrieved from distinct origins are isolated from each other. For example, if a document

www.w3.org

사용자가 로그인 한 이후에 브라우저가 내부적으로 자격 증명을 전송하는 모든 인증 프로토콜들은 위조 방지 토큰을 사용해야만 CSRF 공격을 방지할 수 있습니다. 그 대상에는, 폼 인증 같은 쿠키 기반 인증 프로토콜뿐만 아니라 기본 인증이나 다이제스트 인증도 포함됩니다.

또한, 모든 안전하지 않은 메서드들(POST, PUT, DELETE)에 위조 방지 토큰을 적용해야 합니다. 그리고, 안전한 메서드들도(GET, HEAD) 부작용을 일으키지 않는지 확인해야 합니다. 더군다나, CORS나 JSONP 같은 크로스-도메인 지원을 활성화시켰다면, GET 같은 안전한 메서드조차도 잠재적으로 CSRF 공격에 취약점을 갖게 되므로 공격자가 내부적으로 민감한 데이터를 읽을 수 있게 됩니다.

ASP.NET MVC의 위조 방지 토큰

Razor 페이지에 위조 방지 토큰을 추가하려면 HtmlHelper.AntiForgeryToken 도우미 메서드를 사용합니다:

==================================================================

@using (Html.BeginForm("Manage", "Account")) {

         @Html.AntiForgeryToken()

}

이 메서드는 숨겨진 폼 필드를 추가해줄 뿐만 아니라 쿠키 토큰도 설정해줍니다.

 

CSRF 방지와 AJAX

보통 AJAX 요청은 HTML 폼 데이터 대신 JSON 데이터로 전송되는 경우가 많기 때문에, AJAX 요청에서는 폼 토큰이 문제가 될 수 있습니다. 이 문제를 해결할 수 있는 한 가지 방법은 토큰을 사용자 지정 HTTP 헤더에 담아서 전송하는 것입니다. 다음 코드는 Razor 구문으로 토큰들을 생성한 다음, 이를 AJAX 요청에 추가합니다.

토큰들은 AntiForgery.GetTokens 호출을 통해서 서버 측에서 생성됩니다.

 

==============================================================

<script>

    @functions{

         public string TokenHeaderValue()

         {

                  string cookieToken, formToken;

                  AntiForgery.GetTokens(null, out cookieToken, out formToken);

                  return cookieToken + ":" + formToken;

          }

  }

 

 $.ajax("api/values", {

     type: "post",

     contentType: "application/json",

     data: { }, // JSON data goes here

     dataType: "json",

     headers: {

          'RequestVerificationToken': '@TokenHeaderValue()'

      }

   });

</script>

=============================================================

 

그리고 요청을 처리할 때, 요청 헤더에서 토큰들을 추출합니다. 그런 다음, AntiForgery.Validate 메서드를 호출해서 토큰들의 유효성을 검사합니다. 만약, 토큰이 유효하지 않으면 Validate 메서드에서 예외가 던져집니다.

=============================================================

void ValidateRequestHeader(HttpRequestMessage request)

{

       string cookieToken = "";

       string formToken = "";

 

       IEnumerable<string> tokenHeaders;

       if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))

       {

            string[] tokens = tokenHeaders.First().Split(':');

            if (tokens.Length == 2)

            {

                      cookieToken = tokens[0].Trim();

                      formToken = tokens[1].Trim();

            }

       }

      AntiForgery.Validate(cookieToken, formToken);

}

 

 

http://www.egocube.pe.kr/Translation/Content/asp-net-web-api/201402030001

 

보안: 크로스 사이트 요청 위조(Cross-Site Request Forgery) 공격 방지하기

크로스 사이트 요청 위조(CSRF, Cross-Site Request Forgery) 공격은 사용자가 현재 로그인해 있는 취약한 사이트로 악의적인 사이트에서 요청을 전송하는 공격입니다.

www.egocube.pe.kr

 

+ Recent posts