Microsoft 보안 권고 3137909

ASP.NET 템플릿의 취약성으로 인해 변조가 허용될 수 있음

게시 날짜: 2016년 2월 9일 | 업데이트: 2016년 2월 10일

버전: 1.1

요약

Microsoft는 Visual Studio 2013, Visual Studio 2015, ASP.NET MVC5 및 ASP.NET MVC6의 퍼블릭 버전에서 취약성에 대한 정보를 제공하기 위해 이 보안 권고를 릴리스합니다. 또한 이 권고는 개발자가 빌드한 컨트롤과 구성 요소가 취약성의 영향을 받지 않도록 하기 위해 개발자가 할 수 있는 일에 대한 지침을 제공합니다.

Microsoft는 영향을 받는 ASP.NET 프로젝트 템플릿을 사용하여 빌드된 웹 애플리케이션에 대한 CSRF(교차 사이트 요청 위조) 공격 시나리오에서 사용할 수 있는 Visual Studio 2013 및 Visual Studio 2015의 공개 버전에서 보안 취약성을 알고 있습니다. Microsoft ASP.NET MVC5 및 ASP.NET MVC6 프로젝트 템플릿은 소프트웨어 개발자가 새 웹 애플리케이션을 위한 시작 템플릿으로 사용합니다.

요소 완화

  • 2FA(2단계 인증)는 생성된 애플리케이션에서 기본적으로 사용하도록 설정되지 않습니다. 개발자가 사용자의 전화 번호에 따라 2FA를 사용하도록 설정하지 않은 경우 전화 번호가 제거되면 보안에 영향을 주지 않습니다.

권고 FAQ

공격자가 취약성을 어떻게 악용할 수 있나요?
공격자는 CSRF(교차 사이트 요청 위조)를 사용하여 취약한 템플릿으로 생성된 웹 애플리케이션에 요청을 보낸 다음 ASP.NET ID 데이터베이스에서 인증된 사용자의 전화 번호를 제거할 수 있습니다. 악용된 취약성의 결과로 전화 번호에 의존하는 2FA(2단계 인증) 메커니즘이 제거됩니다. 사용자의 암호는 영향을 받지 않습니다.

업데이트는 무엇을 수행하나요?
이 업데이트는 MVC5 및 MVC6용 Visual Studio 2015 ASP.NET 프로젝트 템플릿을 수정합니다.

템플릿 업데이트는 새 애플리케이션에만 영향을 줍니다. 이러한 이유로 Microsoft는 이러한 템플릿을 사용하여 웹 애플리케이션을 빌드한 개발자가 제안된 작업 섹션에 나열된 즉각적인 조치를 취하여 해당 웹 애플리케이션이 취약성에 노출되었는지 평가한 다음, 해당 섹션의 해결 방법을 사용하여 취약한 응용 프로그램을 보호하기 위해 코드를 변경하여 애플리케이션을 업데이트할 것을 강력히 권장합니다.

Visual Studio 2013을 실행하는 경우 제안된 작업 섹션에 나열된 해결 방법을 사용하여 영향을 받는 템플릿을 사용할 때마다 애플리케이션을 수동으로 업데이트해야 합니다.

업데이트를 적용할 어떻게 할까요? 있나요?

  1. Visual Studio를 시작합니다.
  2. 도구 메뉴에서 확장을 선택하고 업데이트.
  3. 업데이트 트리를 확장합니다.
  4. 제품 업데이트 아래에서 다음 두 항목을 찾습니다.
    • Microsoft ASP.NET 및 Web Tools
    • Microsoft ASP.NET 웹 프레임워크 및 도구
  5. 각 업데이트를 선택하고 업데이트를 클릭합니다.

제안된 작업

다음 해결 방법 정보는 ASP.NET 프로젝트 템플릿에서 만든 기존 애플리케이션에 대해 변경해야 하는 내용을 자세히 설명합니다.

Visual Studio 2015 MVC 5 및 Visual Studio 2013 MVC 5
C의 경우#

  1. Controllers 디렉터리에서 ManageController.cs 로드합니다.

  2. Remove전화Number()(줄 199)를 검색합니다.

  3. 템플릿 코드는 사용자 지정 없이 다음과 같이 표시됩니다.

     public async Task<actionresult> RemovePhoneNumber()
     {
         var result = await UserManager.SetPhoneNumberAsync(User.Identity.GetUserId(), null);
         if (!result.Succeeded)
         {
             return RedirectToAction("Index", new { Message = ManageMessageId.Error });
         }
         var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
         if (user != null)
         {
             await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
         }
         return RedirectToAction("Index", new { Message = ManageMessageId.RemovePhoneSuccess });
     }
    
  4. 코드가 다음과 같이 표시되도록 [HttpPost][ValidateAntiForgeryToken] 특성을 함수 정의에 추가합니다.

     [HttpPost]
     [ValidateAntiForgeryToken]
     public async Task</actionresult><actionresult> RemovePhoneNumber()
     {
         var result = await UserManager.SetPhoneNumberAsync(User.Identity.GetUserId(), null);
         if (!result.Succeeded)
         {
             return RedirectToAction("Index", new { Message = ManageMessageId.Error });
         }
         var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
         if (user != null)
         {
             await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
         }
         return RedirectToAction("Index", new { Message = ManageMessageId.RemovePhoneSuccess });
     }
    
  5. Views/Manage 폴더에서 Index.cshtml 파일을 로드합니다.

  6. <dt>전화 번호:</dt> 검색(줄 40)

  7. 사용자 지정 없이 템플릿 코드는 다음과 같이 표시됩니다.

     <dt>Phone Number:</dt>
    
