MVC에서 AntiForgeryToken을 사용한 CSRF 공격 방어

ASP.NET MVC는 웹 애플리케이션에서 크로스사이트 요청 위조(CSRF) 공격을 방지하기 위해 Html.AntiForgeryToken() 메서드를 제공합니다. 이 기능은 사용자 인증 상태를 악용하는 공격을 차단하며, 단순히 스크립트 삽입을 이용하는 XSS와는 목적과 방식이 다릅니다.

기본 문제 상황

예를 들어, 홈페이지에 공지를 입력하는 폼이 있다고 가정합시다. 기본적인 구현은 다음과 같습니다:

@using (Html.BeginForm("Text", "Home", FormMethod.Post))
{
    @:공지사항: <input type="text" name="Notice" id="Notice" />
    <input type="submit" value="전송" />
}

컨트롤러의 액션은 아래와 같습니다:

[HttpPost]
public ActionResult Text()
{
    ViewBag.Notice = Request.Form["Notice"];
    return View();
}

이 경우, 공격자가 외부 사이트에서 유사한 폼을 만들어서 사용자의 브라우저가 자동으로 해당 요청을 보낼 수 있습니다. 예를 들어, 공격자는 다음과 같은 HTML 파일을 생성할 수 있습니다:

<html>
<head><title>공격 페이지</title></head>
<body>
    <form method="post" action="http://localhost:6060/Home/Text">
        <input type="hidden" name="Notice" value="시스템이 해킹되었습니다!" />
        <input type="submit" value="공격 실행" />
    </form>
</body>
</html>

사용자가 이 페이지를 열고 버튼을 클릭하면, 로컬 사이트의 세션 쿠키를 사용해 공지사항을 무단 변경할 수 있습니다. 이것이 바로 전형적인 CSRF 공격입니다.

방어 방법: AntiForgery 토큰 사용

이 문제를 해결하기 위해, 뷰에 Html.AntiForgeryToken()를 추가하고, 컨트롤러 액션에 [ValidateAntiForgeryToken] 특성을 적용해야 합니다:

@using (Html.BeginForm("Text", "Home", FormMethod.Post))
{
    @Html.AntiForgeryToken()
    @:공지사항: <input type="text" name="Notice" id="Notice" />
    <input type="submit" value="전송" />
}

컨트롤러 코드:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Text()
{
    ViewBag.Notice = Request.Form["Notice"];
    return View();
}

이제 공격자가 위의 악성 폼을 통해 요청을 보내도, 서버는 토큰 검증을 실패하여 예외를 발생시키며 요청을 거부합니다.

내부 동작 원리

Html.AntiForgeryToken()System.Web.WebPages.AntiForgery 클래스의 GetHtml() 메서드를 호출하여, 임의의 값을 생성하고 다음 두 곳에 저장합니다:

  1. 클라이언트 쿠키: 이름은 기본적으로 __RequestVerificationToken
  2. 폼 내부의 숨김 필드: <input type="hidden" name="__RequestVerificationToken" value="..." />

서버에서는 [ValidateAntiForgeryToken] 특성이 요청의 쿠키 값과 폼 데이터의 토큰 값이 일치하는지 확인합니다. 불일치하거나 토큰이 없으면 InvalidOperationException이 발생합니다.

JavaScript AJAX 요청 처리

AJAX 요청에서도 CSRF 보호를 적용하려면, jQuery 플러그인을 사용해야 합니다. 예를 들어, jqueryToken-1.4.2.js를 포함하고, 다음과 같이 사용합니다:

$.ajaxAntiForgery({
    type: "post",
    url: "/Event/Mass/AddGroup",
    data: {
        GroupName: $("#GroupName").val(),
        GroupPhones: $("#GroupPhones").val()
    },
    dataType: "json",
    success: function (data) {
        if (data) {
            alert("그룹 추가 성공");
            $.unblockUI();
        } else {
            alert("추가 실패");
        }
    }
});

모든 데이터 수정 작업(삽입, 삭제, 업데이트)에는 반드시 CSRF 방어 기법을 적용해야 합니다.

요약

CSRF 공격은 사용자의 인증 상태를 악용하여 의도하지 않은 행동을 수행하게 만듭니다. ASP.NET MVC의 Html.AntiForgeryToken()[ValidateAntiForgeryToken] 조합은 이러한 공격을 효과적으로 차단합니다. 이를 통해 신뢰할 수 있는 웹 애플리케이션의 보안을 강화할 수 있습니다.

태그: ASP.NET MVC CSRF 방어 AntiForgeryToken ValidateAntiForgeryToken Web Security

8월 3일 14:40에 게시됨