2024年最佳天气API
.NET XSS:示例与预防
这篇文章将作为有关 .NET XSS 的指南。
这是什么?为什么它很重要?好吧,开发应用程序并将其发布出去,虽然不是一件容易的事,但这只是第一步。第二步(可能永无止境)是确保它继续工作,以最佳方式满足用户的需求。
这听起来简单,其实不然:这其中涉及很多因素,安全性是其中最重要的因素之一。
这就是 XSS 的用武之地。作为最常见的安全威胁之一,作为开发人员,您必须意识到这一点。没有一种编程语言或堆栈可以免受其害,.NET 当然也不例外。
我们将以一些基础知识作为本篇文章的开篇。您将获得 XSS 的简要定义,然后了解其造成的损害及其工作原理。之后,我们将进入文章中与 .NET 相关的部分。您将看到 .NET XSS 的示例和自我保护技巧。
让我们开始吧。
要求
这篇文章将以实践部分为特色。如果你想跟进,需要满足一些要求:
.NET XSS 基础知识
正如承诺的那样,让我们从一些基础知识开始这篇文章,回答 XSS 是什么、为什么和如何存在的问题,不仅在 .NET 中,而且在一般情况下。
什么是 XSS?
XSS 代表跨站点脚本。它是一种注入攻击。顾名思义,注入攻击是指恶意代理能够成功将一些未经授权的代码引入应用程序并运行。注入的代码与应用程序的正确代码交互,使其以不应该的方式运行。
XSS 攻击是指恶意人员能够“诱骗”合法网站在不知情的情况下执行恶意脚本,而这些脚本是通过利用用户输入的常用机制(例如 URL 参数或表单字段)提供的。简而言之,攻击者利用接受 HTML 代码作为输入的易受攻击的网站,然后在不对其进行编码的情况下显示该代码,并注入未经授权的<script>标记,希望该标记被接受并执行。
XSS 为何如此危险?
在最坏的情况下,成功的 XSS 攻击会对应用程序造成灾难性的破坏。通过成功执行脚本,攻击者可以访问浏览器 cookie(这将允许他们代表用户执行操作或访问数据)、本地存储等。后果可能包括未经授权的数据访问、帐户窃取甚至未经授权的金融交易。
请记住,XSS 经常与其他类型的攻击一起使用(例如CSRF) ,并且会促进其他类型的攻击。
XSS 如何工作?
成功的 XSS 攻击通常是由于网站盲目信任所有用户输入。稍后我会再谈这个问题,但重申一遍也不过分:永远不要相信用户输入!
那么,XSS 攻击是如何发生的呢?下面是一个简单的例子。假设您有一个 Web 应用程序,它将一个选项作为 URL 参数,如下所示:
https://www.example.com/products.html?category=phone
然后,假设输入的值显示在页面的 HTML 中:
<h2>Category: phone</h2>
如果用户输入了类似这样的内容会怎么样?
https://www.example.com/products.html?category=<script>alert(‘hello!’);</script>
在这种情况下,网站没有针对 XSS 的保护。因此,脚本将被执行,您将看到显示的hello消息。当然,在现实生活中,攻击者会输入一些恶意的代码片段,而不是良性的消息。
.NET XSS:您的应用程序如何受到保护?
与其他几种安全威胁一样,.NET 已经很好地防御了 XSS,实际上你需要付出一些努力才能让自己失去保护。为了了解它的工作原理,让我们创建一个示例项目。
创建示例项目
首先启动 Visual Studio 并单击“创建新项目”。然后,系统将提示您选择项目类型。选择ASP.NET Core Web App (Model-View-Controller),如下图所示:
在下一个屏幕上,输入项目名称和位置以及解决方案的名称:
在下一个屏幕上,只需接受所有默认设置并单击“创建”。Visual Studio 完成应用程序创建后,执行快速冒烟测试。按 F5,您的默认浏览器将打开并显示如下内容:
添加模型
下一步是添加模型。在 Visual Studio 中,转到解决方案资源管理器,右键单击“模型”文件夹,然后转到“添加和类”。输入Todo作为类的名称并确认。创建类后,将其内容替换为以下内容:
namespace XSSNetDemo.Models
{
public class Todo
{
public int Id { get; set; }
public string? Description { get; set; }
public DateOnly DueDate { get; set; }
}
}
因此,此示例应用程序将是一个老生常谈的话题:待办事项列表。上面的类表示待办事项,具有 ID、描述和截止日期。下一步,我们要为我们的应用程序创建控制器和视图。
搭建控制器和视图
转到解决方案资源管理器并右键单击文件夹控制器。 然后,转到添加>新脚手架项。
在下一个屏幕上,选择带有视图的 MVC 控制器,使用 Entity Framework,然后单击添加:
然后系统会提示您输入一些重要的信息。
- 首先,您必须定义要为哪个模型生成控制器。选择Todo类。
- 然后,您必须为控制器提供数据库上下文。我们没有数据库上下文,因此请单击加号并添加新上下文。
- 最后,更改 Controller 名称,因为 Visual Studio 将使用复数规则并得出TodoesController。我认为TodosController看起来更好,所以我将其更改为那样。
至于其他选项,保留其默认值。单击“添加”完成。
在运行应用程序之前,让我们做一些小改动,以便我们可以使用内存数据库。转到Program.cs类并删除以下行:
builder.Services.AddDbContext<XSSNetDemoContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("XSSNetDemoContext")));
将其替换为以下内容:
builder.Services.AddDbContext<XSSNetDemoContext>(options => options.UseInMemoryDatabase("todos"));
最后,转到“工具”菜单,然后转到“NuGet 包管理器” > “包管理器控制台”。粘贴并运行以下命令:
Install-Package Microsoft.EntityFrameworkCore.InMemory
让我们运行它
您终于可以运行该应用程序了。在 Visual Studio 中按 F5。您的浏览器将打开该应用程序。转到地址栏并将 /Todos 附加到地址。您应该看到类似以下内容:
单击“新建”,您将进入一个新屏幕,您可以在其中添加新的待办事项:
现在,让我们测试一下是否可以将一些脚本注入此应用。在截止日期行中,输入任何您想要的内容。但对于描述,请尝试输入一些脚本,例如<script>alert(‘hey!’);</script>,然后单击“创建”按钮。
幸运的是,结果并不尽如人意:
如您所见,应用程序只是显示“恶意”脚本,而不是执行它。这怎么可能呢?好吧,如果您使用浏览器显示页面底层 HTML 代码的功能,您将看到类似以下内容:
<tbody>
<tr>
<td>
<script>alert('oi');</script>
</td>
<td>
05/02/2022 12:17:00
</td>
<td>
<a href="/Todos/Edit/1">Edit</a> |
<a href="/Todos/Details/1">Details</a> |
<a href="/Todos/Delete/1">Delete</a>
</td>
</tr>
</tbody>
上面的代码显示 <script> 标记中的小于号和大于号被替换为那些看起来很奇怪的代码。这些是 HTML 实体,这意味着 HTML 标记已编码。这样,页面就可以安全地显示它们,而不是运行它们。
让应用程序遭受 XSS 攻击
出于好奇,假设您希望让应用程序容易受到 XSS 攻击。您会怎么做?
转到Views文件夹。 找到Todos文件夹,然后打开名为Index.cshtml的文件。
在文件内,找到以下行:
@Html.DisplayFor(modelItem => item.Description)
将其替换为以下内容:
@Html.Raw(item.Description)
正如代码所示,现在我们显示的是未经任何编码的原始 HTML。为了说明清楚,这是糟糕的做法!不要在现实生活中这样做。
现在,再次运行该应用程序,再次注入恶意脚本作为描述,您将看到以下内容:
另一个坏例子
在我们开始之前,这里还有另一个不该做的事情的例子。返回TodosController.cs类并添加以下方法:
public string Introduce(string id)
{
return $"Hello, my name is {id}.";
}
现在,再次运行该应用程序。然后,将 /Todos/Introduce/<YOUR-NAME> 附加到地址,确保使用您的真实姓名。您将看到类似以下内容:
现在你知道该怎么做了。用脚本替换名称,然后它就会被执行。你该如何解决这个问题?很简单:
public string Introduce(string id)
{
return HtmlEncoder.Default.Encode($"Hello, my name is {id}.");
}
确保将using System.Text.Encodings.Web;添加到您的使用列表中,这样就大功告成了。现在代码正确地对输入的 HTML 代码进行编码,避免了脚本的解释和执行。
结论
XSS 是一种可能造成毁灭性影响的安全威胁,但避免它相对简单。您必须记住永远不要相信用户输入,并且始终对要显示的 HTML 代码进行编码。
此外,如果您完全不允许用户提交 HTML(例如,出于富文本格式目的),那么这会有所帮助。如果有需要,请选择 markdown 之类的格式,这样您可以在显示时安全地将其转换为 HTML。