ASP.NET MVC 中的安全性
关于身份验证、授权、XSS 和 CSRF(跨站请求伪造)的解释
引言
本文旨在解释在开发安全的 ASP.NET MVC 应用程序时应注意的一些安全措施。本文将解释
- 身份验证
- Authorization
- XSS
- CSRF(跨站请求伪造)
身份验证
当您验证用户身份时,您正在验证用户的身份。如果您需要在 MVC 应用程序中验证用户,那可能是因为您正在构建一个限制特定用户访问的应用程序。这与授权完全独立,授权是确定特定人员是否允许执行某个操作。
MVC 中有两种身份验证机制
- 表单身份验证
- Windows 身份验证
表单身份验证
基于表单的身份验证是提供一个输入表单,用户可以在其中输入用户名和密码,并附带应用程序中验证这些凭据所需的逻辑。MVC 为表单身份验证提供了大量基础架构支持。表单身份验证是高度可定制的,您可以自定义从登录表单到凭据存储位置以及如何验证这些凭据的一切。ASP.NET 中的表单身份验证默认依赖于 cookie。一旦用户登录到应用程序,运行时就可以在浏览器上发出一个 cookie。然后浏览器将随后的每个请求都发送该 cookie。ASP.NET 将看到该 cookie 并知道用户已经过身份验证,无需再次登录。
注意:警告,SSL 是确保表单身份验证安全的必需条件。如果您在 http 上运行应用程序,任何窥探网络的人都可以看到用户的凭据。
Windows 身份验证
Windows 身份验证也称为集成身份验证,因为用于身份验证用户的是内置在 Windows 操作系统中的用户组件。一旦用户登录到域,Windows 就可以自动将其验证到应用程序中。Windows 身份验证通常用于公司防火墙内部运行的内部网应用程序,其中所有用户都登录到 Windows 域。它将提供单点登录体验。他们只需登录一次域,就可以在多个内部网应用程序中进行身份验证。
我们何时选择表单身份验证,何时选择 Windows 身份验证?
- 如果您想构建一个公共网站,那么表单身份验证是最佳选择,因为它可以用于 Windows 域之外。
- 如果您想构建一个使用 Windows 身份运行的内部网应用程序,请使用 Windows 身份验证。
表单身份验证如何配置?
首先,我们需要更改 web.config 中的配置,如下所示
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880 />
</authentication>
这段配置告诉运行时,当我们需要验证用户时,将浏览器重定向到 /Account/Logon。这个 Account 控制器和这个 Logon 视图以及其他一些视图允许我在站点上注册。这些内容在 ASP.NET MVC 互联网模板中默认提供。表单身份验证所需的一切都随此模板提供。
选择表单身份验证模板
打开 Visual Studio 2010 >> 新建项目 >> 选择 ASP.NET MVC4 Web 应用程序,然后单击确定。
然后选择 Internet 应用程序模板,它为我们提供了表单身份验证所需的一切,例如 AccountController
、Views
等,然后单击确定。
Authorize
[Authorize]
public ActionResult Index()
{
return View();
}
Authorize
属性并不关心我们如何验证用户。我们可以使用表单身份验证或 Windows 身份验证。Authorize
关心的是用户具有身份并且我们知道他们是谁,它不会让匿名用户进入 Index 操作。当我们尝试在未经身份验证的情况下执行 Index 操作时,它会自动重定向到 Account/Logon,因为用户在此应用程序中没有帐户。因此我们需要注册登录。
我们如何使用 Windows 身份验证进行身份验证?
首先,我们需要在 web.config 文件中的配置部分进行一些更改,如下所示。
<authentication mode="Windows">
<!--<forms loginUrl="~/Account/Login" timeout="2880" />-->
</authentication>
然后将 authorize
属性应用于 index
操作
[Authorize]
public ActionResult Index()
{
return View();
}
您可以将授权筛选器应用于单个操作方法或控制器。当您将筛选器应用于控制器时,它的作用就好像您已将其应用于控制器类中的每个操作方法,并将 Authorize
筛选器应用于该类,因此 Account
控制器中的所有操作方法仅对经过身份验证的用户可用。
为了使 Windows 集成身份验证正常工作,我们需要在 IIS Express 中启用 Windows 身份验证,否则我们会收到以下错误,这是您在当今服务器配置中通常遇到的情况。
Web 服务和数据库服务等服务器程序通常默认关闭某些功能,以减少攻击面。如果我们要使 Windows 身份验证工作,我们需要将其打开。
转到 Document >> IISExpress >> config >> applicationhost.config 文件并将 Windows Authentication 启用为 true
。
您可以获取如下所示的身份验证详细信息
Authorization
authorize
属性还允许您设置一些参数以强制执行授权规则。首先,我们需要知道用户的身份,然后我们可以说只允许特定身份访问这些操作。
[Authorize(Users = "jameel,vinayan")]
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
Authorize
属性还允许您指定角色。Windows 身份验证(默认)映射到服务器上的 Windows 组或 Active Directory 中配置的组。您可以按如下方式设置角色
[Authorize(Roles = "@domainname\username")]
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
在表单身份验证中,ASP.NET 有一个角色提供程序。通过使用这些,您可以在 SqlServer 数据库中存储和管理角色。这些可以在应用程序中默认配置。最简单的方法是使用解决方案资源管理器中的以下按钮。
它会启动 ASP.NET 配置工具。这是您仅在本地开发计算机上使用的工具。它将在 web.config 位置查找并使用与该表单身份验证提供程序相同的应用程序服务数据库,该提供程序已在其中配置。您可以在此处添加和管理角色。在执行这些操作时,它会自动映射到我们在 web.config 文件中配置的数据库。
XSS
我们将面临一些特定的威胁。其中一个流行的攻击是跨站脚本攻击或 XSS。在跨站脚本攻击中,恶意用户将尝试让您的网站将恶意脚本加载到用户的浏览器中。它可能是恶意脚本、Active-X 控件,甚至是某些恶意 HTML。恶意脚本可以窃取 cookie、修改用户设置、下载恶意软件或修改内容。最糟糕的跨站脚本攻击之一是帐户劫持;恶意用户可以访问用户的凭据和个人信息。
一旦发生这种情况,您的用户将面临各种各样的问题。
演示
这是一个保存员工信息的简单应用程序。我正在放置一些 HTML 标签,例如我来自 India,然后当我尝试保存时,ASP.NET 会自动拒绝此请求,以防止跨站脚本攻击,因为 ASP.NET 会查找任何类似 HTML 的内容并拒绝该请求。实际上,强调标签没有问题,但 ASP.NET 在这里没有尝试区分任何看起来像 HTML 的东西都将被拒绝。
有时,用户需要将某些 HTML 上传到服务器,那么总是存在规避此请求验证的方法。您必须非常小心。一个选项是在 Create
操作中将 ValidationInput
属性放置到目标位置。
这样您就可以成功处理此请求。
现在我们可能会遇到 HTML 在此处编码的问题。这是因为 Razor 默认会编码所有内容,这是好事。还有另一种针对跨站点脚本的防御措施,我们可以轻松修复它。但是,validate input false 完全禁用了对跨站点脚本、恶意 HTML 的检查,而我们实际上只需要在一个特定属性中包含 HTML。因此,您可以使用 AllowHtml
属性允许 HTML 存在于一个属性中。此外,还需要进行一些更改,从 Create
操作中删除 ValidateInput
属性,并确保我们应该将 EmployeeViewModel
类作为操作参数传递,这意味着将发生模型绑定并将 HTML 移动到该属性。此外,在视图中进行一项更改,通过在 Html.Raw
助手中使用 ViewData
来显示未编码的 HTML。
然后再次,再保存一个,并在包含 HTML 标签的同一视图中显示 ViewData
。
Anti XSS 库
有人来到表单并输入以下脚本
它也更具恶意性。幸运的是,Microsoft 提供了一个用于防止此情况的库。您可以通过 NuGet 或库包管理器控制台(Visual Studio>>工具>>库包管理器>>包管理器控制台并键入 Install-Package AntiXSS
并按 Enter)下载它。
我将在下面的 Edit 动作 post 方法中添加一行代码。
这段代码将删除所有恶意内容。
跨站请求伪造
跨站请求伪造是一种危险且极其严重的攻击。想象一下,用户来到网站,尝试更新一些信息,这需要身份验证才能执行更新。一旦用户通过表单身份验证登录,您的网站将向用户的浏览器发送一个身份验证 cookie,并且网站的后续每个请求,用户的浏览器都将发送该 cookie,ASP.NET 将看到用户已通过身份验证。浏览器发送 cookie 没有任何问题,这是浏览器和 cookie 的工作方式——这意味着用户无需在每次请求中输入用户名和密码。他们只需验证一次身份,cookie 将允许他们在会话期间保持身份验证状态。
那问题是什么呢?
如果用户访问其他站点或严格从具有恶意意图的恶意来源获取 HTML,那么这个恶意来源可以提供一个表单,就像我们的应用程序会提供给用户的表单一样,然后如果用户提交表单,调用将再次被验证,因为身份验证 cookie 会提供给用户的浏览器。它总是随每个请求一起传输,并且它会将信息保存到数据库中,就像我们一旦验证了请求后总是会做的那样。只有请求中的信息可能才是用户想要提交的内容。有人欺骗用户转账或编辑他们的帐户。这里的问题不仅仅是说我们需要用户在提交某些信息时进行身份验证。我们还必须检查用户提交的信息是否来自我们的应用程序呈现给用户的表单。我们希望阻止他们从恶意来源提交表单。
演示
为了演示 CSRF,我将 authorize
属性应用于我的应用程序的两个 Edit
操作方法。
//
// GET: /CSRF/Edit/5
[Authorize]
public ActionResult Edit(int id = 0)
{
Employee employee = db.Employees.Find(id);
if (employee == null)
{
return HttpNotFound();
}
return View(employee);
}
//
// POST: /CSRF/Edit/5
[HttpPost]
[Authorize]
public ActionResult Edit(Employee employee)
{
if (ModelState.IsValid)
{
db.Entry(employee).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(employee);
}
我可以保存、编辑记录,因为我已进行身份验证。下面是我已成功保存到数据库中的示例记录。
从开发者的角度来看,我们确信我已设置了授权属性,以防止恶意用户编辑员工详细信息。
假设我以用户身份登录。我在系统中看到了一个有趣的链接。
也许这个链接你会从电子邮件或其他网站或互联网的其他区域获取。现在我将点击该链接,然后会弹出一个页面。
现在看看我们之前保存的记录,它已经改变了。发生了什么?
查看链接的源代码
查看表单指向的操作,它具有与员工发布相同的 URL。表单包含完成请求所需的所有输入,并且底部还有一些 JavaScript 代码,用于在页面加载时自动提交表单。
我们如何预防这种情况?
在 form
标签内使用 @Html.AntiForgeryToken()
。此令牌将添加一个隐藏的输入值,该值对于浏览会话是唯一的。同时,向用户的浏览器发送一个匹配值作为 cookie,以便用户接受此 cookie,并且恶意网站将无法做到这一点。
此外,您应该放置一个属性 ValidateAntiForgeryToken
来匹配表单值和 cookie 值
我将再次编辑恶意用户所做的记录。现在我将再次点击该链接,ASP.NET MVC 抛出异常,提示 AntiForgeryToken
未提供或无效。
希望您喜欢我的文章……期待您宝贵的建议……享受编程!