视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
ASP.NET Core中如何利用Csp标头对抗Xss攻击
2020-11-27 14:43:08 责编:小采
文档


简而言之,CSP是网页控制允许加载哪些资源的一种方式。例如,页面可以显式声明允许从中加载JavaScript,CSS和图像资源。这有助于防止跨站点脚本(XSS)攻击等问题。

它也可用于协议,例如通过HTTPS加载的内容。CSP通过 Content-Security-Policy HTTP响应中的标头实现。

启用CSP,您需要配置Web服务器以返回Content-Security-Policy HTTP标头。那么在这篇文章中,我们将要尝试将CSP添加到ASP.NET Core应用程序中。

app.Use(async (ctx, next) =>
 {
 ctx.Response.Headers.Add("Content-Security-Policy",
 "default-src 'self'; report-uri /cspreport");
 await next();
 });

在Home/Index中引入cdn文件,然后我们启动项目,看看会发生什么!

运行并观察错误。加载页面时,浏览器拒绝从远程源加载。

 

所以我们可以组织CSP来控制我们的白名单,在配置当中需要填写来源以及内容,以下是常用的选项。

来源:

*: 允许任何网址。
‘self': 允许所提供页面的来源。请注意,单引号是必需的。
‘none': 不允许任何来源。请注意,单引号是必需的。
Host: 允许指定的互联网主机(按名称或IP地址)。通配符(星号字符)可用于包括所有子域,例如http://*.foo.com
‘unsafe-line': 允许内联脚本
‘nonce-[base-value]': 允许具有特定nonce的内联脚本(使用一次的数字)。对于每个HTTP请求/响应,应该对nonce进行加密和唯一。

 指令:

script-src:定义有效的JavaScript源
style-src:定义样式表的有效来源
img-src:定义有效的图像源
connect-src:定义可以进行AJAX调用的有效源
font-src:定义有效的字体来源
object-src:定义<object>,<embed>和<applet>元素的有效源
media-src:定义有效的音频和视频源
form-action:定义可用作HTML <form>操作的有效源。
default-src:指定加载内容的默认策略

我们可以在可重用的中间件中封装构建和添加CSP头。以下是一个让您入门的示例。你可以根据需要扩展它。首先,创建一个用于保存源的类。

public class CspOptions
 {
 public List<string> Defaults { get; set; } = new List<string>();
 public List<string> Scripts { get; set; } = new List<string>();
 public List<string> Styles { get; set; } = new List<string>();
 public List<string> Images { get; set; } = new List<string>();
 public List<string> Fonts { get; set; } = new List<string>();
 public List<string> Media { get; set; } = new List<string>();
 }

开发一个中间件一定是需要一个构造器的,这将用于.net core 的注入到运行环境中。

public sealed class CspOptionsBuilder 
 { 
 private readonly CspOptions options = new CspOptions(); 
 
 internal CspOptionsBuilder() { } 
 
 public CspDirectiveBuilder Defaults { get; set; } = new CspDirectiveBuilder(); 
 public CspDirectiveBuilder Scripts { get; set; } = new CspDirectiveBuilder(); 
 public CspDirectiveBuilder Styles { get; set; } = new CspDirectiveBuilder(); 
 public CspDirectiveBuilder Images { get; set; } = new CspDirectiveBuilder(); 
 public CspDirectiveBuilder Fonts { get; set; } = new CspDirectiveBuilder(); 
 public CspDirectiveBuilder Media { get; set; } = new CspDirectiveBuilder(); 
 
 internal CspOptions Build() 
 { 
 this.options.Defaults = this.Defaults.Sources; 
 this.options.Scripts = this.Scripts.Sources; 
 this.options.Styles = this.Styles.Sources; 
 this.options.Images = this.Images.Sources; 
 this.options.Fonts = this.Fonts.Sources; 
 this.options.Media = this.Media.Sources; 
 return this.options; 
 } 
 } 
 
 public sealed class CspDirectiveBuilder 
 { 
 internal CspDirectiveBuilder() { } 
 
 internal List<string> Sources { get; set; } = new List<string>(); 
 
 public CspDirectiveBuilder AllowSelf() => Allow("'self'"); 
 public CspDirectiveBuilder AllowNone() => Allow("none"); 
 public CspDirectiveBuilder AllowAny() => Allow("*"); 
 
 public CspDirectiveBuilder Allow(string source) 
 { 
 this.Sources.Add(source); 
 return this; 
 } 
 }

好了,我们创建一个中间件。

namespace XSSDefenses.XSSDefenses.MiddlerWare
{
 public sealed class CspOptionMiddlerWare
 {
 private const string HEADER = "Content-Security-Policy";
 private readonly RequestDelegate next;
 private readonly CspOptions options;

 public CspOptionMiddlerWare(
 RequestDelegate next, CspOptions options)
 {
 this.next = next;
 this.options = options;
 }

 public async Task Invoke(HttpContext context)
 {
 context.Response.Headers.Add(HEADER, GetHeaderValue());
 await this.next(context);
 }

 private string GetHeaderValue()
 {
 var value = "";
 value += GetDirective("default-src", this.options.Defaults);
 value += GetDirective("script-src", this.options.Scripts);
 value += GetDirective("style-src", this.options.Styles);
 value += GetDirective("img-src", this.options.Images);
 value += GetDirective("font-src", this.options.Fonts);
 value += GetDirective("media-src", this.options.Media);
 return value;
 }
 private string GetDirective(string directive, List<string> sources)
 => sources.Count > 0 ? $"{directive} {string.Join(" ", sources)}; " : "";
 }
}

以及设置它的扩展方法。

namespace XSSDefenses.XSSDefenses.Extensions
{
 public static class CspMiddlewareExtensions
 {
 public static IApplicationBuilder UseCsp(
 this IApplicationBuilder app, Action<CspOptionsBuilder> builder)
 {
 var newBuilder = new CspOptionsBuilder();
 builder(newBuilder);
 
 var options = newBuilder.Build();
 return app.UseMiddleware<CspOptionMiddlerWare>(options);
 }
 }
}

我们现在可以在Startup类中配置中间件。

app.UseCsp(builder =>
 {
 builder.Styles.AllowSelf()
 .Allow(@"https://ajax.aspnetcdn.com/");
 });

启动发现,观察网络资源。浏览器已经允许本地和远程资源。

总结

下载本文
显示全文
专题