Microsoft Security Advisory 3137909

Vulnerabilities in ASP.NET Templates Could Allow Tampering

Published: February 9, 2016 | Updated: February 10, 2016

Version: 1.1

Executive Summary

Microsoft is releasing this security advisory to provide information about a vulnerability in the public versions of Visual Studio 2013, Visual Studio 2015, ASP.NET MVC5, and ASP.NET MVC6. This advisory also provides guidance on what developers can do to help ensure that the controls and components that they have built are not subject to the vulnerability.

Microsoft is aware of a security vulnerability in the public versions of Visual Studio 2013 and Visual Studio 2015 that could be used in a cross-site request forgery (CSRF) attack scenario against web applications built using the affected ASP.NET project templates. The Microsoft ASP.NET MVC5 and ASP.NET MVC6 project templates are used by software developers as starter templates for new web applications.

Mitigating Factors

  • Two-factor authentication (2FA) is not enabled by default in any generated applications. If a developer has not enabled 2FA based on a user’s telephone number, then there is no security impact if the telephone number is removed.

Advisory FAQ

How could an attacker exploit the vulnerability?
An attacker could use cross-site request forgery (CSRF) to send a request to a web application generated with the vulnerable templates, and then remove an authenticated user’s telephone number from the ASP.NET Identity Database. The result of the exploited vulnerability removes any two-factor authentication (2FA) mechanism that relies on a telephone number. The user’s password is not affected.

What does the update do?
The update corrects the Visual Studio 2015 ASP.NET project templates for MVC5 and MVC6.

The template updates only affect new applications. For this reason, Microsoft strongly recommends that developers who have built web applications using these templates take immediate action, listed in Suggested Actions section, to evaluate their web applications for exposure to the vulnerability, and then use the workarounds in that section to make code changes to update their applications to protect them from the vulnerable.

If you are running Visual Studio 2013, you need to use the workaround steps listed in the Suggested Actions section to update your applications manually every time that you used the affected templates.

How do I apply the update?

  1. Start Visual Studio.
  2. Under the Tools menu, choose Extensions and Updates.
  3. Expand the Updates tree.
  4. Under Product Updates locate the following two entries:
    • Microsoft ASP.NET and Web Tools
    • Microsoft ASP.NET Web Frameworks and Tools
  5. Select each update and click Update.

Suggested Actions

The following workaround information details the changes that you must make to existing applications created from the ASP.NET project templates.