@(모델. 전화Number ?? "None") [ @if(Model.전화Number != null) { @Html.ActionLink("Change", "Add전화Number") @:  |  @Html.ActionLink("Remove", "Remove전화Number") } else { @Html.ActionLink("Add", "Add전화Number") } ] ]
```
  1. 다음과 같이 표시되도록 보기 코드를 변경합니다.

     <dt>Phone Number:</dt>
    
@(모델. 전화Number ?? "None") @if(Model.전화Number != null) {
using (Html.BeginForm("Remove전화Number", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { @Html.AntiForgeryToken() } } else { }
```
  1. 애플리케이션을 다시 컴파일한 다음 다시 배포합니다.

Visual Basic의 경우

  1. Controllers 디렉터리에서 ManageController.cs 로드합니다.

  2. Remove전화Number()(줄 164)를 검색합니다.

  3. 사용자 지정 없이 템플릿 코드는 다음과 같이 표시됩니다.

         Public Async Function RemovePhoneNumber() As Task(Of ActionResult)
             Dim result = Await UserManager.SetPhoneNumberAsync(User.Identity.GetUserId(), Nothing)
             If Not result.Succeeded Then
                 Return RedirectToAction("Index", New With {
                     .Message = ManageMessageId.[Error]
                 })
             End If
             Dim userInfo = Await UserManager.FindByIdAsync(User.Identity.GetUserId())
             If userInfo IsNot Nothing Then
                 Await SignInManager.SignInAsync(userInfo, isPersistent:=False, rememberBrowser:=False)
             End If
             Return RedirectToAction("Index", New With {
                 .Message = ManageMessageId.RemovePhoneSuccess
             })
         End Function
    
  4. 함수 정의에 HttpPost><ValidateAntiForgeryToken> 특성을 추가하여 다음과 같이 표시합니다.<

         <httppost>
    
  1. Views/Manage 폴더에서 Index.vbhtml 파일을 로드합니다.

  2. <dt>전화 번호:</dt> 검색(줄 37)

  3. 템플릿 코드는 사용자 지정 없이 다음과 같이 표시됩니다.

                 <dt>Phone Number:</dt>
    
@(If(Model.전화Number, "None")) [ @If(Model.전화수
Nothing) then @Html.ActionLink("Change", "Add전화Number") @:  |  @Html.ActionLink("Remove", "Remove전화Number") Else @Html.ActionLink("Add", "Add전화Number") End If ]
```
  1. 다음과 같이 표시되도록 보기 코드를 변경합니다.

                 <dt>Phone Number:</dt>
    
@(If(Model.전화number, "None")) @If(Model.전화수
Nothing) Then @
@ @Using Html.BeginForm("Remove전화Number", "Manage", FormMethod.Post, New with {.class = "form-horizontal", .role = "form"}) @Html.AntiForgeryToken @ End using Else @ End If
```
  1. 애플리케이션을 다시 컴파일한 다음 다시 배포합니다.

Visual Studio 2015 MVC 6
C의 경우#

  1. Controllers 디렉터리에서 ManageController.cs 로드합니다.

  2. Remove전화Number()(줄 178)를 검색합니다.

  3. 사용자 지정 없이 템플릿 코드는 다음과 같이 표시됩니다.

     // GET: /Manage/RemovePhoneNumber
     [HttpGet]
     public async Task<iactionresult> RemovePhoneNumber()
     {
          var user = await GetCurrentUserAsync();
          if (user != null)
          {
              var result = await _userManager.SetPhoneNumberAsync(user, null);
              if (result.Succeeded)
              {
                  await _signInManager.SignInAsync(user, isPersistent: false);
                  return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess });
             }
         }
         return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
     }
    
  4. [HttpGet] 특성을 제거한 다음 코드가 다음과 같이 표시되도록 [HttpPost][ValidateAntiForgeryToken] 특성을 함수 정의에 추가합니다.

      [HttpPost]
      [ValidateAntiForgeryToken]
     public async Task</iactionresult><iactionresult> RemovePhoneNumber()
     {
         var user = await GetCurrentUserAsync();
         if (user != null)
         {
             var result = await _userManager.SetPhoneNumberAsync(user, null);
             if (result.Succeeded)
             {
                 await _signInManager.SignInAsync(user, isPersistent: false);
                 return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess });
             }
         }
         return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
    }
    
  5. Views/Manage 폴더에서 Index.cshtml 파일을 로드합니다.

  6. 다음과 같이 표시되도록 뷰 파일을 완전히 바꿉니다.

     @model IndexViewModel
     @{
         ViewData["Title"] = "Manage your account";
     }
    
     <h2>@ViewData["Title"].</h2>
    

