-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #90 from atidev/UpdateXssAttribute
Update xss attribute
- Loading branch information
Showing
17 changed files
with
165 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
using System; | ||
using System.Net.Http; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 0 additions & 1 deletion
1
ATI.Services.Common/Metrics/MetricsStatusCodeCounterMiddleware.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using ATI.Services.Common.Behaviors; | ||
using Microsoft.AspNetCore.Mvc.Filters; | ||
|
||
namespace ATI.Services.Common.Xss.Attribute; | ||
|
||
static class XssAttributesHelper | ||
{ | ||
public static async Task FieldValidationAction(ActionExecutingContext context, ActionExecutionDelegate next, | ||
Func<string, bool> isXssInjectedFunc) | ||
{ | ||
var actionArguments = context.ActionArguments; | ||
|
||
foreach (var actionArgumentPair in actionArguments) | ||
{ | ||
var model = actionArgumentPair.Value; | ||
var modelType = model.GetType(); | ||
var properties = modelType.GetProperties() | ||
.Where(x => x.IsDefined(typeof(XssValidateAttribute), true)); | ||
|
||
foreach (var property in properties) | ||
{ | ||
var value = property.GetValue(model)?.ToString(); | ||
if (value == null) continue; | ||
|
||
if (isXssInjectedFunc(value)) | ||
{ | ||
context.Result = CommonBehavior.GetActionResult(ActionStatus.BadRequest, | ||
false, "XSS injection detected from property attribute."); | ||
return; | ||
} | ||
} | ||
} | ||
|
||
await next(); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
ATI.Services.Common/Xss/Attribute/XssFieldStrictValidationFilterAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc.Filters; | ||
|
||
namespace ATI.Services.Common.Xss.Attribute; | ||
|
||
public class XssFieldStrictValidationFilterAttribute : System.Attribute, IAsyncActionFilter | ||
{ | ||
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) | ||
{ | ||
await XssAttributesHelper.FieldValidationAction(context, next, XssHelper.IsStrictXssInjected); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
ATI.Services.Common/Xss/Attribute/XssInputStrictValidationFilterAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System; | ||
using System.Threading.Tasks; | ||
using ATI.Services.Common.Behaviors; | ||
using JetBrains.Annotations; | ||
using Microsoft.AspNetCore.Mvc.Filters; | ||
|
||
namespace ATI.Services.Common.Xss.Attribute; | ||
|
||
[PublicAPI] | ||
[AttributeUsage(AttributeTargets.Method)] | ||
public class XssInputStrictValidationFilterAttribute : System.Attribute, IAsyncResourceFilter | ||
{ | ||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) | ||
{ | ||
var httpContext = context.HttpContext; | ||
if (await XssHelper.IsStrictXssInjected(httpContext)) | ||
{ | ||
context.Result = CommonBehavior.GetActionResult(ActionStatus.BadRequest, | ||
false, "XSS injection detected from middleware."); | ||
} | ||
else | ||
{ | ||
await next(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,34 @@ | ||
using ATI.Services.Common.Xss.Attribute; | ||
using JetBrains.Annotations; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace ATI.Services.Common.Xss; | ||
|
||
[PublicAPI] | ||
public static class XssExtensions | ||
{ | ||
public static IApplicationBuilder UseXssValidation(this IApplicationBuilder builder) | ||
{ | ||
return builder.UseMiddleware<XssMiddleware>(); | ||
{ | ||
return builder.UseMiddleware<XssMiddleware>(); | ||
} | ||
|
||
public static IApplicationBuilder UseXssStrictValidation(this IApplicationBuilder builder) | ||
{ | ||
return builder.UseMiddleware<XssStrictMiddleware>(); | ||
} | ||
|
||
|
||
public static IMvcBuilder AddXssStrictValidationAttribute(this IServiceCollection services) | ||
{ | ||
return services.AddControllers(options => | ||
{ | ||
options.Filters.Add(typeof(XssFieldStrictValidationFilterAttribute)); | ||
}); | ||
} | ||
|
||
public static IMvcBuilder AddXssValidationAttribute(this IServiceCollection services) | ||
{ | ||
return services.AddControllers(options => | ||
{ | ||
options.Filters.Add(typeof(XssFieldValidationFilterAttribute)); | ||
}); | ||
return services.AddControllers( | ||
options => { options.Filters.Add(typeof(XssFieldValidationFilterAttribute)); }); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,66 @@ | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using AngleSharp.Css.Dom; | ||
using Ganss.Xss; | ||
using Microsoft.AspNetCore.Http; | ||
|
||
namespace ATI.Services.Common.Xss; | ||
|
||
public static class XssHelper | ||
{ | ||
private static readonly HtmlSanitizer Sanitizer = new(); | ||
|
||
private static readonly HtmlSanitizer DefaultSanitizer = new(); | ||
|
||
private static readonly HtmlSanitizer StrictSanitizer = new(new HtmlSanitizerOptions() | ||
{ | ||
AllowedTags = new HashSet<string>(), | ||
AllowedAttributes = new HashSet<string>(), | ||
AllowedCssProperties = new HashSet<string>(), | ||
AllowedSchemes = new HashSet<string>(), | ||
UriAttributes = HtmlSanitizerDefaults.UriAttributes, | ||
AllowedAtRules = new HashSet<CssRuleType>(), | ||
AllowedCssClasses = new HashSet<string>() | ||
}); | ||
|
||
|
||
public static bool IsXssInjected(string rawText) | ||
{ | ||
var sanitised = Sanitizer.Sanitize(rawText); | ||
var sanitised = DefaultSanitizer.Sanitize(rawText); | ||
return !rawText.Equals(sanitised); | ||
} | ||
|
||
public static bool IsStrictXssInjected(string rawText) | ||
{ | ||
var sanitised = StrictSanitizer.Sanitize(rawText); | ||
return !rawText.Equals(sanitised); | ||
} | ||
|
||
public static async Task<bool> IsXssInjected(HttpContext httpContext) | ||
{ | ||
var raw = await GetStringsFromHttpContext(httpContext); | ||
return IsXssInjected(raw); | ||
} | ||
|
||
public static async Task<bool> IsStrictXssInjected(HttpContext httpContext) | ||
{ | ||
var raw = await GetStringsFromHttpContext(httpContext); | ||
return IsStrictXssInjected(raw); | ||
} | ||
|
||
private static async Task<string> GetStringsFromHttpContext(HttpContext httpContext) | ||
{ | ||
// enable buffering so that the request can be read by the model binders next | ||
httpContext.Request.EnableBuffering(); | ||
|
||
// leaveOpen: true to leave the stream open after disposing, | ||
// so it can be read by the model binders | ||
using var streamReader = new StreamReader(httpContext.Request.Body, Encoding.UTF8, leaveOpen: true); | ||
|
||
var raw = await streamReader.ReadToEndAsync(); | ||
// rewind the stream for the next middleware | ||
httpContext.Request.Body.Seek(0, SeekOrigin.Begin); | ||
return IsXssInjected(raw); | ||
|
||
return raw; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using System.Net; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Http; | ||
|
||
namespace ATI.Services.Common.Xss; | ||
|
||
public class XssStrictMiddleware(RequestDelegate next) | ||
{ | ||
public async Task InvokeAsync(HttpContext httpContext) | ||
{ | ||
if (await XssHelper.IsStrictXssInjected(httpContext)) | ||
{ | ||
httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; | ||
await httpContext.Response.WriteAsync("XSS injection detected from middleware."); | ||
} | ||
else | ||
{ | ||
await next(httpContext); | ||
} | ||
} | ||
} |