Visual Studio 2015 MVC 5 and Visual Studio 2013 MVC 5
For C#

  1. From the Controllers directory, load ManageController.cs.
  2. Search for RemovePhoneNumber() (line 199).
  3. The template code, without any customization, will display as follows:

     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. Add the [HttpPost] and [ValidateAntiForgeryToken] attributes to the function definition, so that the code displays as follows:

     [HttpPost]
     [ValidateAntiForgeryToken]
     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 });
     }
    
  5. From the Views/Manage folder, load the Index.cshtml file.

  6. Search for <dt>Phone Number:</dt> (Line 40)
  7. The template code, without any customization displays as follows:

     <dt>Phone Number:</dt>
     <dd>
     @(Model.PhoneNumber ?? "None") [
     @if (Model.PhoneNumber != null)
     {
         @Html.ActionLink("Change", "AddPhoneNumber")
         @: &nbsp;|&nbsp;
        @Html.ActionLink("Remove", "RemovePhoneNumber")
     }
     else
     {
         @Html.ActionLink("Add", "AddPhoneNumber")
     }
     ]
     </dd>
    
  8. Change the view code to display as follows:

     <dt>Phone Number:</dt>
     <dd>
         @(Model.PhoneNumber ?? "None")
         @if (Model.PhoneNumber != null)
         {
             <br />
             <text>[&nbsp;&nbsp;@Html.ActionLink("Change", "AddPhoneNumber")&nbsp;&nbsp;]</text>
             using (Html.BeginForm("RemovePhoneNumber", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
             {
                 @Html.AntiForgeryToken()
                 <text>[<input type="submit" value="Remove" class="btn-link" />]</text>
             }
         }
         else
         {
             <text>[&nbsp;&nbsp;@Html.ActionLink("Add", "AddPhoneNumber")&nbsp;&nbsp;]</text>
         }
     </dd>
    
  9. Recompile your application and then redeploy it.

For Visual Basic

  1. From the Controllers directory, load ManageController.cs.
  2. Search for RemovePhoneNumber() (line 164).
  3. The template code, without any customization displays as follows:

         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. Add the <HttpPost> and <ValidateAntiForgeryToken> attributes to the function definition to make them display as follows:

         <HttpPost>
         <ValidateAntiForgeryToken>
         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
    
  5. From the Views/Manage folder, load the Index.vbhtml file.

  6. Search for <dt>Phone Number:</dt> (Line 37)
  7. The template code, without any customization, displays as follows:

                 <dt>Phone Number:</dt>
                 <dd>
                     @(If(Model.PhoneNumber, "None")) [
                     @If (Model.PhoneNumber <> Nothing) Then
                         @Html.ActionLink("Change", "AddPhoneNumber")
                         @: &nbsp;|&nbsp;
                         @Html.ActionLink("Remove", "RemovePhoneNumber")
                     Else
                         @Html.ActionLink("Add", "AddPhoneNumber")
                     End If
                     ]
                 </dd>
    
  8. Change the view code to display as follows:

                 <dt>Phone Number:</dt>
                 <dd>
                     @(If(Model.PhoneNumber, "None"))
                     @If (Model.PhoneNumber <> Nothing) Then
                         @<br />
                         @<text>[&nbsp;&nbsp;@Html.ActionLink("Change", "AddPhoneNumber")&nbsp;&nbsp;]</text>
                         @Using Html.BeginForm("RemovePhoneNumber", "Manage", FormMethod.Post, New With {.class = "form-horizontal", .role = "form"})
                             @Html.AntiForgeryToken
                             @<text>[<input type="submit" value="Remove" class="btn-link" />]</text>
                         End Using
                     Else
                         @<text>[&nbsp;&nbsp;@Html.ActionLink("Add", "AddPhoneNumber") &nbsp;&nbsp;]</text>
                     End If
                 </dd>
    
  9. Recompile the application and then redeploy it.

Visual Studio 2015 MVC 6
For C#

  1. From the Controllers directory, load ManageController.cs.
  2. Search for RemovePhoneNumber() (line 178).
  3. The template code, without any customization displays as follows:

     // 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. Remove the [HttpGet] attribute, and then add the [HttpPost] and [ValidateAntiForgeryToken] attributes to the function definition, so that the code displays as follows:

      [HttpPost]
      [ValidateAntiForgeryToken]
     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 });
    }
    
  5. From the Views/Manage folder, load the Index.cshtml file.

  6. Completely replace the view file so that it displays as follows:

     @model IndexViewModel
     @{
         ViewData["Title"] = "Manage your account";
     }
    
     <h2>@ViewData["Title"].</h2>
     <p class="text-success">@ViewData["StatusMessage"]
    
     <div>
         <h4>Change your account settings</h4>
         <hr />
         <dl class="dl-horizontal">
             <dt>Password:</dt>
             <dd>
                 @if (Model.HasPassword)
                 {
                     <text>[&nbsp;&nbsp;<a asp-controller="Manage" asp-action="ChangePassword">Change</a>&nbsp;&nbsp;]</text>
                 }
                 else
                 {
                     <text>[&nbsp;&nbsp;<a asp-controller="Manage" asp-action="SetPassword">Create</a>&nbsp;&nbsp;]</text>
                 }
             </dd>
             <dt>External Logins:</dt>
             <dd>
                 @Model.Logins.Count [&nbsp;&nbsp;<a asp-controller="Manage" asp-action="ManageLogins">Manage</a>&nbsp;&nbsp;]
             </dd>
             <dt>Phone Number:</dt>
             <dd>
    
                     Phone Numbers can used as a second factor of verification in two-factor authentication.
                     See <a href="http://go.microsoft.com/fwlink/?LinkID=532713">this article</a>
                     for details on setting up this ASP.NET application to support two-factor authentication using SMS.
    
                 @*@(Model.PhoneNumber ?? "None")
                     @if (Model.PhoneNumber != null)
                     {
                         <br />
                         <text>[&nbsp;&nbsp;<a asp-controller="Manage" asp-action="AddPhoneNumber">Change</a>&nbsp;&nbsp;]</text>
                         <form asp-controller="Manage" asp-action="RemovePhoneNumber" method="post" role="form">
                             [<button type="submit" class="btn-link">Remove</button>]
                         </form>
                     }
                     else
                     {
                         <text>[&nbsp;&nbsp;<a asp-controller="Manage" asp-action="AddPhoneNumber">Add</a>&nbsp;&nbsp;]</text>
                     }*@
             </dd>
    
             <dt>Two-Factor Authentication:</dt>
             <dd>
    
                     There are no two-factor authentication providers configured. See <a href="http://go.microsoft.com/fwlink/?LinkID=532713">this article</a>
                     for setting up this application to support two-factor authentication.
    
                 @*@if (Model.TwoFactor)
                     {
                         <form asp-controller="Manage" asp-action="DisableTwoFactorAuthentication" method="post" class="form-horizontal" role="form">
                             Enabled [<button type="submit" class="btn-link">Disable</button>]
                         </form>
                     }
                     else
                     {
                         <form asp-controller="Manage" asp-action="EnableTwoFactorAuthentication" method="post" class="form-horizontal" role="form">
                             [<button type="submit" class="btn-link">Enable</button>] Disabled
                         </form>
                     }*@
             </dd>
         </dl>
     </div>
    
  7. Recompile your application and then redeploy it.

For Visual Basic

  • ASP.Net Core (previously ASP.NET 5) does not support Visual Basic.

Additional Suggested Actions

  • Download the Visual Studio tool updates directly at:

  • Protect your PC
    We continue to encourage customers to follow our Protect Your Computer guidance of enabling a firewall, getting software updates, and installing antivirus software. For more information, see Microsoft Safety & Security Center.

  • Keep Microsoft Software Updated
    Users running Microsoft software should apply the latest Microsoft security updates to help make sure that their computers are as protected as possible. If you are not sure whether your software is up to date, visit Microsoft Update, scan your computer for available updates, and install any high-priority updates that are offered to you. If you have automatic updating enabled and configured to provide updates for Microsoft products, the updates are delivered to you when they are released, but you should verify that they are installed.

Other Information

Feedback

Support

Disclaimer

The information provided in this advisory is provided "as is" without warranty of any kind. Microsoft disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. In no event shall Microsoft Corporation or its suppliers be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages, even if Microsoft Corporation or its suppliers have been advised of the possibility of such damages. Some states do not allow the exclusion or limitation of liability for consequential or incidental damages so the foregoing limitation may not apply.

Revisions

  • V1.0 (February 9, 2016): Advisory published.
  • V1.1 (February 10, 2016): Advisory updated to include download information for Microsoft ASP.NET Web Frameworks, and Tools and Microsoft ASP.NET and Web Tools. This is an informational change only.

Page generated 2016-02-19 14:36-08:00.