@ViewData["StatusMessage"]

    <div>

계정 설정 변경


암호:
@if(Model.HasPassword) { } else { }
외부 로그인:
@Model.Logins.Count [  관리  ]
Phone Number:
전화 숫자는 2단계 인증에서 두 번째 인증 요소로 사용할 수 있습니다. SMS를 사용하는 2단계 인증을 지원하도록 이 ASP.NET 애플리케이션을 설정하는 방법에 대한 자세한 내용은 이 문서를 참조하세요. @*@(모델. 전화Number ?? "None") @if(Model.전화Number != null) {
[]
} else { }* @
2단계 인증:
구성된 2단계 인증 공급자가 없습니다. 2단계 인증을 지원하도록 이 애플리케이션을 설정하려면 이 문서를 참조하세요. @*@if(Model.TwoFactor) {
사용 []
} else {
[] 사용 안 함
}* @
```
  1. 애플리케이션을 다시 컴파일한 다음 다시 배포합니다.

Visual Basic의 경우

  • ASP.Net Core(이전 ASP.NET 5)는 Visual Basic을 지원하지 않습니다.

추가 제안된 작업

  • Visual Studio 도구 업데이트를 다음 위치에서 직접 다운로드합니다.

  • PC 보호
    고객이 방화벽을 사용하도록 설정하고, 소프트웨어 업데이트를 받고, 바이러스 백신 소프트웨어를 설치하는 컴퓨터 보호 지침을 따르도록 계속 권장합니다. 자세한 내용은 Microsoft 금고ty 및 Security Center를 참조하세요.

  • Microsoft 소프트웨어 업데이트 유지
    Microsoft 소프트웨어를 실행하는 사용자는 최신 Microsoft 보안 업데이트를 적용하여 컴퓨터가 최대한 보호되도록 해야 합니다. 소프트웨어가 최신 상태인지 확실하지 않은 경우 Microsoft 업데이트를 방문하여 컴퓨터에서 사용 가능한 업데이트를 검색하고 사용자에게 제공되는 우선 순위가 높은 업데이트를 설치합니다. Microsoft 제품에 대한 업데이트를 제공하도록 자동 업데이트를 사용하도록 설정하고 구성한 경우 업데이트가 릴리스될 때 사용자에게 전달되지만 업데이트가 설치되어 있는지 확인해야 합니다.

기타 정보

Feedback

지원

  • 미국 및 캐나다의 고객은 보안 지원에서 기술 지원을 받을 수 있습니다. 자세한 내용은 Microsoft 도움말 및 지원을 참조하세요.
  • 해외 고객은 현지 Microsoft 자회사로부터 지원을 받을 수 있습니다. 자세한 내용은 국제 지원을 참조하세요.
  • Microsoft TechNet Security 는 Microsoft 제품의 보안에 대한 추가 정보를 제공합니다.

부인

이 권고에 제공된 정보는 어떠한 종류의 보증도 없이 "있는 그대로" 제공됩니다. Microsoft는 특정 목적에 대한 상품성 및 적합성에 대한 보증을 포함하여 명시적이거나 묵시적인 모든 보증을 부인합니다. 어떠한 경우에도 Microsoft Corporation 또는 해당 공급업체는 Microsoft Corporation 또는 공급업체가 이러한 손해의 가능성을 통보한 경우에도 직접, 간접, 부수적, 결과적, 비즈니스 이익 손실 또는 특별 손해를 포함한 모든 손해에 대해 책임을 지지 않습니다. 일부 주에서는 결과적 또는 부수적 손해에 대한 책임의 배제 또는 제한을 허용하지 않으므로 앞에서 설명한 제한이 적용되지 않을 수 있습니다.

수정 내용

  • V1.0(2016년 2월 9일): 공지 게시됨.
  • V1.1(2016년 2월 10일): Microsoft ASP.NET Web Frameworks 및 도구 및 Microsoft ASP.NET 및 Web Tools 대한 다운로드 정보를 포함하도록 권고가 업데이트되었습니다. 이는 정보 변경에만 해당합니다.

페이지 생성 2016-02-19 14:36-08:00.